summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bullet/bullet_physics_server.cpp12
-rw-r--r--modules/bullet/bullet_physics_server.h3
-rw-r--r--modules/bullet/godot_result_callbacks.cpp51
-rw-r--r--modules/bullet/godot_result_callbacks.h44
-rw-r--r--modules/bullet/shape_bullet.cpp45
-rw-r--r--modules/bullet/shape_bullet.h24
-rw-r--r--modules/bullet/space_bullet.cpp26
-rw-r--r--modules/bullet/space_bullet.h12
-rw-r--r--modules/cvtt/SCsub21
-rw-r--r--modules/cvtt/config.py5
-rw-r--r--modules/cvtt/image_compress_cvtt.cpp394
-rw-r--r--modules/cvtt/image_compress_cvtt.h39
-rw-r--r--modules/cvtt/register_types.cpp45
-rw-r--r--modules/cvtt/register_types.h34
-rw-r--r--modules/gdnative/gdnative_api.json8
-rw-r--r--modules/gdnative/include/nativescript/godot_nativescript.h2
-rw-r--r--modules/gdnative/nativescript/godot_nativescript.cpp4
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp110
-rw-r--r--modules/gdnative/nativescript/nativescript.h18
-rw-r--r--modules/gdscript/gdscript.cpp8
-rw-r--r--modules/gdscript/gdscript_compiler.cpp6
-rw-r--r--modules/gdscript/gdscript_parser.cpp28
-rw-r--r--modules/gdscript/gdscript_tokenizer.h10
-rw-r--r--modules/gridmap/grid_map.cpp72
-rw-r--r--modules/gridmap/grid_map.h7
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp147
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h16
-rw-r--r--modules/mono/glue/cs_files/Color.cs5
-rw-r--r--modules/mono/glue/cs_files/Plane.cs9
-rw-r--r--modules/mono/glue/cs_files/Rect2.cs121
-rw-r--r--modules/mono/glue/cs_files/Vector2.cs5
-rw-r--r--modules/mono/glue/cs_files/Vector3.cs5
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp76
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h3
-rw-r--r--modules/mono/utils/thread_local.cpp4
-rw-r--r--modules/mono/utils/thread_local.h3
-rw-r--r--modules/squish/image_compress_squish.cpp14
-rw-r--r--modules/squish/image_compress_squish.h2
38 files changed, 1189 insertions, 249 deletions
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
index 0139842470..70f70e7e5f 100644
--- a/modules/bullet/bullet_physics_server.cpp
+++ b/modules/bullet/bullet_physics_server.cpp
@@ -163,6 +163,18 @@ Variant BulletPhysicsServer::shape_get_data(RID p_shape) const {
return shape->get_data();
}
+void BulletPhysicsServer::shape_set_margin(RID p_shape, real_t p_margin) {
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND(!shape);
+ shape->set_margin(p_margin);
+}
+
+real_t BulletPhysicsServer::shape_get_margin(RID p_shape) const {
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND_V(!shape, 0.0);
+ return shape->get_margin();
+}
+
real_t BulletPhysicsServer::shape_get_custom_solver_bias(RID p_shape) const {
//WARN_PRINT("Bias not supported by Bullet physics engine");
return 0.;
diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h
index 76716f1d1b..e9c568d605 100644
--- a/modules/bullet/bullet_physics_server.h
+++ b/modules/bullet/bullet_physics_server.h
@@ -99,6 +99,9 @@ public:
virtual ShapeType shape_get_type(RID p_shape) const;
virtual Variant shape_get_data(RID p_shape) const;
+ virtual void shape_set_margin(RID p_shape, real_t p_margin);
+ virtual real_t shape_get_margin(RID p_shape) const;
+
/// Not supported
virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias);
/// Not supported
diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp
index 85178bf83c..534034d707 100644
--- a/modules/bullet/godot_result_callbacks.cpp
+++ b/modules/bullet/godot_result_callbacks.cpp
@@ -30,6 +30,7 @@
#include "godot_result_callbacks.h"
+#include "area_bullet.h"
#include "bullet_types_converter.h"
#include "collision_object_bullet.h"
#include "rigid_body_bullet.h"
@@ -51,11 +52,23 @@ bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) co
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+
+ if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) {
+ if (!collide_with_areas)
+ return false;
+ } else {
+ if (!collide_with_bodies)
+ return false;
+ }
+
if (m_pickRay && !gObj->is_ray_pickable()) {
return false;
- } else if (m_exclude->has(gObj->get_self())) {
+ }
+
+ if (m_exclude->has(gObj->get_self())) {
return false;
}
+
return true;
} else {
return false;
@@ -124,6 +137,15 @@ bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0)
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+
+ if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) {
+ if (!collide_with_areas)
+ return false;
+ } else {
+ if (!collide_with_bodies)
+ return false;
+ }
+
if (m_exclude->has(gObj->get_self())) {
return false;
}
@@ -144,6 +166,15 @@ bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) co
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+
+ if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) {
+ if (!collide_with_areas)
+ return false;
+ } else {
+ if (!collide_with_bodies)
+ return false;
+ }
+
if (m_exclude->has(gObj->get_self())) {
return false;
}
@@ -189,6 +220,15 @@ bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *pr
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+
+ if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) {
+ if (!collide_with_areas)
+ return false;
+ } else {
+ if (!collide_with_bodies)
+ return false;
+ }
+
if (m_exclude->has(gObj->get_self())) {
return false;
}
@@ -218,6 +258,15 @@ bool GodotRestInfoContactResultCallback::needsCollision(btBroadphaseProxy *proxy
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+
+ if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) {
+ if (!collide_with_areas)
+ return false;
+ } else {
+ if (!collide_with_bodies)
+ return false;
+ }
+
if (m_exclude->has(gObj->get_self())) {
return false;
}
diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h
index 363051f24c..3948f43c00 100644
--- a/modules/bullet/godot_result_callbacks.h
+++ b/modules/bullet/godot_result_callbacks.h
@@ -56,12 +56,17 @@ struct GodotClosestRayResultCallback : public btCollisionWorld::ClosestRayResult
bool m_pickRay;
int m_shapeId;
+ bool collide_with_bodies;
+ bool collide_with_areas;
+
public:
- GodotClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const Set<RID> *p_exclude) :
+ GodotClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld),
m_exclude(p_exclude),
m_pickRay(false),
- m_shapeId(0) {}
+ m_shapeId(0),
+ collide_with_bodies(p_collide_with_bodies),
+ collide_with_areas(p_collide_with_areas) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
@@ -108,9 +113,14 @@ public:
const Set<RID> *m_exclude;
int m_shapeId;
- GodotClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const Set<RID> *p_exclude) :
+ bool collide_with_bodies;
+ bool collide_with_areas;
+
+ GodotClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld),
- m_exclude(p_exclude) {}
+ m_exclude(p_exclude),
+ collide_with_bodies(p_collide_with_bodies),
+ collide_with_areas(p_collide_with_areas) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
@@ -125,12 +135,17 @@ public:
int m_count;
const Set<RID> *m_exclude;
- GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude) :
+ bool collide_with_bodies;
+ bool collide_with_areas;
+
+ GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
m_self_object(p_self_object),
m_results(p_results),
m_exclude(p_exclude),
m_resultMax(p_resultMax),
- m_count(0) {}
+ m_count(0),
+ collide_with_bodies(p_collide_with_bodies),
+ collide_with_areas(p_collide_with_areas) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
@@ -146,12 +161,17 @@ public:
int m_count;
const Set<RID> *m_exclude;
- GodotContactPairContactResultCallback(btCollisionObject *p_self_object, Vector3 *p_results, int p_resultMax, const Set<RID> *p_exclude) :
+ bool collide_with_bodies;
+ bool collide_with_areas;
+
+ GodotContactPairContactResultCallback(btCollisionObject *p_self_object, Vector3 *p_results, int p_resultMax, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
m_self_object(p_self_object),
m_results(p_results),
m_exclude(p_exclude),
m_resultMax(p_resultMax),
- m_count(0) {}
+ m_count(0),
+ collide_with_bodies(p_collide_with_bodies),
+ collide_with_areas(p_collide_with_areas) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
@@ -167,13 +187,17 @@ public:
const btCollisionObject *m_rest_info_collision_object;
btVector3 m_rest_info_bt_point;
const Set<RID> *m_exclude;
+ bool collide_with_bodies;
+ bool collide_with_areas;
- GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeRestInfo *p_result, const Set<RID> *p_exclude) :
+ GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeRestInfo *p_result, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
m_self_object(p_self_object),
m_result(p_result),
m_exclude(p_exclude),
m_collided(false),
- m_min_distance(0) {}
+ m_min_distance(0),
+ collide_with_bodies(p_collide_with_bodies),
+ collide_with_areas(p_collide_with_areas) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index e4c1a5f9b5..fab8d0cf3d 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -44,19 +44,20 @@
@author AndreaCatania
*/
-ShapeBullet::ShapeBullet() {}
+ShapeBullet::ShapeBullet() :
+ margin(0.04) {}
ShapeBullet::~ShapeBullet() {}
-btCollisionShape *ShapeBullet::create_bt_shape(const Vector3 &p_implicit_scale, real_t p_margin) {
+btCollisionShape *ShapeBullet::create_bt_shape(const Vector3 &p_implicit_scale, real_t p_extra_edge) {
btVector3 s;
G_TO_B(p_implicit_scale, s);
- return create_bt_shape(s, p_margin);
+ return create_bt_shape(s, p_extra_edge);
}
btCollisionShape *ShapeBullet::prepare(btCollisionShape *p_btShape) const {
p_btShape->setUserPointer(const_cast<ShapeBullet *>(this));
- p_btShape->setMargin(0.);
+ p_btShape->setMargin(margin);
return p_btShape;
}
@@ -93,6 +94,15 @@ const Map<ShapeOwnerBullet *, int> &ShapeBullet::get_owners() const {
return owners;
}
+void ShapeBullet::set_margin(real_t p_margin) {
+ margin = p_margin;
+ notifyShapeChanged();
+}
+
+real_t ShapeBullet::get_margin() const {
+ return margin;
+}
+
btEmptyShape *ShapeBullet::create_shape_empty() {
return bulletnew(btEmptyShape);
}
@@ -166,7 +176,7 @@ void PlaneShapeBullet::setup(const Plane &p_plane) {
notifyShapeChanged();
}
-btCollisionShape *PlaneShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
+btCollisionShape *PlaneShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
btVector3 btPlaneNormal;
G_TO_B(plane.normal, btPlaneNormal);
return prepare(PlaneShapeBullet::create_shape_plane(btPlaneNormal, plane.d));
@@ -194,8 +204,8 @@ void SphereShapeBullet::setup(real_t p_radius) {
notifyShapeChanged();
}
-btCollisionShape *SphereShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
- return prepare(ShapeBullet::create_shape_sphere(radius * p_implicit_scale[0] + p_margin));
+btCollisionShape *SphereShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
+ return prepare(ShapeBullet::create_shape_sphere(radius * p_implicit_scale[0] + p_extra_edge));
}
/* Box */
@@ -221,8 +231,8 @@ void BoxShapeBullet::setup(const Vector3 &p_half_extents) {
notifyShapeChanged();
}
-btCollisionShape *BoxShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
- return prepare(ShapeBullet::create_shape_box((half_extents * p_implicit_scale) + btVector3(p_margin, p_margin, p_margin)));
+btCollisionShape *BoxShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
+ return prepare(ShapeBullet::create_shape_box((half_extents * p_implicit_scale) + btVector3(p_extra_edge, p_extra_edge, p_extra_edge)));
}
/* Capsule */
@@ -254,8 +264,8 @@ void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) {
notifyShapeChanged();
}
-btCollisionShape *CapsuleShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
- return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_margin, height * p_implicit_scale[1] + p_margin));
+btCollisionShape *CapsuleShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
+ return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_extra_edge, height * p_implicit_scale[1] + p_extra_edge));
}
/* Cylinder */
@@ -329,11 +339,10 @@ void ConvexPolygonShapeBullet::setup(const Vector<Vector3> &p_vertices) {
notifyShapeChanged();
}
-btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
+btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
btCollisionShape *cs(ShapeBullet::create_shape_convex(vertices));
cs->setLocalScaling(p_implicit_scale);
prepare(cs);
- cs->setMargin(p_margin);
return cs;
}
@@ -402,14 +411,13 @@ void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) {
notifyShapeChanged();
}
-btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
+btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
btCollisionShape *cs = ShapeBullet::create_shape_concave(meshShape);
if (!cs)
// This is necessary since if 0 faces the creation of concave return NULL
cs = ShapeBullet::create_shape_empty();
cs->setLocalScaling(p_implicit_scale);
prepare(cs);
- cs->setMargin(p_margin);
return cs;
}
@@ -495,11 +503,10 @@ void HeightMapShapeBullet::setup(PoolVector<real_t> &p_heights, int p_width, int
notifyShapeChanged();
}
-btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
+btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
btCollisionShape *cs(ShapeBullet::create_shape_height_field(heights, width, depth, min_height, max_height));
cs->setLocalScaling(p_implicit_scale);
prepare(cs);
- cs->setMargin(p_margin);
return cs;
}
@@ -533,6 +540,6 @@ void RayShapeBullet::setup(real_t p_length, bool p_slips_on_slope) {
notifyShapeChanged();
}
-btCollisionShape *RayShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
- return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_margin, slips_on_slope));
+btCollisionShape *RayShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
+ return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_extra_edge, slips_on_slope));
}
diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h
index 16a5ac1fc6..638e044e6a 100644
--- a/modules/bullet/shape_bullet.h
+++ b/modules/bullet/shape_bullet.h
@@ -52,6 +52,7 @@ class btBvhTriangleMeshShape;
class ShapeBullet : public RIDBullet {
Map<ShapeOwnerBullet *, int> owners;
+ real_t margin;
protected:
/// return self
@@ -62,14 +63,17 @@ public:
ShapeBullet();
virtual ~ShapeBullet();
- btCollisionShape *create_bt_shape(const Vector3 &p_implicit_scale, real_t p_margin = 0);
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0) = 0;
+ btCollisionShape *create_bt_shape(const Vector3 &p_implicit_scale, real_t p_extra_edge = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0) = 0;
void add_owner(ShapeOwnerBullet *p_owner);
void remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFromThisBody = false);
bool is_owner(ShapeOwnerBullet *p_owner) const;
const Map<ShapeOwnerBullet *, int> &get_owners() const;
+ void set_margin(real_t p_margin);
+ real_t get_margin() const;
+
/// Setup the shape
virtual void set_data(const Variant &p_data) = 0;
virtual Variant get_data() const = 0;
@@ -100,7 +104,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(const Plane &p_plane);
@@ -117,7 +121,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(real_t p_radius);
@@ -134,7 +138,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(const Vector3 &p_half_extents);
@@ -153,7 +157,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(real_t p_height, real_t p_radius);
@@ -189,7 +193,7 @@ public:
void get_vertices(Vector<Vector3> &out_vertices);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(const Vector<Vector3> &p_vertices);
@@ -207,7 +211,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(PoolVector<Vector3> p_faces);
@@ -227,7 +231,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
@@ -244,7 +248,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(real_t p_length, bool p_slips_on_slope);
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index e1a4e88db0..b5329bc347 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -61,7 +61,7 @@ BulletPhysicsDirectSpaceState::BulletPhysicsDirectSpaceState(SpaceBullet *p_spac
PhysicsDirectSpaceState(),
space(p_space) {}
-int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask) {
+int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0)
return 0;
@@ -69,13 +69,13 @@ int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, Shape
btVector3 bt_point;
G_TO_B(p_point, bt_point);
- btSphereShape sphere_point(0.f);
+ btSphereShape sphere_point(0.001f);
btCollisionObject collision_object_point;
collision_object_point.setCollisionShape(&sphere_point);
collision_object_point.setWorldTransform(btTransform(btQuaternion::getIdentity(), bt_point));
// Setup query
- GodotAllContactResultCallback btResult(&collision_object_point, r_results, p_result_max, &p_exclude);
+ GodotAllContactResultCallback btResult(&collision_object_point, r_results, p_result_max, &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btResult.m_collisionFilterGroup = 0;
btResult.m_collisionFilterMask = p_collision_mask;
space->dynamicsWorld->contactTest(&collision_object_point, btResult);
@@ -84,7 +84,7 @@ int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, Shape
return btResult.m_count;
}
-bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_pick_ray) {
+bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) {
btVector3 btVec_from;
btVector3 btVec_to;
@@ -93,7 +93,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V
G_TO_B(p_to, btVec_to);
// setup query
- GodotClosestRayResultCallback btResult(btVec_from, btVec_to, &p_exclude);
+ GodotClosestRayResultCallback btResult(btVec_from, btVec_to, &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btResult.m_collisionFilterGroup = 0;
btResult.m_collisionFilterMask = p_collision_mask;
btResult.m_pickRay = p_pick_ray;
@@ -117,7 +117,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V
}
}
-int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask) {
+int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0)
return 0;
@@ -139,7 +139,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra
collision_object.setCollisionShape(btConvex);
collision_object.setWorldTransform(bt_xform);
- GodotAllContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude);
+ GodotAllContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btQuery.m_collisionFilterGroup = 0;
btQuery.m_collisionFilterMask = p_collision_mask;
btQuery.m_closestDistanceThreshold = 0;
@@ -150,7 +150,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra
return btQuery.m_count;
}
-bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, ShapeRestInfo *r_info) {
+bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape);
btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale(), p_margin);
@@ -171,7 +171,7 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf
btTransform bt_xform_to(bt_xform_from);
bt_xform_to.getOrigin() += bt_motion;
- GodotClosestConvexResultCallback btResult(bt_xform_from.getOrigin(), bt_xform_to.getOrigin(), &p_exclude);
+ GodotClosestConvexResultCallback btResult(bt_xform_from.getOrigin(), bt_xform_to.getOrigin(), &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btResult.m_collisionFilterGroup = 0;
btResult.m_collisionFilterMask = p_collision_mask;
@@ -197,7 +197,7 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf
}
/// Returns the list of contacts pairs in this order: Local contact, other body contact
-bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask) {
+bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0)
return 0;
@@ -219,7 +219,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &
collision_object.setCollisionShape(btConvex);
collision_object.setWorldTransform(bt_xform);
- GodotContactPairContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude);
+ GodotContactPairContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btQuery.m_collisionFilterGroup = 0;
btQuery.m_collisionFilterMask = p_collision_mask;
btQuery.m_closestDistanceThreshold = 0;
@@ -231,7 +231,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &
return btQuery.m_count;
}
-bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask) {
+bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape);
@@ -251,7 +251,7 @@ bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_sh
collision_object.setCollisionShape(btConvex);
collision_object.setWorldTransform(bt_xform);
- GodotRestInfoContactResultCallback btQuery(&collision_object, r_info, &p_exclude);
+ GodotRestInfoContactResultCallback btQuery(&collision_object, r_info, &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btQuery.m_collisionFilterGroup = 0;
btQuery.m_collisionFilterMask = p_collision_mask;
btQuery.m_closestDistanceThreshold = 0;
diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h
index 95814d1fef..517ec67ffa 100644
--- a/modules/bullet/space_bullet.h
+++ b/modules/bullet/space_bullet.h
@@ -73,13 +73,13 @@ private:
public:
BulletPhysicsDirectSpaceState(SpaceBullet *p_space);
- virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF);
- virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_pick_ray = false);
- virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF);
- virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, ShapeRestInfo *r_info = NULL);
+ virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false);
+ virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = NULL);
/// Returns the list of contacts pairs in this order: Local contact, other body contact
- virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF);
- virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF);
+ virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const;
};
diff --git a/modules/cvtt/SCsub b/modules/cvtt/SCsub
new file mode 100644
index 0000000000..5c396482aa
--- /dev/null
+++ b/modules/cvtt/SCsub
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+Import('env')
+Import('env_modules')
+
+env_cvtt = env_modules.Clone()
+
+# Thirdparty source files
+if env['builtin_squish']:
+ thirdparty_dir = "#thirdparty/cvtt/"
+ thirdparty_sources = [
+ "ConvectionKernels.cpp"
+ ]
+
+ thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
+
+ env_cvtt.add_source_files(env.modules_sources, thirdparty_sources)
+ env_cvtt.Append(CPPPATH=[thirdparty_dir])
+
+# Godot source files
+env_cvtt.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/cvtt/config.py b/modules/cvtt/config.py
new file mode 100644
index 0000000000..098f1eafa9
--- /dev/null
+++ b/modules/cvtt/config.py
@@ -0,0 +1,5 @@
+def can_build(env, platform):
+ return env['tools']
+
+def configure(env):
+ pass
diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp
new file mode 100644
index 0000000000..3a371c8597
--- /dev/null
+++ b/modules/cvtt/image_compress_cvtt.cpp
@@ -0,0 +1,394 @@
+/*************************************************************************/
+/* image_compress_cvtt.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 "image_compress_cvtt.h"
+
+#include "os/os.h"
+#include "os/thread.h"
+#include "print_string.h"
+
+#include <ConvectionKernels.h>
+
+struct CVTTCompressionJobParams {
+ bool is_hdr;
+ bool is_signed;
+ int bytes_per_pixel;
+
+ cvtt::Options options;
+};
+
+struct CVTTCompressionRowTask {
+ const uint8_t *in_mm_bytes;
+ uint8_t *out_mm_bytes;
+ int y_start;
+ int width;
+ int height;
+};
+
+struct CVTTCompressionJobQueue {
+ CVTTCompressionJobParams job_params;
+ const CVTTCompressionRowTask *job_tasks;
+ uint32_t num_tasks;
+ uint32_t current_task;
+};
+
+static void _digest_row_task(const CVTTCompressionJobParams &p_job_params, const CVTTCompressionRowTask &p_row_task) {
+ const uint8_t *in_bytes = p_row_task.in_mm_bytes;
+ uint8_t *out_bytes = p_row_task.out_mm_bytes;
+ int w = p_row_task.width;
+ int h = p_row_task.height;
+
+ int y_start = p_row_task.y_start;
+ int y_end = y_start + 4;
+
+ int bytes_per_pixel = p_job_params.bytes_per_pixel;
+ bool is_hdr = p_job_params.is_hdr;
+ bool is_signed = p_job_params.is_signed;
+
+ cvtt::PixelBlockU8 input_blocks_ldr[cvtt::NumParallelBlocks];
+ cvtt::PixelBlockF16 input_blocks_hdr[cvtt::NumParallelBlocks];
+
+ for (int x_start = 0; x_start < w; x_start += 4 * cvtt::NumParallelBlocks) {
+ int x_end = x_start + 4 * cvtt::NumParallelBlocks;
+
+ for (int y = y_start; y < y_end; y++) {
+ int first_input_element = (y - y_start) * 4;
+ const uint8_t *row_start;
+ if (y >= h) {
+ row_start = in_bytes + (h - 1) * (w * bytes_per_pixel);
+ } else {
+ row_start = in_bytes + y * (w * bytes_per_pixel);
+ }
+
+ for (int x = x_start; x < x_end; x++) {
+ const uint8_t *pixel_start;
+ if (x >= w) {
+ pixel_start = row_start + (w - 1) * bytes_per_pixel;
+ } else {
+ pixel_start = row_start + x * bytes_per_pixel;
+ }
+
+ int block_index = (x - x_start) / 4;
+ int block_element = (x - x_start) % 4 + first_input_element;
+ if (is_hdr) {
+ memcpy(input_blocks_hdr[block_index].m_pixels[block_element], pixel_start, bytes_per_pixel);
+ input_blocks_hdr[block_index].m_pixels[block_element][3] = 0x3c00; // 1.0 (unused)
+ } else {
+ memcpy(input_blocks_ldr[block_index].m_pixels[block_element], pixel_start, bytes_per_pixel);
+ }
+ }
+ }
+
+ uint8_t output_blocks[16 * cvtt::NumParallelBlocks];
+
+ if (is_hdr) {
+ if (is_signed) {
+ cvtt::Kernels::EncodeBC6HS(output_blocks, input_blocks_hdr, p_job_params.options);
+ } else {
+ cvtt::Kernels::EncodeBC6HU(output_blocks, input_blocks_hdr, p_job_params.options);
+ }
+ } else {
+ cvtt::Kernels::EncodeBC7(output_blocks, input_blocks_ldr, p_job_params.options);
+ }
+
+ int num_real_blocks = ((w - x_start) + 3) / 4;
+ if (num_real_blocks > cvtt::NumParallelBlocks) {
+ num_real_blocks = cvtt::NumParallelBlocks;
+ }
+
+ memcpy(out_bytes, output_blocks, 16 * num_real_blocks);
+ out_bytes += 16 * num_real_blocks;
+ }
+}
+
+static void _digest_job_queue(void *p_job_queue) {
+ CVTTCompressionJobQueue *job_queue = static_cast<CVTTCompressionJobQueue *>(p_job_queue);
+
+ for (int next_task = atomic_increment(&job_queue->current_task); next_task <= job_queue->num_tasks; next_task = atomic_increment(&job_queue->current_task)) {
+ _digest_row_task(job_queue->job_params, job_queue->job_tasks[next_task - 1]);
+ }
+}
+
+void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressSource p_source) {
+
+ if (p_image->get_format() >= Image::FORMAT_BPTC_RGBA)
+ return; //do not compress, already compressed
+
+ int w = p_image->get_width();
+ int h = p_image->get_height();
+
+ bool is_ldr = (p_image->get_format() <= Image::FORMAT_RGBA8);
+ bool is_hdr = (p_image->get_format() == Image::FORMAT_RGBH);
+
+ if (!is_ldr && !is_hdr) {
+ return; // Not a usable source format
+ }
+
+ cvtt::Options options;
+ uint32_t flags = cvtt::Flags::Fastest;
+
+ if (p_lossy_quality > 0.85)
+ flags = cvtt::Flags::Ultra;
+ else if (p_lossy_quality > 0.75)
+ flags = cvtt::Flags::Better;
+ else if (p_lossy_quality > 0.55)
+ flags = cvtt::Flags::Default;
+ else if (p_lossy_quality > 0.35)
+ flags = cvtt::Flags::Fast;
+ else if (p_lossy_quality > 0.15)
+ flags = cvtt::Flags::Faster;
+
+ flags |= cvtt::Flags::BC7_RespectPunchThrough;
+
+ if (p_source == Image::COMPRESS_SOURCE_NORMAL) {
+ flags |= cvtt::Flags::Uniform;
+ }
+
+ Image::Format target_format = Image::FORMAT_BPTC_RGBA;
+
+ bool is_signed = false;
+ if (is_hdr) {
+ PoolVector<uint8_t>::Read rb = p_image->get_data().read();
+
+ const uint16_t *source_data = reinterpret_cast<const uint16_t *>(&rb[0]);
+ int pixel_element_count = w * h * 3;
+ for (int i = 0; i < pixel_element_count; i++) {
+ if ((source_data[i] & 0x8000) != 0 && (source_data[i] & 0x7fff) != 0) {
+ is_signed = true;
+ break;
+ }
+ }
+
+ target_format = is_signed ? Image::FORMAT_BPTC_RGBF : Image::FORMAT_BPTC_RGBFU;
+ } else {
+ p_image->convert(Image::FORMAT_RGBA8); //still uses RGBA to convert
+ }
+
+ PoolVector<uint8_t>::Read rb = p_image->get_data().read();
+
+ PoolVector<uint8_t> data;
+ int target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps());
+ int mm_count = p_image->has_mipmaps() ? Image::get_image_required_mipmaps(w, h, target_format) : 0;
+ data.resize(target_size);
+ int shift = Image::get_format_pixel_rshift(target_format);
+
+ PoolVector<uint8_t>::Write wb = data.write();
+
+ int dst_ofs = 0;
+
+ CVTTCompressionJobQueue job_queue;
+ job_queue.job_params.is_hdr = is_hdr;
+ job_queue.job_params.is_signed = is_signed;
+ job_queue.job_params.options = options;
+ job_queue.job_params.bytes_per_pixel = is_hdr ? 6 : 4;
+
+#ifdef NO_THREADS
+ int num_job_threads = 0;
+#else
+ int num_job_threads = OS::get_singleton()->can_use_threads() ? (OS::get_singleton()->get_processor_count() - 1) : 0;
+#endif
+
+ PoolVector<CVTTCompressionRowTask> tasks;
+
+ for (int i = 0; i <= mm_count; i++) {
+
+ int bw = w % 4 != 0 ? w + (4 - w % 4) : w;
+ int bh = h % 4 != 0 ? h + (4 - h % 4) : h;
+
+ int src_ofs = p_image->get_mipmap_offset(i);
+
+ const uint8_t *in_bytes = &rb[src_ofs];
+ uint8_t *out_bytes = &wb[dst_ofs];
+
+ for (int y_start = 0; y_start < h; y_start += 4) {
+ int y_end = y_start + 4;
+
+ CVTTCompressionRowTask row_task;
+ row_task.width = w;
+ row_task.height = h;
+ row_task.y_start = y_start;
+ row_task.in_mm_bytes = in_bytes;
+ row_task.out_mm_bytes = out_bytes;
+
+ if (num_job_threads > 0) {
+ tasks.push_back(row_task);
+ } else {
+ _digest_row_task(job_queue.job_params, row_task);
+ }
+
+ out_bytes += 16 * (bw / 4);
+ }
+
+ dst_ofs += (MAX(4, bw) * MAX(4, bh)) >> shift;
+ w >>= 1;
+ h >>= 1;
+ }
+
+ if (num_job_threads > 0) {
+ PoolVector<Thread *> threads;
+ threads.resize(num_job_threads);
+
+ PoolVector<Thread *>::Write threads_wb = threads.write();
+
+ PoolVector<CVTTCompressionRowTask>::Read tasks_rb = tasks.read();
+
+ job_queue.job_tasks = &tasks_rb[0];
+ job_queue.current_task = 0;
+ job_queue.num_tasks = static_cast<uint32_t>(tasks.size());
+
+ for (int i = 0; i < num_job_threads; i++) {
+ threads_wb[i] = Thread::create(_digest_job_queue, &job_queue);
+ }
+ _digest_job_queue(&job_queue);
+
+ for (int i = 0; i < num_job_threads; i++) {
+ Thread::wait_to_finish(threads_wb[i]);
+ memdelete(threads_wb[i]);
+ }
+ }
+
+ p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
+}
+
+void image_decompress_cvtt(Image *p_image) {
+
+ Image::Format target_format;
+ bool is_signed = false;
+ bool is_hdr = false;
+
+ Image::Format input_format = p_image->get_format();
+
+ switch (input_format) {
+ case Image::FORMAT_BPTC_RGBA:
+ target_format = Image::FORMAT_RGBA8;
+ break;
+ case Image::FORMAT_BPTC_RGBF:
+ case Image::FORMAT_BPTC_RGBFU:
+ target_format = Image::FORMAT_RGBH;
+ is_signed = (input_format == Image::FORMAT_BPTC_RGBF);
+ is_hdr = true;
+ break;
+ default:
+ return; // Invalid input format
+ };
+
+ int w = p_image->get_width();
+ int h = p_image->get_height();
+
+ PoolVector<uint8_t>::Read rb = p_image->get_data().read();
+
+ PoolVector<uint8_t> data;
+ int target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps());
+ int mm_count = p_image->get_mipmap_count();
+ data.resize(target_size);
+ int shift = Image::get_format_pixel_rshift(target_format);
+
+ PoolVector<uint8_t>::Write wb = data.write();
+
+ int bytes_per_pixel = is_hdr ? 6 : 4;
+
+ int dst_ofs = 0;
+
+ for (int i = 0; i <= mm_count; i++) {
+
+ int src_ofs = p_image->get_mipmap_offset(i);
+
+ const uint8_t *in_bytes = &rb[src_ofs];
+ uint8_t *out_bytes = &wb[dst_ofs];
+
+ cvtt::PixelBlockU8 output_blocks_ldr[cvtt::NumParallelBlocks];
+ cvtt::PixelBlockF16 output_blocks_hdr[cvtt::NumParallelBlocks];
+
+ for (int y_start = 0; y_start < h; y_start += 4) {
+ int y_end = y_start + 4;
+
+ for (int x_start = 0; x_start < w; x_start += 4 * cvtt::NumParallelBlocks) {
+ int x_end = x_start + 4 * cvtt::NumParallelBlocks;
+
+ uint8_t input_blocks[16 * cvtt::NumParallelBlocks];
+ memset(input_blocks, 0, sizeof(input_blocks));
+
+ int num_real_blocks = ((w - x_start) + 3) / 4;
+ if (num_real_blocks > cvtt::NumParallelBlocks) {
+ num_real_blocks = cvtt::NumParallelBlocks;
+ }
+
+ memcpy(input_blocks, in_bytes, 16 * num_real_blocks);
+ in_bytes += 16 * num_real_blocks;
+
+ if (is_hdr) {
+ if (is_signed) {
+ cvtt::Kernels::DecodeBC6HS(output_blocks_hdr, input_blocks);
+ } else {
+ cvtt::Kernels::DecodeBC6HU(output_blocks_hdr, input_blocks);
+ }
+ } else {
+ cvtt::Kernels::DecodeBC7(output_blocks_ldr, input_blocks);
+ }
+
+ for (int y = y_start; y < y_end; y++) {
+ int first_input_element = (y - y_start) * 4;
+ uint8_t *row_start;
+ if (y >= h) {
+ row_start = out_bytes + (h - 1) * (w * bytes_per_pixel);
+ } else {
+ row_start = out_bytes + y * (w * bytes_per_pixel);
+ }
+
+ for (int x = x_start; x < x_end; x++) {
+ uint8_t *pixel_start;
+ if (x >= w) {
+ pixel_start = row_start + (w - 1) * bytes_per_pixel;
+ } else {
+ pixel_start = row_start + x * bytes_per_pixel;
+ }
+
+ int block_index = (x - x_start) / 4;
+ int block_element = (x - x_start) % 4 + first_input_element;
+ if (is_hdr) {
+ memcpy(pixel_start, output_blocks_hdr[block_index].m_pixels[block_element], bytes_per_pixel);
+ } else {
+ memcpy(pixel_start, output_blocks_ldr[block_index].m_pixels[block_element], bytes_per_pixel);
+ }
+ }
+ }
+ }
+ }
+
+ dst_ofs += w * h * bytes_per_pixel;
+ w >>= 1;
+ h >>= 1;
+ }
+
+ rb = PoolVector<uint8_t>::Read();
+ wb = PoolVector<uint8_t>::Write();
+
+ p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
+}
diff --git a/modules/cvtt/image_compress_cvtt.h b/modules/cvtt/image_compress_cvtt.h
new file mode 100644
index 0000000000..0e18b247e5
--- /dev/null
+++ b/modules/cvtt/image_compress_cvtt.h
@@ -0,0 +1,39 @@
+/*************************************************************************/
+/* image_compress_cvtt.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 IMAGE_COMPRESS_CVTT_H
+#define IMAGE_COMPRESS_CVTT_H
+
+#include "image.h"
+
+void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressSource p_source);
+void image_decompress_cvtt(Image *p_image);
+
+#endif // IMAGE_COMPRESS_CVTT_H
diff --git a/modules/cvtt/register_types.cpp b/modules/cvtt/register_types.cpp
new file mode 100644
index 0000000000..c96fbbf340
--- /dev/null
+++ b/modules/cvtt/register_types.cpp
@@ -0,0 +1,45 @@
+/*************************************************************************/
+/* register_types.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 "register_types.h"
+
+#ifdef TOOLS_ENABLED
+
+#include "image_compress_cvtt.h"
+
+void register_cvtt_types() {
+
+ Image::set_compress_bptc_func(image_compress_cvtt);
+ Image::_image_decompress_bptc = image_decompress_cvtt;
+}
+
+void unregister_cvtt_types() {}
+
+#endif
diff --git a/modules/cvtt/register_types.h b/modules/cvtt/register_types.h
new file mode 100644
index 0000000000..73de9728d3
--- /dev/null
+++ b/modules/cvtt/register_types.h
@@ -0,0 +1,34 @@
+/*************************************************************************/
+/* register_types.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. */
+/*************************************************************************/
+
+#ifdef TOOLS_ENABLED
+void register_cvtt_types();
+void unregister_cvtt_types();
+#endif
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 217fd87c3e..e326d11a84 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -5876,6 +5876,14 @@
["int", "p_idx"],
["godot_object *", "p_object"]
]
+ },
+ {
+ "name": "godot_nativescript_profiling_add_data",
+ "return_type": "void",
+ "arguments": [
+ ["const char *", "p_signature"],
+ ["uint64_t", "p_line"]
+ ]
}
]
},
diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h
index 1c5422d723..29bd9eec5a 100644
--- a/modules/gdnative/include/nativescript/godot_nativescript.h
+++ b/modules/gdnative/include/nativescript/godot_nativescript.h
@@ -238,6 +238,8 @@ void GDAPI godot_nativescript_unregister_instance_binding_data_functions(int p_i
void GDAPI *godot_nativescript_get_instance_binding_data(int p_idx, godot_object *p_object);
+void GDAPI godot_nativescript_profiling_add_data(const char *p_signature, uint64_t p_time);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp
index ace2ecac5c..72606c8340 100644
--- a/modules/gdnative/nativescript/godot_nativescript.cpp
+++ b/modules/gdnative/nativescript/godot_nativescript.cpp
@@ -365,6 +365,10 @@ void GDAPI *godot_nativescript_get_instance_binding_data(int p_idx, godot_object
return NativeScriptLanguage::get_singleton()->get_instance_binding_data(p_idx, (Object *)p_object);
}
+void GDAPI godot_nativescript_profiling_add_data(const char *p_signature, uint64_t p_time) {
+ NativeScriptLanguage::get_singleton()->profiling_add_data(StringName(p_signature), p_time);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index 24264c4256..608c7aa4a5 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -1010,6 +1010,10 @@ NativeScriptLanguage::NativeScriptLanguage() {
has_objects_to_register = false;
mutex = Mutex::create();
#endif
+
+#ifdef DEBUG_ENABLED
+ profiling = false;
+#endif
}
NativeScriptLanguage::~NativeScriptLanguage() {
@@ -1152,17 +1156,105 @@ void NativeScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_
}
void NativeScriptLanguage::profiling_start() {
+#ifdef DEBUG_ENABLED
+#ifndef NO_THREADS
+ MutexLock lock(mutex);
+#endif
+
+ profile_data.clear();
+ profiling = true;
+#endif
}
void NativeScriptLanguage::profiling_stop() {
+#ifdef DEBUG_ENABLED
+#ifndef NO_THREADS
+ MutexLock lock(mutex);
+#endif
+
+ profiling = false;
+#endif
}
int NativeScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) {
+#ifdef DEBUG_ENABLED
+#ifndef NO_THREADS
+ MutexLock lock(mutex);
+#endif
+ int current = 0;
+
+ for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) {
+ if (current >= p_info_max)
+ break;
+
+ p_info_arr[current].call_count = d->get().call_count;
+ p_info_arr[current].self_time = d->get().self_time;
+ p_info_arr[current].total_time = d->get().total_time;
+ p_info_arr[current].signature = d->get().signature;
+ current++;
+ }
+
+ return current;
+#else
return 0;
+#endif
}
int NativeScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) {
+#ifdef DEBUG_ENABLED
+#ifndef NO_THREADS
+ MutexLock lock(mutex);
+#endif
+ int current = 0;
+
+ for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) {
+ if (current >= p_info_max)
+ break;
+
+ if (d->get().last_frame_call_count) {
+ p_info_arr[current].call_count = d->get().last_frame_call_count;
+ p_info_arr[current].self_time = d->get().last_frame_self_time;
+ p_info_arr[current].total_time = d->get().last_frame_total_time;
+ p_info_arr[current].signature = d->get().signature;
+ current++;
+ }
+ }
+
+ return current;
+#else
return 0;
+#endif
+}
+
+void NativeScriptLanguage::profiling_add_data(StringName p_signature, uint64_t p_time) {
+#ifdef DEBUG_ENABLED
+#ifndef NO_THREADS
+ MutexLock lock(mutex);
+#endif
+
+ Map<StringName, ProfileData>::Element *d = profile_data.find(p_signature);
+ if (d) {
+ d->get().call_count += 1;
+ d->get().total_time += p_time;
+ d->get().frame_call_count += 1;
+ d->get().frame_total_time += p_time;
+ } else {
+ ProfileData data;
+
+ data.signature = p_signature;
+ data.call_count = 1;
+ data.self_time = 0;
+ data.total_time = p_time;
+ data.frame_call_count = 1;
+ data.frame_self_time = 0;
+ data.frame_total_time = p_time;
+ data.last_frame_call_count = 0;
+ data.last_frame_self_time = 0;
+ data.last_frame_total_time = 0;
+
+ profile_data.insert(p_signature, data);
+ }
+#endif
}
int NativeScriptLanguage::register_binding_functions(godot_instance_binding_functions p_binding_functions) {
@@ -1405,6 +1497,24 @@ void NativeScriptLanguage::frame() {
has_objects_to_register = false;
}
#endif
+
+#ifdef DEBUG_ENABLED
+ {
+#ifndef NO_THREADS
+ MutexLock lock(mutex);
+#endif
+
+ for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) {
+ d->get().last_frame_call_count = d->get().frame_call_count;
+ d->get().last_frame_self_time = d->get().frame_self_time;
+ d->get().last_frame_total_time = d->get().frame_total_time;
+ d->get().frame_call_count = 0;
+ d->get().frame_self_time = 0;
+ d->get().frame_total_time = 0;
+ }
+ }
+#endif
+
call_libraries_cb(_frame_call_name);
}
diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h
index c1f11646b0..6f18e2db27 100644
--- a/modules/gdnative/nativescript/nativescript.h
+++ b/modules/gdnative/nativescript/nativescript.h
@@ -254,6 +254,22 @@ private:
Map<int, HashMap<StringName, const void *> > global_type_tags;
+ struct ProfileData {
+ StringName signature;
+ uint64_t call_count;
+ uint64_t self_time;
+ uint64_t total_time;
+ uint64_t frame_call_count;
+ uint64_t frame_self_time;
+ uint64_t frame_total_time;
+ uint64_t last_frame_call_count;
+ uint64_t last_frame_self_time;
+ uint64_t last_frame_total_time;
+ };
+
+ Map<StringName, ProfileData> profile_data;
+ bool profiling;
+
public:
// These two maps must only be touched on the main thread
Map<String, Map<StringName, NativeScriptDesc> > library_classes;
@@ -343,6 +359,8 @@ public:
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, String *r_icon_path) const;
+
+ void profiling_add_data(StringName p_signature, uint64_t p_time);
};
inline NativeScriptDesc *NativeScript::get_script_desc() const {
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index b987d2897f..5125b58b41 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -606,9 +606,11 @@ Error GDScript::reload(bool p_keep_state) {
}
#if DEBUG_ENABLED
for (const List<GDScriptWarning>::Element *E = parser.get_warnings().front(); E; E = E->next()) {
- String msg = "Script warning: " + E->get().get_name() + " (" + path + ") line " + itos(E->get().line) + ": ";
- msg += E->get().get_message();
- WARN_PRINTS(msg);
+ const GDScriptWarning &warning = E->get();
+ if (ScriptDebugger::get_singleton()) {
+ Vector<ScriptLanguage::StackInfo> si;
+ ScriptDebugger::get_singleton()->send_error("", get_path(), warning.line, warning.get_name(), warning.get_message(), ERR_HANDLER_WARNING, si);
+ }
}
#endif
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index fe393957db..368601127d 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1994,8 +1994,11 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner
p_script->_signals[name] = p_class->_signals[i].arguments;
}
- if (!p_class->owner) {
+ if (p_class->owner) {
parsed_classes.insert(p_class->name);
+ if (parsing_classes.has(p_class->name)) {
+ parsing_classes.erase(p_class->name);
+ }
}
//parse sub-classes
@@ -2011,7 +2014,6 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner
Error err = _parse_class_level(subclass.ptr(), p_script, p_class->subclasses[i], p_keep_state);
if (err)
return err;
- parsing_classes.erase(name);
}
#ifdef TOOLS_ENABLED
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index bec314866d..2c0d541d8f 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -2024,12 +2024,20 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) {
// bind
case GDScriptTokenizer::TK_PR_VAR: {
tokenizer->advance();
+ if (!tokenizer->is_token_literal()) {
+ _set_error("Expected identifier for binding variable name.");
+ return NULL;
+ }
pattern->pt_type = GDScriptParser::PatternNode::PT_BIND;
pattern->bind = tokenizer->get_token_identifier();
- // Check if binding is already used
- if (current_block->variables.has(pattern->bind)) {
- _set_error("Binding name of '" + pattern->bind.operator String() + "' was already used in the pattern.");
- return NULL;
+ // Check if variable name is already used
+ BlockNode *bl = current_block;
+ while (bl) {
+ if (bl->variables.has(pattern->bind)) {
+ _set_error("Binding name of '" + pattern->bind.operator String() + "' is already declared in this scope.");
+ return NULL;
+ }
+ bl = bl->parent_block;
}
// Create local variable for proper identifier detection later
LocalVarNode *lv = alloc_node<LocalVarNode>();
@@ -7389,7 +7397,7 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) {
}
}
#ifdef DEBUG_ENABLED
- if (p_function->arguments_usage[i] == 0) {
+ if (p_function->arguments_usage[i] == 0 && !p_function->arguments[i].operator String().begins_with("_")) {
_add_warning(GDScriptWarning::UNUSED_ARGUMENT, p_function->line, p_function->name, p_function->arguments[i].operator String());
}
#endif // DEBUG_ENABLED
@@ -7847,10 +7855,12 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
// Warnings check
for (Map<StringName, LocalVarNode *>::Element *E = p_block->variables.front(); E; E = E->next()) {
LocalVarNode *lv = E->get();
- if (lv->usages == 0) {
- _add_warning(GDScriptWarning::UNUSED_VARIABLE, lv->line, lv->name);
- } else if (lv->assignments == 0) {
- _add_warning(GDScriptWarning::UNASSIGNED_VARIABLE, lv->line, lv->name);
+ if (!lv->name.operator String().begins_with("_")) {
+ if (lv->usages == 0) {
+ _add_warning(GDScriptWarning::UNUSED_VARIABLE, lv->line, lv->name);
+ } else if (lv->assignments == 0) {
+ _add_warning(GDScriptWarning::UNASSIGNED_VARIABLE, lv->line, lv->name);
+ }
}
}
#endif // DEBUG_ENABLED
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index 28a08bfaf8..11a291cb2e 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -283,8 +283,14 @@ public:
virtual String get_token_error(int p_offset = 0) const;
virtual void advance(int p_amount = 1);
#ifdef DEBUG_ENABLED
- virtual const Vector<Pair<int, String> > &get_warning_skips() const { return Vector<Pair<int, String> >(); }
- virtual const Set<String> &get_warning_global_skips() const { return Set<String>(); }
+ virtual const Vector<Pair<int, String> > &get_warning_skips() const {
+ static Vector<Pair<int, String> > v;
+ return v;
+ }
+ virtual const Set<String> &get_warning_global_skips() const {
+ static Set<String> s;
+ return s;
+ }
virtual const bool is_ignoring_warnings() const { return true; }
#endif // DEBUG_ENABLED
GDScriptTokenizerBuffer();
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 0c5df57d49..8b63987cde 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -208,21 +208,35 @@ bool GridMap::get_collision_layer_bit(int p_bit) const {
return get_collision_layer() & (1 << p_bit);
}
+#ifndef DISABLE_DEPRECATED
void GridMap::set_theme(const Ref<MeshLibrary> &p_theme) {
- if (!theme.is_null())
- theme->unregister_owner(this);
- theme = p_theme;
- if (!theme.is_null())
- theme->register_owner(this);
+ WARN_PRINTS("GridMap.theme/set_theme() is deprecated and will be removed in a future version. Use GridMap.mesh_library/set_mesh_library() instead.");
+ set_mesh_library(p_theme);
+}
+
+Ref<MeshLibrary> GridMap::get_theme() const {
+
+ WARN_PRINTS("GridMap.theme/get_theme() is deprecated and will be removed in a future version. Use GridMap.mesh_library/get_mesh_library() instead.");
+ return get_mesh_library();
+}
+#endif // DISABLE_DEPRECATED
+
+void GridMap::set_mesh_library(const Ref<MeshLibrary> &p_mesh_library) {
+
+ if (!mesh_library.is_null())
+ mesh_library->unregister_owner(this);
+ mesh_library = p_mesh_library;
+ if (!mesh_library.is_null())
+ mesh_library->register_owner(this);
_recreate_octant_data();
- _change_notify("theme");
+ _change_notify("mesh_library");
}
-Ref<MeshLibrary> GridMap::get_theme() const {
+Ref<MeshLibrary> GridMap::get_mesh_library() const {
- return theme;
+ return mesh_library;
}
void GridMap::set_cell_size(const Vector3 &p_size) {
@@ -469,7 +483,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
ERR_CONTINUE(!cell_map.has(E->get()));
const Cell &c = cell_map[E->get()];
- if (!theme.is_valid() || !theme->has_item(c.item))
+ if (!mesh_library.is_valid() || !mesh_library->has_item(c.item))
continue;
//print_line("OCTANT, CELLS: "+itos(ii.cells.size()));
@@ -488,7 +502,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
xform.set_origin(cellpos * cell_size + ofs);
xform.basis.scale(Vector3(cell_scale, cell_scale, cell_scale));
if (baked_meshes.size() == 0) {
- if (theme->get_item_mesh(c.item).is_valid()) {
+ if (mesh_library->get_item_mesh(c.item).is_valid()) {
if (!multimesh_items.has(c.item)) {
multimesh_items[c.item] = List<Pair<Transform, IndexKey> >();
}
@@ -500,7 +514,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
}
}
- Vector<MeshLibrary::ShapeData> shapes = theme->get_item_shapes(c.item);
+ Vector<MeshLibrary::ShapeData> shapes = mesh_library->get_item_shapes(c.item);
// add the item's shape at given xform to octant's static_body
for (int i = 0; i < shapes.size(); i++) {
// add the item's shape
@@ -515,7 +529,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
}
// add the item's navmesh at given xform to GridMap's Navigation ancestor
- Ref<NavigationMesh> navmesh = theme->get_item_navmesh(c.item);
+ Ref<NavigationMesh> navmesh = mesh_library->get_item_navmesh(c.item);
if (navmesh.is_valid()) {
Octant::NavMesh nm;
nm.xform = xform;
@@ -537,7 +551,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
RID mm = VS::get_singleton()->multimesh_create();
VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_NONE);
- VS::get_singleton()->multimesh_set_mesh(mm, theme->get_item_mesh(E->key())->get_rid());
+ VS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid());
int idx = 0;
for (List<Pair<Transform, IndexKey> >::Element *F = E->get().front(); F; F = F->next()) {
@@ -612,11 +626,11 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
VS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform());
}
- if (navigation && theme.is_valid()) {
+ if (navigation && mesh_library.is_valid()) {
for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) {
if (cell_map.has(F->key()) && F->get().id < 0) {
- Ref<NavigationMesh> nm = theme->get_item_navmesh(cell_map[F->key()].item);
+ Ref<NavigationMesh> nm = mesh_library->get_item_navmesh(cell_map[F->key()].item);
if (nm.is_valid()) {
F->get().id = navigation->navmesh_add(nm, F->get().xform, this);
}
@@ -846,8 +860,13 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &GridMap::set_collision_layer_bit);
ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &GridMap::get_collision_layer_bit);
+#ifndef DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("set_theme", "theme"), &GridMap::set_theme);
ClassDB::bind_method(D_METHOD("get_theme"), &GridMap::get_theme);
+#endif // DISABLE_DEPRECATED
+
+ ClassDB::bind_method(D_METHOD("set_mesh_library", "mesh_library"), &GridMap::set_mesh_library);
+ ClassDB::bind_method(D_METHOD("get_mesh_library"), &GridMap::get_mesh_library);
ClassDB::bind_method(D_METHOD("set_cell_size", "size"), &GridMap::set_cell_size);
ClassDB::bind_method(D_METHOD("get_cell_size"), &GridMap::get_cell_size);
@@ -865,7 +884,6 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("world_to_map", "pos"), &GridMap::world_to_map);
ClassDB::bind_method(D_METHOD("map_to_world", "x", "y", "z"), &GridMap::map_to_world);
- //ClassDB::bind_method(D_METHOD("_recreate_octants"),&GridMap::_recreate_octants);
ClassDB::bind_method(D_METHOD("_update_octants_callback"), &GridMap::_update_octants_callback);
ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &GridMap::resource_changed);
@@ -889,7 +907,11 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_baked_meshes"), &GridMap::clear_baked_meshes);
ClassDB::bind_method(D_METHOD("make_baked_meshes", "gen_lightmap_uv", "lightmap_uv_texel_size"), &GridMap::make_baked_meshes, DEFVAL(false), DEFVAL(0.1));
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "MeshLibrary"), "set_theme", "get_theme");
+#ifndef DISABLE_DEPRECATED
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "MeshLibrary", PROPERTY_USAGE_NOEDITOR), "set_theme", "get_theme");
+#endif // DISABLE_DEPRECATED
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh_library", PROPERTY_HINT_RESOURCE_TYPE, "MeshLibrary"), "set_mesh_library", "get_mesh_library");
ADD_GROUP("Cell", "cell_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cell_size"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_octant_size", PROPERTY_HINT_RANGE, "1,1024,1"), "set_octant_size", "get_octant_size");
@@ -952,7 +974,7 @@ Array GridMap::get_used_cells() const {
Array GridMap::get_meshes() {
- if (theme.is_null())
+ if (mesh_library.is_null())
return Array();
Vector3 ofs = _get_offset();
@@ -961,9 +983,9 @@ Array GridMap::get_meshes() {
for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next()) {
int id = E->get().item;
- if (!theme->has_item(id))
+ if (!mesh_library->has_item(id))
continue;
- Ref<Mesh> mesh = theme->get_item_mesh(id);
+ Ref<Mesh> mesh = mesh_library->get_item_mesh(id);
if (mesh.is_null())
continue;
@@ -1004,7 +1026,7 @@ void GridMap::clear_baked_meshes() {
void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texel_size) {
- if (!theme.is_valid())
+ if (!mesh_library.is_valid())
return;
//generate
@@ -1015,10 +1037,10 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe
IndexKey key = E->key();
int item = E->get().item;
- if (!theme->has_item(item))
+ if (!mesh_library->has_item(item))
continue;
- Ref<Mesh> mesh = theme->get_item_mesh(item);
+ Ref<Mesh> mesh = mesh_library->get_item_mesh(item);
if (!mesh.is_valid())
continue;
@@ -1137,8 +1159,8 @@ GridMap::GridMap() {
GridMap::~GridMap() {
- if (!theme.is_null())
- theme->unregister_owner(this);
+ if (!mesh_library.is_null())
+ mesh_library->unregister_owner(this);
clear();
}
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index ed36751fc8..3d8be5c9c7 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -157,7 +157,7 @@ class GridMap : public Spatial {
Vector3::Axis clip_axis;
- Ref<MeshLibrary> theme;
+ Ref<MeshLibrary> mesh_library;
Map<OctantKey, Octant *> octant_map;
Map<IndexKey, Cell> cell_map;
@@ -227,8 +227,13 @@ public:
void set_collision_mask_bit(int p_bit, bool p_value);
bool get_collision_mask_bit(int p_bit) const;
+#ifndef DISABLE_DEPRECATED
void set_theme(const Ref<MeshLibrary> &p_theme);
Ref<MeshLibrary> get_theme() const;
+#endif // DISABLE_DEPRECATED
+
+ void set_mesh_library(const Ref<MeshLibrary> &p_mesh_library);
+ Ref<MeshLibrary> get_mesh_library() const;
void set_cell_size(const Vector3 &p_size);
Vector3 get_cell_size() const;
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index fc5972c810..90e28129cc 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -43,7 +43,7 @@ void GridMapEditor::_node_removed(Node *p_node) {
if (p_node == node) {
node = NULL;
hide();
- theme_pallete->hide();
+ mesh_library_palette->hide();
}
}
@@ -320,12 +320,12 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo
if (!spatial_editor)
return false;
- if (selected_pallete < 0 && input_action != INPUT_COPY && input_action != INPUT_SELECT && input_action != INPUT_DUPLICATE)
+ if (selected_palette < 0 && input_action != INPUT_COPY && input_action != INPUT_SELECT && input_action != INPUT_DUPLICATE)
return false;
- Ref<MeshLibrary> theme = node->get_theme();
- if (theme.is_null())
+ Ref<MeshLibrary> mesh_library = node->get_mesh_library();
+ if (mesh_library.is_null())
return false;
- if (input_action != INPUT_COPY && input_action != INPUT_SELECT && input_action != INPUT_DUPLICATE && !theme->has_item(selected_pallete))
+ if (input_action != INPUT_COPY && input_action != INPUT_SELECT && input_action != INPUT_DUPLICATE && !mesh_library->has_item(selected_palette))
return false;
Camera *camera = p_camera;
@@ -407,9 +407,9 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo
int item = node->get_cell_item(cell[0], cell[1], cell[2]);
if (item >= 0) {
- selected_pallete = item;
- theme_pallete->set_current(item);
- update_pallete();
+ selected_palette = item;
+ mesh_library_palette->set_current(item);
+ update_palette();
_update_cursor_instance();
}
return true;
@@ -417,12 +417,12 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo
if (input_action == INPUT_PAINT) {
SetItem si;
si.pos = Vector3(cell[0], cell[1], cell[2]);
- si.new_value = selected_pallete;
+ si.new_value = selected_palette;
si.new_orientation = cursor_rot;
si.old_value = node->get_cell_item(cell[0], cell[1], cell[2]);
si.old_orientation = node->get_cell_item_orientation(cell[0], cell[1], cell[2]);
set_items.push_back(si);
- node->set_cell_item(cell[0], cell[1], cell[2], selected_pallete, cursor_rot);
+ node->set_cell_item(cell[0], cell[1], cell[2], selected_palette, cursor_rot);
return true;
} else if (input_action == INPUT_ERASE) {
SetItem si;
@@ -474,7 +474,7 @@ void GridMapEditor::_fill_selection() {
for (int k = selection.begin.z; k <= selection.end.z; k++) {
- undo_redo->add_do_method(node, "set_cell_item", i, j, k, selected_pallete, cursor_rot);
+ undo_redo->add_do_method(node, "set_cell_item", i, j, k, selected_palette, cursor_rot);
undo_redo->add_undo_method(node, "set_cell_item", i, j, k, node->get_cell_item(i, j, k), node->get_cell_item_orientation(i, j, k));
}
}
@@ -712,42 +712,42 @@ void GridMapEditor::_set_display_mode(int p_mode) {
display_mode = p_mode;
- update_pallete();
+ update_palette();
}
-void GridMapEditor::update_pallete() {
- int selected = theme_pallete->get_current();
+void GridMapEditor::update_palette() {
+ int selected = mesh_library_palette->get_current();
- theme_pallete->clear();
+ mesh_library_palette->clear();
if (display_mode == DISPLAY_THUMBNAIL) {
- theme_pallete->set_max_columns(0);
- theme_pallete->set_icon_mode(ItemList::ICON_MODE_TOP);
+ mesh_library_palette->set_max_columns(0);
+ mesh_library_palette->set_icon_mode(ItemList::ICON_MODE_TOP);
} else if (display_mode == DISPLAY_LIST) {
- theme_pallete->set_max_columns(1);
- theme_pallete->set_icon_mode(ItemList::ICON_MODE_LEFT);
+ mesh_library_palette->set_max_columns(1);
+ mesh_library_palette->set_icon_mode(ItemList::ICON_MODE_LEFT);
}
float min_size = EDITOR_DEF("editors/grid_map/preview_size", 64);
- theme_pallete->set_fixed_icon_size(Size2(min_size, min_size));
- theme_pallete->set_fixed_column_width(min_size * 3 / 2);
- theme_pallete->set_max_text_lines(2);
+ mesh_library_palette->set_fixed_icon_size(Size2(min_size, min_size));
+ mesh_library_palette->set_fixed_column_width(min_size * 3 / 2);
+ mesh_library_palette->set_max_text_lines(2);
- Ref<MeshLibrary> theme = node->get_theme();
+ Ref<MeshLibrary> mesh_library = node->get_mesh_library();
- if (theme.is_null()) {
- last_theme = NULL;
+ if (mesh_library.is_null()) {
+ last_mesh_library = NULL;
return;
}
Vector<int> ids;
- ids = theme->get_item_list();
+ ids = mesh_library->get_item_list();
List<_CGMEItemSort> il;
for (int i = 0; i < ids.size(); i++) {
_CGMEItemSort is;
is.id = ids[i];
- is.name = theme->get_item_name(ids[i]);
+ is.name = mesh_library->get_item_name(ids[i]);
il.push_back(is);
}
il.sort();
@@ -757,28 +757,28 @@ void GridMapEditor::update_pallete() {
for (List<_CGMEItemSort>::Element *E = il.front(); E; E = E->next()) {
int id = E->get().id;
- theme_pallete->add_item("");
+ mesh_library_palette->add_item("");
- String name = theme->get_item_name(id);
- Ref<Texture> preview = theme->get_item_preview(id);
+ String name = mesh_library->get_item_name(id);
+ Ref<Texture> preview = mesh_library->get_item_preview(id);
if (!preview.is_null()) {
- theme_pallete->set_item_icon(item, preview);
- theme_pallete->set_item_tooltip(item, name);
+ mesh_library_palette->set_item_icon(item, preview);
+ mesh_library_palette->set_item_tooltip(item, name);
}
if (name != "") {
- theme_pallete->set_item_text(item, name);
+ mesh_library_palette->set_item_text(item, name);
}
- theme_pallete->set_item_metadata(item, id);
+ mesh_library_palette->set_item_metadata(item, id);
item++;
}
if (selected != -1) {
- theme_pallete->select(selected);
+ mesh_library_palette->select(selected);
}
- last_theme = theme.operator->();
+ last_mesh_library = mesh_library.operator->();
}
void GridMapEditor::edit(GridMap *p_gridmap) {
@@ -805,7 +805,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) {
return;
}
- update_pallete();
+ update_palette();
set_process(true);
@@ -914,7 +914,7 @@ void GridMapEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- theme_pallete->connect("item_selected", this, "_item_selected_cbk");
+ mesh_library_palette->connect("item_selected", this, "_item_selected_cbk");
for (int i = 0; i < 3; i++) {
grid[i] = VS::get_singleton()->mesh_create();
@@ -959,9 +959,9 @@ void GridMapEditor::_notification(int p_what) {
}
grid_xform = xf;
}
- Ref<MeshLibrary> cgmt = node->get_theme();
- if (cgmt.operator->() != last_theme)
- update_pallete();
+ Ref<MeshLibrary> cgmt = node->get_mesh_library();
+ if (cgmt.operator->() != last_mesh_library)
+ update_palette();
if (lock_view) {
@@ -994,10 +994,10 @@ void GridMapEditor::_update_cursor_instance() {
VisualServer::get_singleton()->free(cursor_instance);
cursor_instance = RID();
- if (selected_pallete >= 0) {
+ if (selected_palette >= 0) {
- if (node && !node->get_theme().is_null()) {
- Ref<Mesh> mesh = node->get_theme()->get_item_mesh(selected_pallete);
+ if (node && !node->get_mesh_library().is_null()) {
+ Ref<Mesh> mesh = node->get_mesh_library()->get_item_mesh(selected_palette);
if (!mesh.is_null() && mesh->get_rid().is_valid()) {
cursor_instance = VisualServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario());
@@ -1008,7 +1008,7 @@ void GridMapEditor::_update_cursor_instance() {
}
void GridMapEditor::_item_selected_cbk(int idx) {
- selected_pallete = theme_pallete->get_item_metadata(idx);
+ selected_palette = mesh_library_palette->get_item_metadata(idx);
_update_cursor_instance();
}
@@ -1146,9 +1146,9 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
display_mode = DISPLAY_THUMBNAIL;
- theme_pallete = memnew(ItemList);
- add_child(theme_pallete);
- theme_pallete->set_v_size_flags(SIZE_EXPAND_FILL);
+ mesh_library_palette = memnew(ItemList);
+ add_child(mesh_library_palette);
+ mesh_library_palette->set_v_size_flags(SIZE_EXPAND_FILL);
edit_axis = Vector3::AXIS_Y;
edit_floor[0] = -1;
@@ -1156,7 +1156,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
edit_floor[2] = -1;
cursor_visible = false;
- selected_pallete = -1;
+ selected_palette = -1;
lock_view = false;
cursor_rot = 0;
last_mouseover = Vector3(-1, -1, -1);
@@ -1315,9 +1315,24 @@ GridMapEditor::~GridMapEditor() {
VisualServer::get_singleton()->free(duplicate_instance);
}
+void GridMapEditorPlugin::_notification(int p_what) {
+
+ if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
+
+ switch ((int)EditorSettings::get_singleton()->get("editors/grid_map/editor_side")) {
+ case 0: { // Left.
+ SpatialEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 0);
+ } break;
+ case 1: { // Right.
+ SpatialEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 1);
+ } break;
+ }
+ }
+}
+
void GridMapEditorPlugin::edit(Object *p_object) {
- gridmap_editor->edit(Object::cast_to<GridMap>(p_object));
+ grid_map_editor->edit(Object::cast_to<GridMap>(p_object));
}
bool GridMapEditorPlugin::handles(Object *p_object) const {
@@ -1328,29 +1343,35 @@ bool GridMapEditorPlugin::handles(Object *p_object) const {
void GridMapEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
- gridmap_editor->show();
- gridmap_editor->spatial_editor_hb->show();
- gridmap_editor->set_process(true);
+ grid_map_editor->show();
+ grid_map_editor->spatial_editor_hb->show();
+ grid_map_editor->set_process(true);
} else {
- gridmap_editor->spatial_editor_hb->hide();
- gridmap_editor->hide();
- gridmap_editor->edit(NULL);
- gridmap_editor->set_process(false);
+ grid_map_editor->spatial_editor_hb->hide();
+ grid_map_editor->hide();
+ grid_map_editor->edit(NULL);
+ grid_map_editor->set_process(false);
}
}
GridMapEditorPlugin::GridMapEditorPlugin(EditorNode *p_node) {
editor = p_node;
- gridmap_editor = memnew(GridMapEditor(editor));
- SpatialEditor::get_singleton()->get_palette_split()->add_child(gridmap_editor);
- // TODO: make this configurable, so the user can choose were to put this, it makes more sense
- // on the right, but some people might find it strange.
- SpatialEditor::get_singleton()->get_palette_split()->move_child(gridmap_editor, 1);
+ EDITOR_DEF("editors/grid_map/editor_side", 1);
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "editors/grid_map/editor_side", PROPERTY_HINT_ENUM, "Left,Right"));
- gridmap_editor->hide();
+ grid_map_editor = memnew(GridMapEditor(editor));
+ switch ((int)EditorSettings::get_singleton()->get("editors/grid_map/editor_side")) {
+ case 0: { // Left.
+ add_control_to_container(CONTAINER_SPATIAL_EDITOR_SIDE_LEFT, grid_map_editor);
+ } break;
+ case 1: { // Right.
+ add_control_to_container(CONTAINER_SPATIAL_EDITOR_SIDE_RIGHT, grid_map_editor);
+ } break;
+ }
+ grid_map_editor->hide();
}
GridMapEditorPlugin::~GridMapEditorPlugin() {
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index 7c5feda125..663274f46e 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -97,7 +97,7 @@ class GridMapEditor : public VBoxContainer {
List<SetItem> set_items;
GridMap *node;
- MeshLibrary *last_theme;
+ MeshLibrary *last_mesh_library;
ClipMode clip_mode;
bool lock_view;
@@ -141,7 +141,7 @@ class GridMapEditor : public VBoxContainer {
Vector3 last_mouseover;
int display_mode;
- int selected_pallete;
+ int selected_palette;
int cursor_rot;
enum Menu {
@@ -185,9 +185,9 @@ class GridMapEditor : public VBoxContainer {
void update_grid();
void _configure();
void _menu_option(int);
- void update_pallete();
+ void update_palette();
void _set_display_mode(int p_mode);
- ItemList *theme_pallete;
+ ItemList *mesh_library_palette;
void _item_selected_cbk(int idx);
void _update_cursor_transform();
void _update_cursor_instance();
@@ -207,7 +207,6 @@ class GridMapEditor : public VBoxContainer {
bool do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click);
friend class GridMapEditorPlugin;
- Panel *theme_panel;
protected:
void _notification(int p_what);
@@ -227,11 +226,14 @@ class GridMapEditorPlugin : public EditorPlugin {
GDCLASS(GridMapEditorPlugin, EditorPlugin);
- GridMapEditor *gridmap_editor;
+ GridMapEditor *grid_map_editor;
EditorNode *editor;
+protected:
+ void _notification(int p_what);
+
public:
- virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event) { return gridmap_editor->forward_spatial_input_event(p_camera, p_event); }
+ virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event) { return grid_map_editor->forward_spatial_input_event(p_camera, p_event); }
virtual String get_name() const { return "GridMap"; }
bool has_main_screen() const { return false; }
virtual void edit(Object *p_object);
diff --git a/modules/mono/glue/cs_files/Color.cs b/modules/mono/glue/cs_files/Color.cs
index 1195071bd3..49e04b333a 100644
--- a/modules/mono/glue/cs_files/Color.cs
+++ b/modules/mono/glue/cs_files/Color.cs
@@ -258,11 +258,6 @@ namespace Godot
return res;
}
- public float Gray()
- {
- return (r + g + b) / 3.0f;
- }
-
public Color Inverted()
{
return new Color(
diff --git a/modules/mono/glue/cs_files/Plane.cs b/modules/mono/glue/cs_files/Plane.cs
index 1020f06bf5..9611dce11e 100644
--- a/modules/mono/glue/cs_files/Plane.cs
+++ b/modules/mono/glue/cs_files/Plane.cs
@@ -145,6 +145,15 @@ namespace Godot
return point - _normal * DistanceTo(point);
}
+ // Constants
+ private static readonly Plane _planeYZ = new Plane(1, 0, 0, 0);
+ private static readonly Plane _planeXZ = new Plane(0, 1, 0, 0);
+ private static readonly Plane _planeXY = new Plane(0, 0, 1, 0);
+
+ public static Plane PlaneYZ { get { return _planeYZ; } }
+ public static Plane PlaneXZ { get { return _planeXZ; } }
+ public static Plane PlaneXY { get { return _planeXY; } }
+
// Constructors
public Plane(real_t a, real_t b, real_t c, real_t d)
{
diff --git a/modules/mono/glue/cs_files/Rect2.cs b/modules/mono/glue/cs_files/Rect2.cs
index 6f16656573..e772665009 100644
--- a/modules/mono/glue/cs_files/Rect2.cs
+++ b/modules/mono/glue/cs_files/Rect2.cs
@@ -11,24 +11,24 @@ namespace Godot
[StructLayout(LayoutKind.Sequential)]
public struct Rect2 : IEquatable<Rect2>
{
- private Vector2 position;
- private Vector2 size;
+ private Vector2 _position;
+ private Vector2 _size;
public Vector2 Position
{
- get { return position; }
- set { position = value; }
+ get { return _position; }
+ set { _position = value; }
}
public Vector2 Size
{
- get { return size; }
- set { size = value; }
+ get { return _size; }
+ set { _size = value; }
}
public Vector2 End
{
- get { return position + size; }
+ get { return _position + _size; }
}
public real_t Area
@@ -36,6 +36,13 @@ namespace Godot
get { return GetArea(); }
}
+ public Rect2 Abs()
+ {
+ Vector2 end = End;
+ Vector2 topLeft = new Vector2(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y));
+ return new Rect2(topLeft, _size.Abs());
+ }
+
public Rect2 Clip(Rect2 b)
{
var newRect = b;
@@ -43,31 +50,31 @@ namespace Godot
if (!Intersects(newRect))
return new Rect2();
- newRect.position.x = Mathf.Max(b.position.x, position.x);
- newRect.position.y = Mathf.Max(b.position.y, position.y);
+ newRect._position.x = Mathf.Max(b._position.x, _position.x);
+ newRect._position.y = Mathf.Max(b._position.y, _position.y);
- Vector2 bEnd = b.position + b.size;
- Vector2 end = position + size;
+ Vector2 bEnd = b._position + b._size;
+ Vector2 end = _position + _size;
- newRect.size.x = Mathf.Min(bEnd.x, end.x) - newRect.position.x;
- newRect.size.y = Mathf.Min(bEnd.y, end.y) - newRect.position.y;
+ newRect._size.x = Mathf.Min(bEnd.x, end.x) - newRect._position.x;
+ newRect._size.y = Mathf.Min(bEnd.y, end.y) - newRect._position.y;
return newRect;
}
public bool Encloses(Rect2 b)
{
- return b.position.x >= position.x && b.position.y >= position.y &&
- b.position.x + b.size.x < position.x + size.x &&
- b.position.y + b.size.y < position.y + size.y;
+ return b._position.x >= _position.x && b._position.y >= _position.y &&
+ b._position.x + b._size.x < _position.x + _size.x &&
+ b._position.y + b._size.y < _position.y + _size.y;
}
public Rect2 Expand(Vector2 to)
{
var expanded = this;
- Vector2 begin = expanded.position;
- Vector2 end = expanded.position + expanded.size;
+ Vector2 begin = expanded._position;
+ Vector2 end = expanded._position + expanded._size;
if (to.x < begin.x)
begin.x = to.x;
@@ -79,25 +86,25 @@ namespace Godot
if (to.y > end.y)
end.y = to.y;
- expanded.position = begin;
- expanded.size = end - begin;
+ expanded._position = begin;
+ expanded._size = end - begin;
return expanded;
}
public real_t GetArea()
{
- return size.x * size.y;
+ return _size.x * _size.y;
}
public Rect2 Grow(real_t by)
{
var g = this;
- g.position.x -= by;
- g.position.y -= by;
- g.size.x += by * 2;
- g.size.y += by * 2;
+ g._position.x -= by;
+ g._position.y -= by;
+ g._size.x += by * 2;
+ g._size.y += by * 2;
return g;
}
@@ -106,10 +113,10 @@ namespace Godot
{
var g = this;
- g.position.x -= left;
- g.position.y -= top;
- g.size.x += left + right;
- g.size.y += top + bottom;
+ g._position.x -= left;
+ g._position.y -= top;
+ g._size.x += left + right;
+ g._size.y += top + bottom;
return g;
}
@@ -128,19 +135,19 @@ namespace Godot
public bool HasNoArea()
{
- return size.x <= 0 || size.y <= 0;
+ return _size.x <= 0 || _size.y <= 0;
}
public bool HasPoint(Vector2 point)
{
- if (point.x < position.x)
+ if (point.x < _position.x)
return false;
- if (point.y < position.y)
+ if (point.y < _position.y)
return false;
- if (point.x >= position.x + size.x)
+ if (point.x >= _position.x + _size.x)
return false;
- if (point.y >= position.y + size.y)
+ if (point.y >= _position.y + _size.y)
return false;
return true;
@@ -148,13 +155,13 @@ namespace Godot
public bool Intersects(Rect2 b)
{
- if (position.x > b.position.x + b.size.x)
+ if (_position.x > b._position.x + b._size.x)
return false;
- if (position.x + size.x < b.position.x)
+ if (_position.x + _size.x < b._position.x)
return false;
- if (position.y > b.position.y + b.size.y)
+ if (_position.y > b._position.y + b._size.y)
return false;
- if (position.y + size.y < b.position.y)
+ if (_position.y + _size.y < b._position.y)
return false;
return true;
@@ -164,13 +171,13 @@ namespace Godot
{
Rect2 newRect;
- newRect.position.x = Mathf.Min(b.position.x, position.x);
- newRect.position.y = Mathf.Min(b.position.y, position.y);
+ newRect._position.x = Mathf.Min(b._position.x, _position.x);
+ newRect._position.y = Mathf.Min(b._position.y, _position.y);
- newRect.size.x = Mathf.Max(b.position.x + b.size.x, position.x + size.x);
- newRect.size.y = Mathf.Max(b.position.y + b.size.y, position.y + size.y);
+ newRect._size.x = Mathf.Max(b._position.x + b._size.x, _position.x + _size.x);
+ newRect._size.y = Mathf.Max(b._position.y + b._size.y, _position.y + _size.y);
- newRect.size = newRect.size - newRect.position; // Make relative again
+ newRect._size = newRect._size - newRect._position; // Make relative again
return newRect;
}
@@ -178,23 +185,23 @@ namespace Godot
// Constructors
public Rect2(Vector2 position, Vector2 size)
{
- this.position = position;
- this.size = size;
+ _position = position;
+ _size = size;
}
public Rect2(Vector2 position, real_t width, real_t height)
{
- this.position = position;
- size = new Vector2(width, height);
+ _position = position;
+ _size = new Vector2(width, height);
}
public Rect2(real_t x, real_t y, Vector2 size)
{
- position = new Vector2(x, y);
- this.size = size;
+ _position = new Vector2(x, y);
+ _size = size;
}
public Rect2(real_t x, real_t y, real_t width, real_t height)
{
- position = new Vector2(x, y);
- size = new Vector2(width, height);
+ _position = new Vector2(x, y);
+ _size = new Vector2(width, height);
}
public static bool operator ==(Rect2 left, Rect2 right)
@@ -219,20 +226,20 @@ namespace Godot
public bool Equals(Rect2 other)
{
- return position.Equals(other.position) && size.Equals(other.size);
+ return _position.Equals(other._position) && _size.Equals(other._size);
}
public override int GetHashCode()
{
- return position.GetHashCode() ^ size.GetHashCode();
+ return _position.GetHashCode() ^ _size.GetHashCode();
}
public override string ToString()
{
return String.Format("({0}, {1})", new object[]
{
- position.ToString(),
- size.ToString()
+ _position.ToString(),
+ _size.ToString()
});
}
@@ -240,8 +247,8 @@ namespace Godot
{
return String.Format("({0}, {1})", new object[]
{
- position.ToString(format),
- size.ToString(format)
+ _position.ToString(format),
+ _size.ToString(format)
});
}
}
diff --git a/modules/mono/glue/cs_files/Vector2.cs b/modules/mono/glue/cs_files/Vector2.cs
index 14c8de6986..080b8802ba 100644
--- a/modules/mono/glue/cs_files/Vector2.cs
+++ b/modules/mono/glue/cs_files/Vector2.cs
@@ -184,6 +184,11 @@ namespace Godot
return result;
}
+ public Vector2 Project(Vector2 onNormal)
+ {
+ return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
+ }
+
public Vector2 Reflect(Vector2 n)
{
return 2.0f * n * Dot(n) - this;
diff --git a/modules/mono/glue/cs_files/Vector3.cs b/modules/mono/glue/cs_files/Vector3.cs
index 861d9c54d9..6fffe5e4d6 100644
--- a/modules/mono/glue/cs_files/Vector3.cs
+++ b/modules/mono/glue/cs_files/Vector3.cs
@@ -210,6 +210,11 @@ namespace Godot
);
}
+ public Vector3 Project(Vector3 onNormal)
+ {
+ return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
+ }
+
public Vector3 Reflect(Vector3 n)
{
#if DEBUG
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 9d3bee2176..27ce39b6d7 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -42,8 +42,25 @@
#include "gd_mono_class.h"
bool GDMonoAssembly::no_search = false;
+bool GDMonoAssembly::in_preload = false;
+
Vector<String> GDMonoAssembly::search_dirs;
+void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, void *user_data) {
+
+ if (no_search)
+ return;
+
+ // If our search and preload hooks fail to load the assembly themselves, the mono runtime still might.
+ // Just do Assembly.LoadFrom("/Full/Path/On/Disk.dll");
+ // In this case, we wouldn't have the assembly known in GDMono, which causes crashes
+ // if any class inside the assembly is looked up by Godot.
+ // And causing a lookup like that is as easy as throwing an exception defined in it...
+ // No, we can't make the assembly load hooks smart enough because they get passed a MonoAssemblyName* only,
+ // not the disk path passed to say Assembly.LoadFrom().
+ _wrap_mono_assembly(assembly);
+}
+
MonoAssembly *GDMonoAssembly::assembly_search_hook(MonoAssemblyName *aname, void *user_data) {
return GDMonoAssembly::_search_hook(aname, user_data, false);
}
@@ -111,6 +128,8 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d
return res ? res->get_assembly() : NULL;
}
+static _THREAD_LOCAL_(MonoImage *) image_corlib_loading = NULL;
+
MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly) {
(void)user_data; // UNUSED
@@ -138,16 +157,38 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse
}
}
+ {
+ // If we find the assembly here, we load it with `mono_assembly_load_from_full`,
+ // which in turn invokes load hooks before returning the MonoAssembly to us.
+ // One of the load hooks is `load_aot_module`. This hook can end up calling preload hooks
+ // again for the same assembly in certain in certain circumstances (the `do_load_image` part).
+ // If this is the case and we return NULL due to the no_search condition below,
+ // it will result in an internal crash later on. Therefore we need to return the assembly we didn't
+ // get yet from `mono_assembly_load_from_full`. Luckily we have the image, which already got it.
+ // This must be done here. If done in search hooks, it would cause `mono_assembly_load_from_full`
+ // to think another MonoAssembly for this assembly was already loaded, making it delete its own,
+ // when in fact both pointers were the same... This hooks thing is confusing.
+ if (image_corlib_loading) {
+ return mono_image_get_assembly(image_corlib_loading);
+ }
+ }
+
+ if (no_search)
+ return NULL;
+
+ no_search = true;
+ in_preload = true;
+
String name = mono_assembly_name_get_name(aname);
bool has_extension = name.ends_with(".dll");
+ GDMonoAssembly *res = NULL;
if (has_extension ? name == "mscorlib.dll" : name == "mscorlib") {
GDMonoAssembly **stored_assembly = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name);
if (stored_assembly)
return (*stored_assembly)->get_assembly();
String path;
- GDMonoAssembly *res = NULL;
for (int i = 0; i < search_dirs.size(); i++) {
const String &search_dir = search_dirs[i];
@@ -168,11 +209,12 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse
}
}
}
-
- return res ? res->get_assembly() : NULL;
}
- return NULL;
+ no_search = false;
+ in_preload = false;
+
+ return res ? res->get_assembly() : NULL;
}
GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly) {
@@ -192,12 +234,30 @@ GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const
return assembly;
}
+void GDMonoAssembly::_wrap_mono_assembly(MonoAssembly *assembly) {
+ String name = mono_assembly_name_get_name(mono_assembly_get_name(assembly));
+
+ MonoImage *image = mono_assembly_get_image(assembly);
+
+ GDMonoAssembly *gdassembly = memnew(GDMonoAssembly(name, mono_image_get_filename(image)));
+ Error err = gdassembly->wrapper_for_image(image);
+
+ if (err != OK) {
+ memdelete(gdassembly);
+ ERR_FAIL();
+ }
+
+ MonoDomain *domain = mono_domain_get();
+ GDMono::get_singleton()->add_assembly(domain ? mono_domain_get_id(domain) : 0, gdassembly);
+}
+
void GDMonoAssembly::initialize() {
mono_install_assembly_search_hook(&assembly_search_hook, NULL);
mono_install_assembly_refonly_search_hook(&assembly_refonly_search_hook, NULL);
mono_install_assembly_preload_hook(&assembly_preload_hook, NULL);
mono_install_assembly_refonly_preload_hook(&assembly_refonly_preload_hook, NULL);
+ mono_install_assembly_load_hook(&assembly_load_hook, NULL);
}
Error GDMonoAssembly::load(bool p_refonly) {
@@ -241,8 +301,16 @@ no_pdb:
#endif
+ bool is_corlib_preload = in_preload && name == "mscorlib";
+
+ if (is_corlib_preload)
+ image_corlib_loading = image;
+
assembly = mono_assembly_load_from_full(image, image_filename.utf8().get_data(), &status, refonly);
+ if (is_corlib_preload)
+ image_corlib_loading = NULL;
+
ERR_FAIL_COND_V(status != MONO_IMAGE_OK || assembly == NULL, ERR_FILE_CANT_OPEN);
loaded = true;
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index 5cf744a5a2..2c6d367fc6 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -89,8 +89,10 @@ class GDMonoAssembly {
#endif
static bool no_search;
+ static bool in_preload;
static Vector<String> search_dirs;
+ static void assembly_load_hook(MonoAssembly *assembly, void *user_data);
static MonoAssembly *assembly_search_hook(MonoAssemblyName *aname, void *user_data);
static MonoAssembly *assembly_refonly_search_hook(MonoAssemblyName *aname, void *user_data);
static MonoAssembly *assembly_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data);
@@ -100,6 +102,7 @@ class GDMonoAssembly {
static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly);
static GDMonoAssembly *_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly);
+ static void _wrap_mono_assembly(MonoAssembly *assembly);
friend class GDMono;
static void initialize();
diff --git a/modules/mono/utils/thread_local.cpp b/modules/mono/utils/thread_local.cpp
index ae9f130518..a0e28fca5f 100644
--- a/modules/mono/utils/thread_local.cpp
+++ b/modules/mono/utils/thread_local.cpp
@@ -69,7 +69,7 @@ struct ThreadLocalStorage::Impl {
#define _CALLBACK_FUNC_
#endif
- Impl(void (_CALLBACK_FUNC_ *p_destr_callback_func)(void *)) {
+ Impl(void(_CALLBACK_FUNC_ *p_destr_callback_func)(void *)) {
#ifdef WINDOWS_ENABLED
dwFlsIndex = FlsAlloc(p_destr_callback_func);
ERR_FAIL_COND(dwFlsIndex == FLS_OUT_OF_INDEXES);
@@ -95,7 +95,7 @@ void ThreadLocalStorage::set_value(void *p_value) const {
pimpl->set_value(p_value);
}
-void ThreadLocalStorage::alloc(void (_CALLBACK_FUNC_ *p_destr_callback)(void *)) {
+void ThreadLocalStorage::alloc(void(_CALLBACK_FUNC_ *p_destr_callback)(void *)) {
pimpl = memnew(ThreadLocalStorage::Impl(p_destr_callback));
}
diff --git a/modules/mono/utils/thread_local.h b/modules/mono/utils/thread_local.h
index 783e40dc01..84dae1d86b 100644
--- a/modules/mono/utils/thread_local.h
+++ b/modules/mono/utils/thread_local.h
@@ -76,7 +76,7 @@ struct ThreadLocalStorage {
void *get_value() const;
void set_value(void *p_value) const;
- void alloc(void (_CALLBACK_FUNC_ *p_dest_callback)(void *));
+ void alloc(void(_CALLBACK_FUNC_ *p_dest_callback)(void *));
void free();
private:
@@ -95,7 +95,6 @@ class ThreadLocal {
memdelete(static_cast<T *>(tls_data));
}
-
T *_tls_get_value() const {
void *tls_data = storage.get_value();
diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp
index f6be537413..25fc897146 100644
--- a/modules/squish/image_compress_squish.cpp
+++ b/modules/squish/image_compress_squish.cpp
@@ -32,12 +32,6 @@
#include "print_string.h"
-#if defined(__SSE2__)
-#define SQUISH_USE_SSE 2
-#elif defined(__SSE__)
-#define SQUISH_USE_SSE 1
-#endif
-
#include <squish.h>
void image_decompress_squish(Image *p_image) {
@@ -81,7 +75,7 @@ void image_decompress_squish(Image *p_image) {
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
}
-void image_compress_squish(Image *p_image, Image::CompressSource p_source) {
+void image_compress_squish(Image *p_image, float p_lossy_quality, Image::CompressSource p_source) {
if (p_image->get_format() >= Image::FORMAT_DXT1)
return; //do not compress, already compressed
@@ -92,6 +86,12 @@ void image_compress_squish(Image *p_image, Image::CompressSource p_source) {
if (p_image->get_format() <= Image::FORMAT_RGBA8) {
int squish_comp = squish::kColourRangeFit;
+
+ if (p_lossy_quality > 0.85)
+ squish_comp = squish::kColourIterativeClusterFit;
+ else if (p_lossy_quality > 0.75)
+ squish_comp = squish::kColourClusterFit;
+
Image::Format target_format = Image::FORMAT_RGBA8;
Image::DetectChannels dc = p_image->get_detected_channels();
diff --git a/modules/squish/image_compress_squish.h b/modules/squish/image_compress_squish.h
index c022063fe5..6da947beea 100644
--- a/modules/squish/image_compress_squish.h
+++ b/modules/squish/image_compress_squish.h
@@ -33,7 +33,7 @@
#include "image.h"
-void image_compress_squish(Image *p_image, Image::CompressSource p_source);
+void image_compress_squish(Image *p_image, float p_lossy_quality, Image::CompressSource p_source);
void image_decompress_squish(Image *p_image);
#endif // IMAGE_COMPRESS_SQUISH_H