summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/3d/arvr_nodes.cpp10
-rw-r--r--scene/3d/baked_lightmap.cpp84
-rw-r--r--scene/3d/baked_lightmap.h22
-rw-r--r--scene/3d/camera.cpp12
-rw-r--r--scene/3d/camera.h2
-rw-r--r--scene/3d/skeleton.cpp7
-rw-r--r--scene/3d/voxel_light_baker.cpp170
-rw-r--r--scene/3d/voxel_light_baker.h35
-rw-r--r--scene/gui/base_button.cpp8
-rw-r--r--scene/gui/label.cpp2
-rw-r--r--scene/main/scene_tree.cpp27
-rw-r--r--scene/main/scene_tree.h5
-rw-r--r--scene/main/viewport.cpp26
-rw-r--r--scene/register_scene_types.cpp4
-rw-r--r--scene/resources/dynamic_font.cpp86
-rw-r--r--scene/resources/dynamic_font.h24
-rw-r--r--scene/resources/font.cpp4
17 files changed, 395 insertions, 133 deletions
diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp
index e1e0b9b1ce..2bb41bf49e 100644
--- a/scene/3d/arvr_nodes.cpp
+++ b/scene/3d/arvr_nodes.cpp
@@ -231,7 +231,7 @@ void ARVRController::_notification(int p_what) {
void ARVRController::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_controller_id", "controller_id"), &ARVRController::set_controller_id);
ClassDB::bind_method(D_METHOD("get_controller_id"), &ARVRController::get_controller_id);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_id", PROPERTY_HINT_RANGE, "1,32,1"), "set_controller_id", "get_controller_id");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_id", PROPERTY_HINT_RANGE, "0,32,1"), "set_controller_id", "get_controller_id");
ClassDB::bind_method(D_METHOD("get_controller_name"), &ARVRController::get_controller_name);
// passthroughs to information about our related joystick
@@ -251,7 +251,8 @@ void ARVRController::_bind_methods() {
};
void ARVRController::set_controller_id(int p_controller_id) {
- // we don't check any bounds here, this controller may not yet be active and just be a place holder until it is.
+ // We don't check any bounds here, this controller may not yet be active and just be a place holder until it is.
+ // Note that setting this to 0 means this node is not bound to a controller yet.
controller_id = p_controller_id;
};
@@ -420,7 +421,7 @@ void ARVRAnchor::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_anchor_id", "anchor_id"), &ARVRAnchor::set_anchor_id);
ClassDB::bind_method(D_METHOD("get_anchor_id"), &ARVRAnchor::get_anchor_id);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_id"), "set_anchor_id", "get_anchor_id");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_id", PROPERTY_HINT_RANGE, "0,32,1"), "set_anchor_id", "get_anchor_id");
ClassDB::bind_method(D_METHOD("get_anchor_name"), &ARVRAnchor::get_anchor_name);
ClassDB::bind_method(D_METHOD("get_is_active"), &ARVRAnchor::get_is_active);
@@ -430,7 +431,8 @@ void ARVRAnchor::_bind_methods() {
};
void ARVRAnchor::set_anchor_id(int p_anchor_id) {
- // we don't check any bounds here, this anchor may not yet be active and just be a place holder until it is.
+ // We don't check any bounds here, this anchor may not yet be active and just be a place holder until it is.
+ // Note that setting this to 0 means this node is not bound to an anchor yet.
anchor_id = p_anchor_id;
};
diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp
index 754dcd9a6c..9a77626296 100644
--- a/scene/3d/baked_lightmap.cpp
+++ b/scene/3d/baked_lightmap.cpp
@@ -165,20 +165,20 @@ BakedLightmap::BakeBeginFunc BakedLightmap::bake_begin_function = NULL;
BakedLightmap::BakeStepFunc BakedLightmap::bake_step_function = NULL;
BakedLightmap::BakeEndFunc BakedLightmap::bake_end_function = NULL;
-void BakedLightmap::set_bake_subdiv(Subdiv p_subdiv) {
- bake_subdiv = p_subdiv;
+void BakedLightmap::set_bake_cell_size(float p_cell_size) {
+ bake_cell_size = p_cell_size;
}
-BakedLightmap::Subdiv BakedLightmap::get_bake_subdiv() const {
- return bake_subdiv;
+float BakedLightmap::get_bake_cell_size() const {
+ return bake_cell_size;
}
-void BakedLightmap::set_capture_subdiv(Subdiv p_subdiv) {
- capture_subdiv = p_subdiv;
+void BakedLightmap::set_capture_cell_size(float p_cell_size) {
+ capture_cell_size = p_cell_size;
}
-BakedLightmap::Subdiv BakedLightmap::get_capture_subdiv() const {
- return capture_subdiv;
+float BakedLightmap::get_capture_cell_size() const {
+ return capture_cell_size;
}
void BakedLightmap::set_extents(const Vector3 &p_extents) {
@@ -327,11 +327,29 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
Ref<BakedLightmapData> new_light_data;
new_light_data.instance();
- static const int subdiv_value[SUBDIV_MAX] = { 8, 9, 10, 11 };
-
VoxelLightBaker baker;
- baker.begin_bake(subdiv_value[bake_subdiv], AABB(-extents, extents * 2.0));
+ int bake_subdiv;
+ int capture_subdiv;
+ AABB bake_bounds;
+ {
+ bake_bounds = AABB(-extents, extents * 2.0);
+ int subdiv = nearest_power_of_2_templated(int(bake_bounds.get_longest_axis_size() / bake_cell_size));
+ bake_bounds.size[bake_bounds.get_longest_axis_size()] = subdiv * bake_cell_size;
+ bake_subdiv = nearest_shift(subdiv) + 1;
+
+ capture_subdiv = bake_subdiv;
+ float css = bake_cell_size;
+ while (css < capture_cell_size && capture_subdiv > 2) {
+ capture_subdiv--;
+ css *= 2.0;
+ }
+
+ print_line("bake subdiv: " + itos(bake_subdiv));
+ print_line("capture subdiv: " + itos(capture_subdiv));
+ }
+
+ baker.begin_bake(bake_subdiv, bake_bounds);
List<PlotMesh> mesh_list;
List<PlotLight> light_list;
@@ -510,19 +528,19 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
}
}
- int csubdiv = subdiv_value[capture_subdiv];
AABB bounds = AABB(-extents, extents * 2);
- new_light_data->set_cell_subdiv(csubdiv);
+ new_light_data->set_cell_subdiv(capture_subdiv);
new_light_data->set_bounds(bounds);
- new_light_data->set_octree(baker.create_capture_octree(csubdiv));
+ new_light_data->set_octree(baker.create_capture_octree(capture_subdiv));
{
+ float bake_bound_size = bake_bounds.get_longest_axis_size();
Transform to_bounds;
- to_bounds.basis.scale(Vector3(bounds.get_longest_axis_size(), bounds.get_longest_axis_size(), bounds.get_longest_axis_size()));
+ to_bounds.basis.scale(Vector3(bake_bound_size, bake_bound_size, bake_bound_size));
to_bounds.origin = bounds.position;
Transform to_grid;
- to_grid.basis.scale(Vector3(1 << (csubdiv - 1), 1 << (csubdiv - 1), 1 << (csubdiv - 1)));
+ to_grid.basis.scale(Vector3(1 << (capture_subdiv - 1), 1 << (capture_subdiv - 1), 1 << (capture_subdiv - 1)));
Transform to_cell_space = to_grid * to_bounds.affine_inverse();
new_light_data->set_cell_space_transform(to_cell_space);
@@ -693,11 +711,11 @@ void BakedLightmap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_light_data", "data"), &BakedLightmap::set_light_data);
ClassDB::bind_method(D_METHOD("get_light_data"), &BakedLightmap::get_light_data);
- ClassDB::bind_method(D_METHOD("set_bake_subdiv", "bake_subdiv"), &BakedLightmap::set_bake_subdiv);
- ClassDB::bind_method(D_METHOD("get_bake_subdiv"), &BakedLightmap::get_bake_subdiv);
+ ClassDB::bind_method(D_METHOD("set_bake_cell_size", "bake_cell_size"), &BakedLightmap::set_bake_cell_size);
+ ClassDB::bind_method(D_METHOD("get_bake_cell_size"), &BakedLightmap::get_bake_cell_size);
- ClassDB::bind_method(D_METHOD("set_capture_subdiv", "capture_subdiv"), &BakedLightmap::set_capture_subdiv);
- ClassDB::bind_method(D_METHOD("get_capture_subdiv"), &BakedLightmap::get_capture_subdiv);
+ ClassDB::bind_method(D_METHOD("set_capture_cell_size", "capture_cell_size"), &BakedLightmap::set_capture_cell_size);
+ ClassDB::bind_method(D_METHOD("get_capture_cell_size"), &BakedLightmap::get_capture_cell_size);
ClassDB::bind_method(D_METHOD("set_bake_quality", "bake_quality"), &BakedLightmap::set_bake_quality);
ClassDB::bind_method(D_METHOD("get_bake_quality"), &BakedLightmap::get_bake_quality);
@@ -724,23 +742,20 @@ void BakedLightmap::_bind_methods() {
ClassDB::bind_method(D_METHOD("debug_bake"), &BakedLightmap::_debug_bake);
ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_subdiv", PROPERTY_HINT_ENUM, "128,256,512,1024"), "set_bake_subdiv", "get_bake_subdiv");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "capture_subdiv", PROPERTY_HINT_ENUM, "128,256,512"), "set_capture_subdiv", "get_capture_subdiv");
+ ADD_GROUP("Bake", "bake_");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_bake_cell_size", "get_bake_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_bake_quality", "get_bake_quality");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mode", PROPERTY_HINT_ENUM, "ConeTrace,RayTrace"), "set_bake_mode", "get_bake_mode");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_energy", "get_energy");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr"), "set_hdr", "is_hdr");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_energy", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_energy", "get_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_hdr"), "set_hdr", "is_hdr");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "bake_extents"), "set_extents", "get_extents");
+ ADD_GROUP("Capture", "capture_");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "capture_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_capture_cell_size", "get_capture_cell_size");
+ ADD_GROUP("Data", "");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "image_path", PROPERTY_HINT_DIR), "set_image_path", "get_image_path");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "BakedIndirectLightData"), "set_light_data", "get_light_data");
- BIND_ENUM_CONSTANT(SUBDIV_128);
- BIND_ENUM_CONSTANT(SUBDIV_256);
- BIND_ENUM_CONSTANT(SUBDIV_512);
- BIND_ENUM_CONSTANT(SUBDIV_1024);
- BIND_ENUM_CONSTANT(SUBDIV_MAX);
-
BIND_ENUM_CONSTANT(BAKE_QUALITY_LOW);
BIND_ENUM_CONSTANT(BAKE_QUALITY_MEDIUM);
BIND_ENUM_CONSTANT(BAKE_QUALITY_HIGH);
@@ -757,8 +772,9 @@ void BakedLightmap::_bind_methods() {
BakedLightmap::BakedLightmap() {
extents = Vector3(10, 10, 10);
- bake_subdiv = SUBDIV_256;
- capture_subdiv = SUBDIV_128;
+ bake_cell_size = 0.1;
+ capture_cell_size = 0.25;
+
bake_quality = BAKE_QUALITY_MEDIUM;
bake_mode = BAKE_MODE_CONE_TRACE;
energy = 1;
diff --git a/scene/3d/baked_lightmap.h b/scene/3d/baked_lightmap.h
index 9e15f1bb10..9b53e41d73 100644
--- a/scene/3d/baked_lightmap.h
+++ b/scene/3d/baked_lightmap.h
@@ -61,15 +61,6 @@ class BakedLightmap : public VisualInstance {
GDCLASS(BakedLightmap, VisualInstance);
public:
- enum Subdiv {
- SUBDIV_128,
- SUBDIV_256,
- SUBDIV_512,
- SUBDIV_1024,
- SUBDIV_MAX
-
- };
-
enum BakeQuality {
BAKE_QUALITY_LOW,
BAKE_QUALITY_MEDIUM,
@@ -95,8 +86,8 @@ public:
typedef void (*BakeEndFunc)();
private:
- Subdiv bake_subdiv;
- Subdiv capture_subdiv;
+ float bake_cell_size;
+ float capture_cell_size;
Vector3 extents;
float propagation;
float energy;
@@ -148,11 +139,11 @@ public:
void set_light_data(const Ref<BakedLightmapData> &p_data);
Ref<BakedLightmapData> get_light_data() const;
- void set_bake_subdiv(Subdiv p_subdiv);
- Subdiv get_bake_subdiv() const;
+ void set_bake_cell_size(float p_cell_size);
+ float get_bake_cell_size() const;
- void set_capture_subdiv(Subdiv p_subdiv);
- Subdiv get_capture_subdiv() const;
+ void set_capture_cell_size(float p_cell_size);
+ float get_capture_cell_size() const;
void set_extents(const Vector3 &p_extents);
Vector3 get_extents() const;
@@ -182,7 +173,6 @@ public:
BakedLightmap();
};
-VARIANT_ENUM_CAST(BakedLightmap::Subdiv);
VARIANT_ENUM_CAST(BakedLightmap::BakeQuality);
VARIANT_ENUM_CAST(BakedLightmap::BakeMode);
VARIANT_ENUM_CAST(BakedLightmap::BakeError);
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 72c0b979af..c74abb7e2d 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -407,15 +407,6 @@ Camera::KeepAspect Camera::get_keep_aspect_mode() const {
return keep_aspect;
}
-void Camera::set_vaspect(bool p_vaspect) {
- set_keep_aspect_mode(p_vaspect ? KEEP_WIDTH : KEEP_HEIGHT);
- _update_camera_mode();
-}
-
-bool Camera::get_vaspect() const {
- return keep_aspect == KEEP_HEIGHT;
-}
-
void Camera::set_doppler_tracking(DopplerTracking p_tracking) {
if (doppler_tracking == p_tracking)
@@ -468,14 +459,11 @@ void Camera::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_environment"), &Camera::get_environment);
ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera::set_keep_aspect_mode);
ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera::get_keep_aspect_mode);
- ClassDB::bind_method(D_METHOD("set_vaspect"), &Camera::set_vaspect);
- ClassDB::bind_method(D_METHOD("get_vaspect"), &Camera::get_vaspect);
ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera::set_doppler_tracking);
ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera::get_doppler_tracking);
//ClassDB::bind_method(D_METHOD("_camera_make_current"),&Camera::_camera_make_current );
ADD_PROPERTY(PropertyInfo(Variant::INT, "keep_aspect", PROPERTY_HINT_ENUM, "Keep Width,Keep Height"), "set_keep_aspect_mode", "get_keep_aspect_mode");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vaspect"), "set_vaspect", "get_vaspect");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset");
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index 520afb962b..d69a02afeb 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -148,8 +148,6 @@ public:
void set_keep_aspect_mode(KeepAspect p_aspect);
KeepAspect get_keep_aspect_mode() const;
- void set_vaspect(bool p_vaspect);
- bool get_vaspect() const;
void set_v_offset(float p_offset);
float get_v_offset() const;
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index d0e0937eca..3d40bb299a 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -180,6 +180,9 @@ void Skeleton::_notification(int p_what) {
rest_global_inverse_dirty = false;
}
+ Transform global_transform = get_global_transform();
+ Transform global_transform_inverse = global_transform.affine_inverse();
+
for (int i = 0; i < len; i++) {
Bone &b = bonesptr[i];
@@ -239,7 +242,9 @@ void Skeleton::_notification(int p_what) {
}
}
- vs->skeleton_bone_set_transform(skeleton, i, b.pose_global * b.rest_global_inverse);
+ Transform transform = b.pose_global * b.rest_global_inverse;
+
+ vs->skeleton_bone_set_transform(skeleton, i, global_transform * (transform * global_transform_inverse));
for (List<uint32_t>::Element *E = b.nodes_bound.front(); E; E = E->next()) {
diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp
index 96ac5e8a05..bf0f801e32 100644
--- a/scene/3d/voxel_light_baker.cpp
+++ b/scene/3d/voxel_light_baker.cpp
@@ -1,5 +1,41 @@
+/*************************************************************************/
+/* voxel_light_baker.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
#include "voxel_light_baker.h"
#include "os/os.h"
+
+#include <stdlib.h>
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
#define FINDMINMAX(x0, x1, x2, min, max) \
min = max = x0; \
if (x1 < min) min = x1; \
@@ -183,14 +219,23 @@ static bool fast_tri_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalf
return true; /* box and triangle overlaps */
}
-static _FORCE_INLINE_ Vector2 get_uv(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv) {
+static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) {
- if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2)
- return p_uv[0];
- if (p_pos.distance_squared_to(p_vtx[1]) < CMP_EPSILON2)
- return p_uv[1];
- if (p_pos.distance_squared_to(p_vtx[2]) < CMP_EPSILON2)
- return p_uv[2];
+ if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) {
+ r_uv = p_uv[0];
+ r_normal = p_normal[0];
+ return;
+ }
+ if (p_pos.distance_squared_to(p_vtx[1]) < CMP_EPSILON2) {
+ r_uv = p_uv[1];
+ r_normal = p_normal[1];
+ return;
+ }
+ if (p_pos.distance_squared_to(p_vtx[2]) < CMP_EPSILON2) {
+ r_uv = p_uv[2];
+ r_normal = p_normal[2];
+ return;
+ }
Vector3 v0 = p_vtx[1] - p_vtx[0];
Vector3 v1 = p_vtx[2] - p_vtx[0];
@@ -202,16 +247,20 @@ static _FORCE_INLINE_ Vector2 get_uv(const Vector3 &p_pos, const Vector3 *p_vtx,
float d20 = v2.dot(v0);
float d21 = v2.dot(v1);
float denom = (d00 * d11 - d01 * d01);
- if (denom == 0)
- return p_uv[0];
+ if (denom == 0) {
+ r_uv = p_uv[0];
+ r_normal = p_normal[0];
+ return;
+ }
float v = (d11 * d20 - d01 * d21) / denom;
float w = (d00 * d21 - d01 * d20) / denom;
float u = 1.0f - v - w;
- return p_uv[0] * u + p_uv[1] * v + p_uv[2] * w;
+ r_uv = p_uv[0] * u + p_uv[1] * v + p_uv[2] * w;
+ r_normal = (p_normal[0] * u + p_normal[1] * v + p_normal[2] * w).normalized();
}
-void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb) {
+void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector3 *p_normal, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb) {
if (p_level == cell_subdiv - 1) {
//plot the face by guessing it's albedo and emission value
@@ -289,7 +338,11 @@ void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p
intersection = Face3(p_vtx[0], p_vtx[1], p_vtx[2]).get_closest_point_to(intersection);
- Vector2 uv = get_uv(intersection, p_vtx, p_uv);
+ Vector2 uv;
+ Vector3 lnormal;
+ get_uv_and_normal(intersection, p_vtx, p_uv, p_normal, uv, lnormal);
+ if (lnormal == Vector3()) //just in case normal as nor provided
+ lnormal = normal;
int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
@@ -304,7 +357,7 @@ void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p
emission_accum.g += p_material.emission[ofs].g;
emission_accum.b += p_material.emission[ofs].b;
- normal_accum += normal;
+ normal_accum += lnormal;
alpha += 1.0;
}
@@ -316,7 +369,11 @@ void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p
Face3 f(p_vtx[0], p_vtx[1], p_vtx[2]);
Vector3 inters = f.get_closest_point_to(p_aabb.position + p_aabb.size * 0.5);
- Vector2 uv = get_uv(inters, p_vtx, p_uv);
+ Vector3 lnormal;
+ Vector2 uv;
+ get_uv_and_normal(inters, p_vtx, p_uv, p_normal, uv, normal);
+ if (lnormal == Vector3()) //just in case normal as nor provided
+ lnormal = normal;
int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
@@ -334,7 +391,7 @@ void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p
emission_accum.g = p_material.emission[ofs].g * alpha;
emission_accum.b = p_material.emission[ofs].b * alpha;
- normal_accum *= alpha;
+ normal_accum = lnormal * alpha;
} else {
@@ -415,7 +472,7 @@ void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p
bake_cells[child_idx].level = p_level + 1;
}
- _plot_face(bake_cells[p_idx].childs[i], p_level + 1, nx, ny, nz, p_vtx, p_uv, p_material, aabb);
+ _plot_face(bake_cells[p_idx].childs[i], p_level + 1, nx, ny, nz, p_vtx, p_normal, p_uv, p_material, aabb);
}
}
}
@@ -539,9 +596,12 @@ void VoxelLightBaker::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, con
PoolVector<Vector3>::Read vr = vertices.read();
PoolVector<Vector2> uv = a[Mesh::ARRAY_TEX_UV];
PoolVector<Vector2>::Read uvr;
+ PoolVector<Vector3> normals = a[Mesh::ARRAY_NORMAL];
+ PoolVector<Vector3>::Read nr;
PoolVector<int> index = a[Mesh::ARRAY_INDEX];
bool read_uv = false;
+ bool read_normals = false;
if (uv.size()) {
@@ -549,6 +609,11 @@ void VoxelLightBaker::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, con
read_uv = true;
}
+ if (normals.size()) {
+ read_normals = true;
+ nr = normals.read();
+ }
+
if (index.size()) {
int facecount = index.size() / 3;
@@ -558,6 +623,7 @@ void VoxelLightBaker::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, con
Vector3 vtxs[3];
Vector2 uvs[3];
+ Vector3 normal[3];
for (int k = 0; k < 3; k++) {
vtxs[k] = p_xform.xform(vr[ir[j * 3 + k]]);
@@ -569,11 +635,17 @@ void VoxelLightBaker::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, con
}
}
+ if (read_normals) {
+ for (int k = 0; k < 3; k++) {
+ normal[k] = nr[ir[j * 3 + k]];
+ }
+ }
+
//test against original bounds
if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
continue;
//plot
- _plot_face(0, 0, 0, 0, 0, vtxs, uvs, material, po2_bounds);
+ _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds);
}
} else {
@@ -584,6 +656,7 @@ void VoxelLightBaker::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, con
Vector3 vtxs[3];
Vector2 uvs[3];
+ Vector3 normal[3];
for (int k = 0; k < 3; k++) {
vtxs[k] = p_xform.xform(vr[j * 3 + k]);
@@ -595,11 +668,17 @@ void VoxelLightBaker::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, con
}
}
+ if (read_normals) {
+ for (int k = 0; k < 3; k++) {
+ normal[k] = nr[j * 3 + k];
+ }
+ }
+
//test against original bounds
if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
continue;
//plot face
- _plot_face(0, 0, 0, 0, 0, vtxs, uvs, material, po2_bounds);
+ _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds);
}
}
}
@@ -1600,19 +1679,17 @@ Vector3 VoxelLightBaker::_compute_pixel_light_at_pos(const Vector3 &p_pos, const
return accum;
}
-uint32_t xorshiftstate[] = { 123 }; // anything non-zero will do here
-
-_ALWAYS_INLINE_ uint32_t xorshift32() {
+_ALWAYS_INLINE_ uint32_t xorshift32(uint32_t *state) {
/* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
- uint32_t x = xorshiftstate[0];
+ uint32_t x = *state;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
- xorshiftstate[0] = x;
+ *state = x;
return x;
}
-Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal) {
+Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal, uint32_t *rng_state) {
int samples_per_quality[3] = { 48, 128, 512 };
@@ -1634,20 +1711,23 @@ Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const V
const Light *light = bake_light.ptr();
const Cell *cells = bake_cells.ptr();
+ // Prevent false sharing when running on OpenMP
+ uint32_t local_rng_state = *rng_state;
+
for (int i = 0; i < samples; i++) {
- float random_angle1 = (((xorshift32() % 65535) / 65535.0) * 2.0 - 1.0) * spread;
+ float random_angle1 = (((xorshift32(&local_rng_state) % 65535) / 65535.0) * 2.0 - 1.0) * spread;
Vector3 axis(0, sin(random_angle1), cos(random_angle1));
- float random_angle2 = ((xorshift32() % 65535) / 65535.0) * Math_PI * 2.0;
+ float random_angle2 = ((xorshift32(&local_rng_state) % 65535) / 65535.0) * Math_PI * 2.0;
Basis rot(Vector3(0, 0, 1), random_angle2);
axis = rot.xform(axis);
Vector3 direction = normal_xform.xform(axis).normalized();
- Vector3 pos = p_pos + Vector3(0.5, 0.5, 0.5) + direction * bias;
-
Vector3 advance = direction * _get_normal_advance(direction);
+ Vector3 pos = p_pos /*+ Vector3(0.5, 0.5, 0.5)*/ + advance * bias;
+
uint32_t cell = CHILD_EMPTY;
while (cell == CHILD_EMPTY) {
@@ -1709,9 +1789,14 @@ Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const V
accum.y += light[cell].accum[i][1] * amount;
accum.z += light[cell].accum[i][2] * amount;
}
+ accum.x += cells[cell].emission[0];
+ accum.y += cells[cell].emission[1];
+ accum.z += cells[cell].emission[2];
}
}
+ // Make sure we don't reset this thread's RNG state
+ *rng_state = local_rng_state;
return accum / samples;
}
@@ -1758,6 +1843,7 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh
Vector3 vertex[3];
Vector3 normal[3];
Vector2 uv[3];
+
for (int j = 0; j < 3; j++) {
int idx = ic ? ir[i * 3 + j] : i * 3 + j;
vertex[j] = xform.xform(vr[idx]);
@@ -1768,21 +1854,43 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh
_plot_triangle(uv, vertex, normal, lightmap.ptrw(), width, height);
}
}
- //step 3 perform voxel cone trace on lightmap pixels
+ //step 3 perform voxel cone trace on lightmap pixels
{
LightMap *lightmap_ptr = lightmap.ptrw();
uint64_t begin_time = OS::get_singleton()->get_ticks_usec();
volatile int lines = 0;
+ // make sure our OS-level rng is seeded
+ srand(OS::get_singleton()->get_ticks_usec());
+
+ // setup an RNG state for each OpenMP thread
+ uint32_t threadcount = 1;
+ uint32_t threadnum = 0;
+#ifdef _OPENMP
+ threadcount = omp_get_max_threads();
+#endif
+ Vector<uint32_t> rng_states;
+ rng_states.resize(threadcount);
+ for (uint32_t i = 0; i < threadcount; i++) {
+ do {
+ rng_states[i] = rand();
+ } while (rng_states[i] == 0);
+ }
+ uint32_t *rng_states_p = rng_states.ptrw();
+
for (int i = 0; i < height; i++) {
//print_line("bake line " + itos(i) + " / " + itos(height));
#ifdef _OPENMP
-#pragma omp parallel for schedule(dynamic, 1)
+#pragma omp parallel for schedule(dynamic, 1) private(threadnum)
#endif
for (int j = 0; j < width; j++) {
+#ifdef _OPENMP
+ threadnum = omp_get_thread_num();
+#endif
+
//if (i == 125 && j == 280) {
LightMap *pixel = &lightmap_ptr[i * width + j];
@@ -1795,7 +1903,7 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh
pixel->light = _compute_pixel_light_at_pos(pixel->pos, pixel->normal) * energy;
} break;
case BAKE_MODE_RAY_TRACE: {
- pixel->light = _compute_ray_trace_at_pos(pixel->pos, pixel->normal) * energy;
+ pixel->light = _compute_ray_trace_at_pos(pixel->pos, pixel->normal, &rng_states_p[threadnum]) * energy;
} break;
// pixel->light = Vector3(1, 1, 1);
//}
diff --git a/scene/3d/voxel_light_baker.h b/scene/3d/voxel_light_baker.h
index 6dee2ee69b..7db31f8a67 100644
--- a/scene/3d/voxel_light_baker.h
+++ b/scene/3d/voxel_light_baker.h
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* voxel_light_baker.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
#ifndef VOXEL_LIGHT_BAKER_H
#define VOXEL_LIGHT_BAKER_H
@@ -99,7 +129,8 @@ private:
Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add);
MaterialCache _get_material_cache(Ref<Material> p_material);
- void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb);
+
+ void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector3 *p_normal, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb);
void _fixup_plot(int p_idx, int p_level);
void _debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, DebugMode p_mode);
void _check_init_light();
@@ -117,7 +148,7 @@ private:
_FORCE_INLINE_ void _sample_baked_octree_filtered_and_anisotropic(const Vector3 &p_posf, const Vector3 &p_direction, float p_level, Vector3 &r_color, float &r_alpha);
_FORCE_INLINE_ Vector3 _voxel_cone_trace(const Vector3 &p_pos, const Vector3 &p_normal, float p_aperture);
_FORCE_INLINE_ Vector3 _compute_pixel_light_at_pos(const Vector3 &p_pos, const Vector3 &p_normal);
- _FORCE_INLINE_ Vector3 _compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal);
+ _FORCE_INLINE_ Vector3 _compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal, uint32_t *rng_state);
public:
void begin_bake(int p_subdiv, const AABB &p_bounds);
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 148277f2dd..a67fe2aeeb 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -450,11 +450,11 @@ String BaseButton::get_tooltip(const Point2 &p_pos) const {
String tooltip = Control::get_tooltip(p_pos);
if (shortcut.is_valid() && shortcut->is_valid()) {
- if (tooltip.find("$sc") != -1) {
- tooltip = tooltip.replace_first("$sc", "(" + shortcut->get_as_text() + ")");
- } else {
- tooltip += " (" + shortcut->get_as_text() + ")";
+ String text = shortcut->get_name() + " (" + shortcut->get_as_text() + ")";
+ if (shortcut->get_name().nocasecmp_to(tooltip) != 0) {
+ text += "\n" + tooltip;
}
+ tooltip = text;
}
return tooltip;
}
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index e1f77594da..51a25c60a1 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -207,7 +207,7 @@ void Label::_notification(int p_what) {
} break;
}
- int y_ofs = style->get_offset().y;
+ float y_ofs = style->get_offset().y;
y_ofs += (line - lines_skipped) * font_h + font->get_ascent();
y_ofs += vbegin + line * vsep;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index deb40800bc..7c31b72bb5 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -38,6 +38,7 @@
#include "os/os.h"
#include "print_string.h"
#include "project_settings.h"
+#include "scene/resources/dynamic_font.h"
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
#include "scene/resources/packed_scene.h"
@@ -495,6 +496,11 @@ bool SceneTree::idle(float p_time) {
Size2 win_size = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height);
if (win_size != last_screen_size) {
+ if (use_font_oversampling) {
+ DynamicFontAtSize::font_oversampling = OS::get_singleton()->get_window_size().width / root->get_visible_rect().size.width;
+ DynamicFont::update_oversampling();
+ }
+
last_screen_size = win_size;
_update_root_rect();
@@ -2195,6 +2201,9 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("_connection_failed"), &SceneTree::_connection_failed);
ClassDB::bind_method(D_METHOD("_server_disconnected"), &SceneTree::_server_disconnected);
+ ClassDB::bind_method(D_METHOD("set_use_font_oversampling", "enable"), &SceneTree::set_use_font_oversampling);
+ ClassDB::bind_method(D_METHOD("is_using_font_oversampling"), &SceneTree::is_using_font_oversampling);
+
ADD_SIGNAL(MethodInfo("tree_changed"));
ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node")));
ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node")));
@@ -2244,6 +2253,20 @@ void SceneTree::add_idle_callback(IdleCallback p_callback) {
idle_callbacks[idle_callback_count++] = p_callback;
}
+void SceneTree::set_use_font_oversampling(bool p_oversampling) {
+
+ use_font_oversampling = p_oversampling;
+ if (use_font_oversampling) {
+ DynamicFontAtSize::font_oversampling = OS::get_singleton()->get_window_size().width / root->get_visible_rect().size.width;
+ } else {
+ DynamicFontAtSize::font_oversampling = 1.0;
+ }
+}
+
+bool SceneTree::is_using_font_oversampling() const {
+ return use_font_oversampling;
+}
+
SceneTree::SceneTree() {
singleton = this;
@@ -2327,7 +2350,7 @@ SceneTree::SceneTree() {
ProjectSettings::get_singleton()->set("rendering/environment/default_environment", "");
} else {
//file was erased, notify user.
- ERR_PRINTS(RTR("Default Environment as specified in Project Setings (Rendering -> Viewport -> Default Environment) could not be loaded."));
+ ERR_PRINTS(RTR("Default Environment as specified in Project Setings (Rendering -> Environment -> Default Environment) could not be loaded."));
}
}
}
@@ -2380,6 +2403,8 @@ SceneTree::SceneTree() {
last_send_cache_id = 1;
#endif
+
+ use_font_oversampling = false;
}
SceneTree::~SceneTree() {
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 244fc8da62..9c5b0f69cb 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -122,11 +122,13 @@ private:
bool _quit;
bool initialized;
bool input_handled;
+
Size2 last_screen_size;
StringName tree_changed_name;
StringName node_added_name;
StringName node_removed_name;
+ bool use_font_oversampling;
int64_t current_frame;
int node_count;
@@ -420,6 +422,9 @@ public:
void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, real_t p_shrink = 1);
+ void set_use_font_oversampling(bool p_oversampling);
+ bool is_using_font_oversampling() const;
+
//void change_scene(const String& p_path);
//Node *get_loaded_scene();
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index f5d7043a40..8f431389d8 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1659,6 +1659,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
//cancel event, sorry, modal exclusive EATS UP ALL
//alternative, you can't pop out a window the same frame it was made modal (fixes many issues)
get_tree()->set_input_as_handled();
+
return; // no one gets the event if exclusive NO ONE
}
@@ -1807,15 +1808,18 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
pos = gui.focus_inv_xform.xform(pos);
mb->set_position(pos);
- if (gui.mouse_focus->can_process()) {
- _gui_call_input(gui.mouse_focus, mb);
- }
+ Control *mouse_focus = gui.mouse_focus;
+ //disable mouse focus if needed before calling input, this makes popups on mouse press event work better, as the release will never be received otherwise
if (mb->get_button_index() == gui.mouse_focus_button) {
gui.mouse_focus = NULL;
gui.mouse_focus_button = -1;
}
+ if (mouse_focus->can_process()) {
+ _gui_call_input(mouse_focus, mb);
+ }
+
/*if (gui.drag_data.get_type()!=Variant::NIL && mb->get_button_index()==BUTTON_LEFT) {
_propagate_viewport_notification(this,NOTIFICATION_DRAG_END);
gui.drag_data=Variant(); //always clear
@@ -2348,7 +2352,6 @@ void Viewport::_gui_control_grab_focus(Control *p_control) {
//no need for change
if (gui.key_focus && gui.key_focus == p_control)
return;
-
get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "_viewports", "_gui_remove_focus");
gui.key_focus = p_control;
p_control->notification(Control::NOTIFICATION_FOCUS_ENTER);
@@ -2370,6 +2373,21 @@ List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) {
else
p_control->_modal_set_prev_focus_owner(0);
+ if (gui.mouse_focus && !p_control->is_a_parent_of(gui.mouse_focus)) {
+ Ref<InputEventMouseButton> mb;
+ mb.instance();
+ mb->set_position(gui.mouse_focus->get_local_mouse_position());
+ mb->set_global_position(gui.mouse_focus->get_local_mouse_position());
+ mb->set_button_index(gui.mouse_focus_button);
+ mb->set_pressed(false);
+ gui.mouse_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb);
+
+ //if (gui.mouse_over == gui.mouse_focus) {
+ // gui.mouse_focus->notification(Control::NOTIFICATION_MOUSE_EXIT);
+ //}
+ gui.mouse_focus = NULL;
+ }
+
return gui.modal_stack.back();
}
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 246283edcc..39e6698725 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -542,6 +542,8 @@ void register_scene_types() {
ClassDB::register_class<DynamicFontData>();
ClassDB::register_class<DynamicFont>();
+ DynamicFont::initialize_dynamic_fonts();
+
ClassDB::register_virtual_class<StyleBox>();
ClassDB::register_class<StyleBoxEmpty>();
ClassDB::register_class<StyleBoxTexture>();
@@ -621,6 +623,8 @@ void unregister_scene_types() {
memdelete(resource_loader_stream_texture);
memdelete(resource_loader_theme);
+ DynamicFont::finish_dynamic_fonts();
+
if (resource_saver_text) {
memdelete(resource_saver_text);
}
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index a40417f24d..66b1e49d13 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -191,10 +191,10 @@ Error DynamicFontAtSize::_load() {
ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER );
}*/
- error = FT_Set_Pixel_Sizes(face, 0, id.size);
+ error = FT_Set_Pixel_Sizes(face, 0, id.size * oversampling);
- ascent = face->size->metrics.ascender >> 6;
- descent = -face->size->metrics.descender >> 6;
+ ascent = (face->size->metrics.ascender >> 6) / oversampling;
+ descent = (-face->size->metrics.descender >> 6) / oversampling;
linegap = 0;
texture_flags = 0;
if (id.mipmaps)
@@ -208,6 +208,8 @@ Error DynamicFontAtSize::_load() {
return OK;
}
+float DynamicFontAtSize::font_oversampling = 1.0;
+
float DynamicFontAtSize::get_height() const {
return ascent + descent;
@@ -282,11 +284,11 @@ Size2 DynamicFontAtSize::get_char_size(CharType p_char, CharType p_next, const V
if (delta.x == 0)
continue;
- ret.x += delta.x >> 6;
+ ret.x += (delta.x >> 6) / oversampling;
break;
}
} else {
- ret.x += delta.x >> 6;
+ ret.x += (delta.x >> 6) / oversampling;
}
}
@@ -338,7 +340,7 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT
cpos.y += ch->v_align;
ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= fb->textures.size(), 0);
if (ch->texture_idx != -1)
- VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect, p_modulate, false, RID(), false);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect_uv, p_modulate, false, RID(), false);
advance = ch->advance;
used_fallback = true;
break;
@@ -360,7 +362,7 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT
cpos.y += c->v_align;
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), 0);
if (c->texture_idx != -1)
- VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx].texture->get_rid(), c->rect, p_modulate, false, RID(), false);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx].texture->get_rid(), c->rect_uv, p_modulate, false, RID(), false);
advance = c->advance;
//textures[c->texture_idx].texture->draw(p_canvas_item,Vector2());
}
@@ -382,11 +384,11 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT
if (delta.x == 0)
continue;
- advance += delta.x >> 6;
+ advance += (delta.x >> 6) / oversampling;
break;
}
} else {
- advance += delta.x >> 6;
+ advance += (delta.x >> 6) / oversampling;
}
}
@@ -602,19 +604,37 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
}
Character chr;
- chr.h_align = xofs;
- chr.v_align = ascent - yofs; // + ascent - descent;
- chr.advance = advance;
+ chr.h_align = xofs / oversampling;
+ chr.v_align = ascent - (yofs / oversampling); // + ascent - descent;
+ chr.advance = advance / oversampling;
chr.texture_idx = tex_index;
chr.found = true;
- chr.rect = Rect2(tex_x + rect_margin, tex_y + rect_margin, w, h);
+ chr.rect_uv = Rect2(tex_x + rect_margin, tex_y + rect_margin, w, h);
+ chr.rect = chr.rect_uv;
+ chr.rect.position /= oversampling;
+ chr.rect.size /= oversampling;
//print_line("CHAR: "+String::chr(p_char)+" TEX INDEX: "+itos(tex_index)+" RECT: "+chr.rect+" X OFS: "+itos(xofs)+" Y OFS: "+itos(yofs));
char_map[p_char] = chr;
}
+bool DynamicFontAtSize::update_oversampling() {
+ if (oversampling == font_oversampling)
+ return false;
+ if (!valid)
+ return false;
+
+ FT_Done_FreeType(library);
+ textures.clear();
+ char_map.clear();
+ oversampling = font_oversampling;
+ _load();
+
+ return true;
+}
+
DynamicFontAtSize::DynamicFontAtSize() {
valid = false;
@@ -623,6 +643,7 @@ DynamicFontAtSize::DynamicFontAtSize() {
descent = 1;
linegap = 1;
texture_flags = 0;
+ oversampling = font_oversampling;
}
DynamicFontAtSize::~DynamicFontAtSize() {
@@ -913,15 +934,52 @@ void DynamicFont::_bind_methods() {
BIND_ENUM_CONSTANT(SPACING_SPACE);
}
-DynamicFont::DynamicFont() {
+Mutex *DynamicFont::dynamic_font_mutex = NULL;
+
+SelfList<DynamicFont>::List DynamicFont::dynamic_fonts;
+
+DynamicFont::DynamicFont() :
+ font_list(this) {
spacing_top = 0;
spacing_bottom = 0;
spacing_char = 0;
spacing_space = 0;
+ if (dynamic_font_mutex)
+ dynamic_font_mutex->lock();
+ dynamic_fonts.add(&font_list);
+ if (dynamic_font_mutex)
+ dynamic_font_mutex->unlock();
}
DynamicFont::~DynamicFont() {
+
+ if (dynamic_font_mutex)
+ dynamic_font_mutex->lock();
+ dynamic_fonts.remove(&font_list);
+ if (dynamic_font_mutex)
+ dynamic_font_mutex->unlock();
+}
+
+void DynamicFont::initialize_dynamic_fonts() {
+ dynamic_font_mutex = Mutex::create();
+}
+
+void DynamicFont::finish_dynamic_fonts() {
+ memdelete(dynamic_font_mutex);
+ dynamic_font_mutex = NULL;
+}
+
+void DynamicFont::update_oversampling() {
+
+ SelfList<DynamicFont> *E = dynamic_fonts.first();
+ while (E) {
+
+ if (E->self()->data_at_size.is_valid() && E->self()->data_at_size->update_oversampling()) {
+ E->self()->emit_changed();
+ }
+ E = E->next();
+ }
}
/////////////////////////
diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h
index 52c3f30590..b2452a6a0a 100644
--- a/scene/resources/dynamic_font.h
+++ b/scene/resources/dynamic_font.h
@@ -32,6 +32,7 @@
#ifdef FREETYPE_ENABLED
#include "io/resource_loader.h"
+#include "os/mutex.h"
#include "os/thread_safe.h"
#include "scene/resources/font.h"
@@ -97,10 +98,11 @@ class DynamicFontAtSize : public Reference {
FT_Face face; /* handle to face object */
FT_StreamRec stream;
- int ascent;
- int descent;
- int linegap;
- int rect_margin;
+ float ascent;
+ float descent;
+ float linegap;
+ float rect_margin;
+ float oversampling;
uint32_t texture_flags;
@@ -121,6 +123,7 @@ class DynamicFontAtSize : public Reference {
bool found;
int texture_idx;
Rect2 rect;
+ Rect2 rect_uv;
float v_align;
float h_align;
float advance;
@@ -145,8 +148,9 @@ class DynamicFontAtSize : public Reference {
static HashMap<String, Vector<uint8_t> > _fontdata;
Error _load();
-protected:
public:
+ static float font_oversampling;
+
float get_height() const;
float get_ascent() const;
@@ -157,6 +161,7 @@ public:
float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks) const;
void set_texture_flags(uint32_t p_flags);
+ bool update_oversampling();
DynamicFontAtSize();
~DynamicFontAtSize();
@@ -232,6 +237,15 @@ public:
virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1)) const;
+ SelfList<DynamicFont> font_list;
+
+ static Mutex *dynamic_font_mutex;
+ static SelfList<DynamicFont>::List dynamic_fonts;
+
+ static void initialize_dynamic_fonts();
+ static void finish_dynamic_fonts();
+ static void update_oversampling();
+
DynamicFont();
~DynamicFont();
};
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 2b44ea4554..8510669d6c 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -257,8 +257,8 @@ Error BitmapFont::create_from_fnt(const String &p_file) {
if (keys.has("file")) {
- String file = keys["file"];
- file = p_file.get_base_dir() + "/" + file;
+ String base_dir = p_file.get_base_dir();
+ String file = base_dir.plus_file(keys["file"]);
Ref<Texture> tex = ResourceLoader::load(file);
if (tex.is_null()) {
ERR_PRINT("Can't load font texture!");