summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/area_2d.cpp6
-rw-r--r--scene/2d/light_2d.cpp6
-rw-r--r--scene/2d/polygon_2d.cpp27
-rw-r--r--scene/2d/polygon_2d.h4
-rw-r--r--scene/3d/mesh_instance.cpp87
-rw-r--r--scene/3d/mesh_instance.h5
-rw-r--r--scene/gui/box_container.cpp1
-rw-r--r--scene/gui/dialogs.cpp87
-rw-r--r--scene/gui/dialogs.h7
-rw-r--r--scene/gui/item_list.cpp64
-rw-r--r--scene/gui/item_list.h14
-rw-r--r--scene/gui/tab_container.cpp5
-rw-r--r--scene/gui/text_edit.cpp160
-rw-r--r--scene/gui/text_edit.h22
-rw-r--r--scene/gui/texture_frame.cpp46
-rw-r--r--scene/gui/texture_frame.h15
-rw-r--r--scene/main/scene_main_loop.cpp10
-rw-r--r--scene/main/scene_main_loop.h1
-rw-r--r--scene/register_scene_types.cpp5
-rw-r--r--scene/resources/default_theme/default_theme.cpp277
-rw-r--r--scene/resources/default_theme/default_theme.h2
-rw-r--r--scene/resources/dynamic_font.cpp301
-rw-r--r--scene/resources/dynamic_font.h76
-rw-r--r--scene/resources/dynamic_font_stb.cpp527
-rw-r--r--scene/resources/dynamic_font_stb.h178
-rw-r--r--scene/resources/mesh.cpp5
-rw-r--r--scene/scene_string_names.cpp7
-rw-r--r--scene/scene_string_names.h6
28 files changed, 1580 insertions, 371 deletions
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index 8b7aff3b7a..71728966fd 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -660,9 +660,9 @@ void Area2D::_bind_methods() {
ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point"));
ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_gravity"),_SCS("get_gravity"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_linear_damp"),_SCS("get_linear_damp"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_angular_damp"),_SCS("get_angular_damp"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.001"),_SCS("set_gravity"),_SCS("get_gravity"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,100,0.01"),_SCS("set_linear_damp"),_SCS("get_linear_damp"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,100,0.01"),_SCS("set_angular_damp"),_SCS("get_angular_damp"));
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable"));
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index b79c07360b..1cb34075bb 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -357,11 +357,11 @@ void Light2D::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,4096,0.01"),_SCS("set_texture_scale"),_SCS("get_texture_scale"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,50,0.01"),_SCS("set_texture_scale"),_SCS("get_texture_scale"));
ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy"),_SCS("set_energy"),_SCS("get_energy"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy",PROPERTY_HINT_RANGE,"0.01,100,0.01"),_SCS("set_energy"),_SCS("get_energy"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Add,Sub,Mix,Mask"),_SCS("set_mode"),_SCS("get_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height",PROPERTY_HINT_RANGE,"-100,100,0.1"),_SCS("set_height"),_SCS("get_height"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min"));
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index fc6986327f..03ced12c55 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -145,7 +145,18 @@ void Polygon2D::_notification(int p_what) {
Vector<Color> colors;
- colors.push_back(color);
+ int color_len=vertex_colors.size();
+ colors.resize(len);
+ {
+ DVector<Color>::Read color_r=vertex_colors.read();
+ for(int i=0;i<color_len && i<len;i++){
+ colors[i]=color_r[i];
+ }
+ for(int i=color_len;i<len;i++){
+ colors[i]=color;
+ }
+ }
+
Vector<int> indices = Geometry::triangulate_polygon(points);
VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(),indices,points,colors,uvs,texture.is_valid()?texture->get_rid():RID());
@@ -188,6 +199,16 @@ Color Polygon2D::get_color() const{
return color;
}
+void Polygon2D::set_vertex_colors(const DVector<Color>& p_colors){
+
+ vertex_colors=p_colors;
+ update();
+}
+DVector<Color> Polygon2D::get_vertex_colors() const{
+
+ return vertex_colors;
+}
+
void Polygon2D::set_texture(const Ref<Texture>& p_texture){
texture=p_texture;
@@ -293,6 +314,9 @@ void Polygon2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_color","color"),&Polygon2D::set_color);
ObjectTypeDB::bind_method(_MD("get_color"),&Polygon2D::get_color);
+ ObjectTypeDB::bind_method(_MD("set_vertex_colors","vertex_colors"),&Polygon2D::set_vertex_colors);
+ ObjectTypeDB::bind_method(_MD("get_vertex_colors"),&Polygon2D::get_vertex_colors);
+
ObjectTypeDB::bind_method(_MD("set_texture","texture"),&Polygon2D::set_texture);
ObjectTypeDB::bind_method(_MD("get_texture"),&Polygon2D::get_texture);
@@ -323,6 +347,7 @@ void Polygon2D::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"uv"),_SCS("set_uv"),_SCS("get_uv"));
ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
+ ADD_PROPERTY( PropertyInfo(Variant::COLOR_ARRAY,"vertex_colors"),_SCS("set_vertex_colors"),_SCS("get_vertex_colors"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_offset"),_SCS("get_offset"));
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture/offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h
index 517b623ccd..eaa642787c 100644
--- a/scene/2d/polygon_2d.h
+++ b/scene/2d/polygon_2d.h
@@ -9,6 +9,7 @@ class Polygon2D : public Node2D {
DVector<Vector2> polygon;
DVector<Vector2> uv;
+ DVector<Color> vertex_colors;
Color color;
Ref<Texture> texture;
Vector2 tex_scale;
@@ -40,6 +41,9 @@ public:
void set_color(const Color& p_color);
Color get_color() const;
+ void set_vertex_colors(const DVector<Color>& p_colors);
+ DVector<Color> get_vertex_colors() const;
+
void set_texture(const Ref<Texture>& p_texture);
Ref<Texture> get_texture() const;
diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp
index cfe273fa20..ef956e8ad9 100644
--- a/scene/3d/mesh_instance.cpp
+++ b/scene/3d/mesh_instance.cpp
@@ -31,8 +31,8 @@
#include "skeleton.h"
#include "physics_body.h"
#include "body_shape.h"
-
-
+#include "scene/scene_string_names.h"
+#include "core_string_names.h"
bool MeshInstance::_set(const StringName& p_name, const Variant& p_value) {
//this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else.
@@ -43,13 +43,22 @@ bool MeshInstance::_set(const StringName& p_name, const Variant& p_value) {
Map<StringName,MorphTrack>::Element *E = morph_tracks.find(p_name);
- if (!E)
- return false;
+ if (E) {
+ E->get().value=p_value;
+ VisualServer::get_singleton()->instance_set_morph_target_weight(get_instance(),E->get().idx,E->get().value);
+ return true;
+ }
- E->get().value=p_value;
- VisualServer::get_singleton()->instance_set_morph_target_weight(get_instance(),E->get().idx,E->get().value);
+ if (p_name.operator String().begins_with("material/")) {
+ int idx = p_name.operator String().get_slicec('/',1).to_int();
+ if (idx>=materials.size() || idx<0)
+ return false;
- return true;
+ set_surface_material(idx,p_value);
+ return true;
+ }
+
+ return false;
}
bool MeshInstance::_get(const StringName& p_name,Variant &r_ret) const {
@@ -59,12 +68,19 @@ bool MeshInstance::_get(const StringName& p_name,Variant &r_ret) const {
return false;
const Map<StringName,MorphTrack>::Element *E = morph_tracks.find(p_name);
- if (!E)
- return false;
-
- r_ret = E->get().value;
+ if (E) {
+ r_ret = E->get().value;
+ return true;
+ }
- return true;
+ if (p_name.operator String().begins_with("material/")) {
+ int idx = p_name.operator String().get_slicec('/',1).to_int();
+ if (idx>=materials.size() || idx<0)
+ return false;
+ r_ret=materials[idx];
+ return true;
+ }
+ return false;
}
void MeshInstance::_get_property_list( List<PropertyInfo> *p_list) const {
@@ -80,6 +96,12 @@ void MeshInstance::_get_property_list( List<PropertyInfo> *p_list) const {
for(List<String>::Element *E=ls.front();E;E=E->next()) {
p_list->push_back( PropertyInfo(Variant::REAL,E->get(),PROPERTY_HINT_RANGE,"0,1,0.01"));
}
+
+ if (mesh.is_valid()) {
+ for(int i=0;i<mesh->get_surface_count();i++) {
+ p_list->push_back( PropertyInfo(Variant::OBJECT, "material/"+itos(i), PROPERTY_HINT_RESOURCE_TYPE, "Material"));
+ }
+ }
}
@@ -87,6 +109,14 @@ void MeshInstance::_get_property_list( List<PropertyInfo> *p_list) const {
void MeshInstance::set_mesh(const Ref<Mesh>& p_mesh) {
+ if (mesh==p_mesh)
+ return;
+
+ if (mesh.is_valid()) {
+ mesh->disconnect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_mesh_changed);
+ materials.clear();
+ }
+
mesh=p_mesh;
morph_tracks.clear();
@@ -100,13 +130,17 @@ void MeshInstance::set_mesh(const Ref<Mesh>& p_mesh) {
mt.value=0;
morph_tracks["morph/"+String(mesh->get_morph_target_name(i))]=mt;
}
+
+ mesh->connect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_mesh_changed);
+ materials.resize(mesh->get_surface_count());
+
set_base(mesh->get_rid());
} else {
set_base(RID());
}
- _change_notify("mesh");
+ _change_notify();
}
Ref<Mesh> MeshInstance::get_mesh() const {
@@ -232,6 +266,32 @@ void MeshInstance::_notification(int p_what) {
}
+void MeshInstance::set_surface_material(int p_surface,const Ref<Material>& p_material) {
+
+ ERR_FAIL_INDEX(p_surface,materials.size());
+
+ materials[p_surface]=p_material;
+
+ if (materials[p_surface].is_valid())
+ VS::get_singleton()->instance_set_surface_material(get_instance(),p_surface,materials[p_surface]->get_rid());
+ else
+ VS::get_singleton()->instance_set_surface_material(get_instance(),p_surface,RID());
+
+}
+
+Ref<Material> MeshInstance::get_surface_material(int p_surface) const {
+
+ ERR_FAIL_INDEX_V(p_surface,materials.size(),Ref<Material>());
+
+ return materials[p_surface];
+}
+
+
+void MeshInstance::_mesh_changed() {
+
+ materials.resize( mesh->get_surface_count() );
+}
+
void MeshInstance::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_mesh","mesh:Mesh"),&MeshInstance::set_mesh);
@@ -243,6 +303,7 @@ void MeshInstance::_bind_methods() {
ObjectTypeDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT);
ObjectTypeDB::bind_method(_MD("create_convex_collision"),&MeshInstance::create_convex_collision);
ObjectTypeDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT);
+ ObjectTypeDB::bind_method(_MD("_mesh_changed"),&MeshInstance::_mesh_changed);
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "mesh/mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh" ), _SCS("set_mesh"), _SCS("get_mesh"));
ADD_PROPERTY( PropertyInfo (Variant::NODE_PATH, "mesh/skeleton"), _SCS("set_skeleton_path"), _SCS("get_skeleton_path"));
}
diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h
index 7c605c2d6d..fd8faf38b4 100644
--- a/scene/3d/mesh_instance.h
+++ b/scene/3d/mesh_instance.h
@@ -50,7 +50,9 @@ class MeshInstance : public GeometryInstance {
};
Map<StringName,MorphTrack> morph_tracks;
+ Vector<Ref<Material> > materials;
+ void _mesh_changed();
void _resolve_skeleton_path();
protected:
@@ -69,6 +71,9 @@ public:
void set_skeleton_path(const NodePath& p_skeleton);
NodePath get_skeleton_path();
+ void set_surface_material(int p_surface,const Ref<Material>& p_material);
+ Ref<Material> get_surface_material(int p_surface) const;
+
Node* create_trimesh_collision_node();
void create_trimesh_collision();
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index a9522cf248..a6ffc30a83 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -280,6 +280,7 @@ BoxContainer::AlignMode BoxContainer::get_alignment() const {
void BoxContainer::add_spacer(bool p_begin) {
Control *c = memnew( Control );
+ c->set_stop_mouse(false);
if (vertical)
c->set_v_size_flags(SIZE_EXPAND_FILL);
else
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index 51242d89bd..6342391383 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -118,6 +118,16 @@ void WindowDialog::set_title(const String& p_title) {
update();
}
+Size2 WindowDialog::get_minimum_size() const {
+
+ Ref<Font> font = get_font("title_font","WindowDialog");
+ int msx=close_button->get_combined_minimum_size().x;
+ msx+=font->get_string_size(title).x;
+
+ return Size2(msx,1);
+}
+
+
String WindowDialog::get_title() const {
return title;
@@ -192,11 +202,9 @@ void AcceptDialog::_notification(int p_what) {
if (p_what==NOTIFICATION_MODAL_CLOSE) {
cancel_pressed();
- } if (p_what==NOTIFICATION_DRAW) {
-
-
-
+ } if (p_what==NOTIFICATION_RESIZED) {
+ _update_child_rect();
}
}
@@ -244,12 +252,69 @@ void AcceptDialog::register_text_enter(Node *p_line_edit) {
p_line_edit->connect("text_entered", this,"_builtin_text_entered");
}
+void AcceptDialog::_update_child_rect() {
+
+ int margin = get_constant("margin","Dialogs");
+ Size2 size = get_size();
+ Size2 hminsize = hbc->get_combined_minimum_size();
+
+ Vector2 cpos(margin,margin);
+ Vector2 csize(size.x-margin*2,size.y-margin*3-hminsize.y);
+ label->set_pos(cpos);
+ label->set_size(csize);
+
+ if (child) {
+
+ child->set_pos(cpos);
+ child->set_size(csize);
+ }
+
+ cpos.y+=csize.y+margin;
+ csize.y=hminsize.y;
+
+ hbc->set_pos(cpos);
+ hbc->set_size(csize);
+
+}
+
+Size2 AcceptDialog::get_minimum_size() const {
+
+ int margin = get_constant("margin","Dialogs");
+ Size2 minsize = label->get_combined_minimum_size();
+ if (child) {
+
+ Size2 cminsize = child->get_combined_minimum_size();
+ minsize.x=MAX(cminsize.x,minsize.x);
+ minsize.y=MAX(cminsize.y,minsize.y);
+ }
+
+ Size2 hminsize = hbc->get_combined_minimum_size();
+ minsize.x = MAX(hminsize.x,minsize.x);
+ minsize.y+=hminsize.y;
+ minsize.x+=margin*2;
+ minsize.y+=margin*3; //one as separation between hbc and child
+
+ Size2 wmsize = WindowDialog::get_minimum_size();
+ minsize.x=MAX(wmsize.x,minsize.x);
+ return minsize;
+}
+
+
void AcceptDialog::set_child_rect(Control *p_child) {
ERR_FAIL_COND(p_child->get_parent()!=this);
- p_child->set_area_as_parent_rect(get_constant("margin","Dialogs"));
- p_child->set_margin(MARGIN_BOTTOM, get_constant("button_margin","Dialogs")+10);
+ //p_child->set_area_as_parent_rect(get_constant("margin","Dialogs"));
+ child=p_child;
+ minimum_size_changed();
+ _update_child_rect();
+}
+
+void AcceptDialog::remove_child_notify(Node *p_child) {
+
+ if (p_child==child) {
+ child=NULL;
+ }
}
void AcceptDialog::_custom_action(const String& p_action) {
@@ -284,7 +349,7 @@ Button* AcceptDialog::add_cancel(const String &p_cancel) {
String c = p_cancel;
if (p_cancel=="")
- c="Cancel";
+ c=RTR("Cancel");
Button *b = swap_ok_cancel ? add_button(c,true) : add_button(c);
b->connect("pressed",this,"_closed");
return b;
@@ -341,7 +406,7 @@ AcceptDialog::AcceptDialog() {
hbc->add_spacer();
ok = memnew( Button );
- ok->set_text("OK");
+ ok->set_text(RTR("OK"));
hbc->add_child(ok);
hbc->add_spacer();
//add_child(ok);
@@ -351,7 +416,9 @@ AcceptDialog::AcceptDialog() {
set_as_toplevel(true);
hide_on_ok=true;
- set_title("Alert!");
+ set_title(RTR("Alert!"));
+
+ child=NULL;
}
@@ -372,6 +439,6 @@ Button *ConfirmationDialog::get_cancel() {
ConfirmationDialog::ConfirmationDialog() {
- set_title("Please Confirm...");
+ set_title(RTR("Please Confirm..."));
cancel = add_cancel();
}
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index f256c49aee..d00bb41ff6 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -64,6 +64,8 @@ public:
void set_title(const String& p_title);
String get_title() const;
+ Size2 get_minimum_size() const;
+
WindowDialog();
~WindowDialog();
@@ -89,6 +91,7 @@ class AcceptDialog : public WindowDialog {
OBJ_TYPE(AcceptDialog,WindowDialog);
+ Control *child;
HBoxContainer *hbc;
Label *label;
Button *ok;
@@ -100,10 +103,12 @@ class AcceptDialog : public WindowDialog {
void _ok_pressed();
void _close_pressed();
void _builtin_text_entered(const String& p_text);
+ void _update_child_rect();
static bool swap_ok_cancel;
+ virtual void remove_child_notify(Node *p_child);
protected:
@@ -116,6 +121,8 @@ protected:
virtual void custom_action(const String&) {}
public:
+ Size2 get_minimum_size() const;
+
Label *get_label() { return label; }
static void set_swap_ok_cancel(bool p_swap);
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index c1a0e43e49..fc4ab5f8ca 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -325,6 +325,18 @@ int ItemList::get_fixed_column_width() const{
return fixed_column_width;
}
+void ItemList::set_same_column_width(bool p_enable){
+
+ same_column_width=p_enable;
+ update();
+ shape_changed=true;
+
+}
+int ItemList::is_same_column_width() const{
+
+ return same_column_width;
+}
+
void ItemList::set_max_text_lines(int p_lines){
ERR_FAIL_COND(p_lines<1);
@@ -824,6 +836,8 @@ void ItemList::_notification(int p_what) {
}
if (shape_changed) {
+
+ float max_column_width = 0;
//1- compute item minimum sizes
for(int i=0;i<items.size();i++) {
@@ -831,7 +845,7 @@ void ItemList::_notification(int p_what) {
Size2 minsize;
if (items[i].icon.is_valid()) {
- minsize=_adjust_to_max_size(items[i].get_icon_size(),max_icon_size);
+ minsize=_adjust_to_max_size(items[i].get_icon_size(),max_icon_size) * icon_scale;
if (items[i].text!="") {
if (icon_mode==ICON_MODE_TOP) {
@@ -864,10 +878,11 @@ void ItemList::_notification(int p_what) {
}
-
- items[i].rect_cache.size=minsize;
if (fixed_column_width>0)
- items[i].rect_cache.size.x=fixed_column_width;
+ minsize.x=fixed_column_width;
+ max_column_width=MAX(max_column_width,minsize.x);
+ items[i].rect_cache.size=minsize;
+ items[i].min_rect_cache.size=minsize;
}
@@ -896,17 +911,23 @@ void ItemList::_notification(int p_what) {
break;
}
+ items[i].rect_cache=items[i].min_rect_cache;
+ if(same_column_width)
+ items[i].rect_cache.size.x=max_column_width;
items[i].rect_cache.pos=ofs;
max_h=MAX(max_h,items[i].rect_cache.size.y);
- ofs.x+=items[i].rect_cache.size.x;
+ ofs.x+=items[i].rect_cache.size.x + hseparation;
//print_line("item "+itos(i)+" ofs "+rtos(items[i].rect_cache.size.x));
- if (col>0)
- ofs.x+=hseparation;
col++;
if (col==current_columns) {
if (i<items.size()-1)
separators.push_back(ofs.y+max_h+vseparation/2);
+
+ for(int j=i;j>=0 && col>0;j--, col--) {
+ items[j].rect_cache.size.y = max_h;
+ }
+
ofs.x=0;
ofs.y+=max_h+vseparation;
col=0;
@@ -914,6 +935,10 @@ void ItemList::_notification(int p_what) {
}
}
+ for(int j=items.size()-1;j>=0 && col>0;j--, col--) {
+ items[j].rect_cache.size.y = max_h;
+ }
+
if (all_fit) {
float max = MAX(page,ofs.y+max_h);
scroll_bar->set_max(max);
@@ -976,7 +1001,7 @@ void ItemList::_notification(int p_what) {
Vector2 text_ofs;
if (items[i].icon.is_valid()) {
- Size2 icon_size = _adjust_to_max_size(items[i].get_icon_size(),max_icon_size);
+ Size2 icon_size = _adjust_to_max_size(items[i].get_icon_size(),max_icon_size) * icon_scale;
Vector2 icon_ofs;
if (min_icon_size!=Vector2()) {
@@ -988,7 +1013,12 @@ void ItemList::_notification(int p_what) {
if (icon_mode==ICON_MODE_TOP) {
pos.x += Math::floor((items[i].rect_cache.size.width - icon_size.width)/2);
+ pos.y += MIN(
+ Math::floor((items[i].rect_cache.size.height - icon_size.height)/2),
+ items[i].rect_cache.size.height - items[i].min_rect_cache.size.height
+ );
text_ofs.y = MAX(icon_size.height, min_icon_size.y) + icon_margin;
+ text_ofs.y += items[i].rect_cache.size.height - items[i].min_rect_cache.size.height;
} else {
pos.y += Math::floor((items[i].rect_cache.size.height - icon_size.height)/2);
@@ -1014,6 +1044,8 @@ void ItemList::_notification(int p_what) {
Vector2 size = font->get_string_size(items[i].text);
if (fixed_column_width)
max_len=fixed_column_width;
+ else if(same_column_width)
+ max_len=items[i].rect_cache.size.x;
else
max_len=size.x;
@@ -1201,6 +1233,14 @@ bool ItemList::get_allow_rmb_select() const {
return allow_rmb_select;
}
+void ItemList::set_icon_scale(real_t p_scale) {
+ icon_scale = p_scale;
+}
+
+real_t ItemList::get_icon_scale() const {
+ return icon_scale;
+}
+
void ItemList::_bind_methods(){
ObjectTypeDB::bind_method(_MD("add_item","text","icon:Texture","selectable"),&ItemList::add_item,DEFVAL(Variant()),DEFVAL(true));
@@ -1243,6 +1283,9 @@ void ItemList::_bind_methods(){
ObjectTypeDB::bind_method(_MD("set_fixed_column_width","width"),&ItemList::set_fixed_column_width);
ObjectTypeDB::bind_method(_MD("get_fixed_column_width"),&ItemList::get_fixed_column_width);
+ ObjectTypeDB::bind_method(_MD("set_same_column_width","enable"),&ItemList::set_same_column_width);
+ ObjectTypeDB::bind_method(_MD("is_same_column_width"),&ItemList::is_same_column_width);
+
ObjectTypeDB::bind_method(_MD("set_max_text_lines","lines"),&ItemList::set_max_text_lines);
ObjectTypeDB::bind_method(_MD("get_max_text_lines"),&ItemList::get_max_text_lines);
@@ -1261,6 +1304,9 @@ void ItemList::_bind_methods(){
ObjectTypeDB::bind_method(_MD("set_max_icon_size","size"),&ItemList::set_max_icon_size);
ObjectTypeDB::bind_method(_MD("get_max_icon_size"),&ItemList::get_max_icon_size);
+ ObjectTypeDB::bind_method(_MD("set_icon_scale","scale"),&ItemList::set_icon_scale);
+ ObjectTypeDB::bind_method(_MD("get_icon_scale"),&ItemList::get_icon_scale);
+
ObjectTypeDB::bind_method(_MD("set_allow_rmb_select","allow"),&ItemList::set_allow_rmb_select);
ObjectTypeDB::bind_method(_MD("get_allow_rmb_select"),&ItemList::get_allow_rmb_select);
@@ -1292,6 +1338,7 @@ ItemList::ItemList() {
icon_mode=ICON_MODE_LEFT;
fixed_column_width=0;
+ same_column_width = false;
max_text_lines=1;
max_columns=1;
@@ -1308,6 +1355,7 @@ ItemList::ItemList() {
defer_select_single=-1;
allow_rmb_select=false;
+ icon_scale = 1.0f;
}
ItemList::~ItemList() {
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 59fa1d8270..087c585128 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -33,6 +33,7 @@ private:
Color custom_bg;
Rect2 rect_cache;
+ Rect2 min_rect_cache;
Size2 get_icon_size() const;
@@ -44,6 +45,7 @@ private:
bool shape_changed;
bool ensure_selected_visible;
+ bool same_column_width;
Vector<Item> items;
Vector<int> separators;
@@ -59,12 +61,18 @@ private:
int fixed_column_width;
int max_text_lines;
int max_columns;
+
Size2 min_icon_size;
Size2 max_icon_size;
+
+ Size2 max_item_size_cache;
+
int defer_select_single;
bool allow_rmb_select;
+ real_t icon_scale;
+
void _scroll_changed(double);
void _input_event(const InputEvent& p_event);
protected:
@@ -121,6 +129,9 @@ public:
void set_fixed_column_width(int p_size);
int get_fixed_column_width() const;
+ void set_same_column_width(bool p_enable);
+ int is_same_column_width() const;
+
void set_max_text_lines(int p_amount);
int get_max_text_lines() const;
@@ -150,6 +161,9 @@ public:
virtual String get_tooltip(const Point2& p_pos) const;
int get_item_at_pos(const Point2& p_pos,bool p_exact=false) const;
+ void set_icon_scale(real_t p_scale);
+ real_t get_icon_scale() const;
+
ItemList();
~ItemList();
};
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 1c6a97bab8..c8bd1cb5a1 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -411,6 +411,11 @@ void TabContainer::_notification(int p_what) {
panel->draw(ci, Rect2( 0, top_size.height, size.width, size.height-top_size.height));
} break;
+ case NOTIFICATION_READY:
+ case NOTIFICATION_THEME_CHANGED: {
+
+ call_deferred("set_current_tab",get_current_tab()); //wait until all changed theme
+ } break;
}
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 03024daff5..fd6e97d33f 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -314,6 +314,10 @@ void TextEdit::_update_scrollbars() {
if (line_numbers)
total_width += cache.line_number_w;
+ if (draw_breakpoint_gutter) {
+ total_width += cache.breakpoint_gutter_width;
+ }
+
bool use_hscroll=true;
bool use_vscroll=true;
@@ -412,9 +416,15 @@ void TextEdit::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
_update_caches();
- };
+ } break;
case NOTIFICATION_DRAW: {
+ if (draw_breakpoint_gutter) {
+ cache.breakpoint_gutter_width = breakpoint_gutter_width;
+ } else {
+ cache.breakpoint_gutter_width = 0;
+ }
+
int line_number_char_count=0;
{
@@ -439,7 +449,7 @@ void TextEdit::_notification(int p_what) {
RID ci = get_canvas_item();
- int xmargin_beg=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w;
+ int xmargin_beg=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w+cache.breakpoint_gutter_width;
int xmargin_end=cache.size.width-cache.style_normal->get_margin(MARGIN_RIGHT);
//let's do it easy for now:
cache.style_normal->draw(ci,Rect2(Point2(),cache.size));
@@ -682,9 +692,13 @@ void TextEdit::_notification(int p_what) {
// check if line contains highlighted word
int highlighted_text_col = -1;
- if (highlighted_text.length() != 0) {
- highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, 0);
- }
+ int search_text_col = -1;
+
+ if (!search_text.empty())
+ search_text_col = _get_column_pos_of_word(search_text, str, search_flags, 0);
+
+ if (highlighted_text.length() != 0 && highlighted_text != search_text)
+ highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE|SEARCH_WHOLE_WORDS, 0);
if (cache.line_number_w) {
String fc = String::num(line+1);
@@ -692,7 +706,7 @@ void TextEdit::_notification(int p_what) {
fc="0"+fc;
}
- cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT),ofs_y+cache.font->get_ascent()),fc,cache.line_number_color);
+ cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT)+cache.breakpoint_gutter_width,ofs_y+cache.font->get_ascent()),fc,cache.line_number_color);
}
const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(line);
@@ -706,6 +720,14 @@ void TextEdit::_notification(int p_what) {
if (text.is_breakpoint(line)) {
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.breakpoint_color);
+
+ // draw breakpoint marker
+ if (draw_breakpoint_gutter) {
+ int vertical_gap = cache.breakpoint_gutter_width / 2;
+ int marker_size = cache.breakpoint_gutter_width - vertical_gap;
+ // no transparency on marker
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + 1, ofs_y + vertical_gap ,marker_size, marker_size),Color(cache.breakpoint_color.r, cache.breakpoint_color.g, cache.breakpoint_color.b));
+ }
}
@@ -879,20 +901,45 @@ void TextEdit::_notification(int p_what) {
break;
}
- bool in_selection = (selection.active && line>=selection.from_line && line<=selection.to_line && (line>selection.from_line || j>=selection.from_column) && (line<selection.to_line || j<selection.to_column));
+ bool in_search_result=false;
+
+ if (search_text_col != -1) {
+ // if we are at the end check for new search result on same line
+ if (j >= search_text_col+search_text.length())
+ search_text_col = _get_column_pos_of_word(search_text, str, search_flags, j);
+
+ in_search_result = j >= search_text_col && j < search_text_col+search_text.length();
+
+ if (in_search_result) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w, get_row_height())),cache.search_result_color);
+ }
+ }
+ bool in_selection = (selection.active && line>=selection.from_line && line<=selection.to_line && (line>selection.from_line || j>=selection.from_column) && (line<selection.to_line || j<selection.to_column));
if (in_selection) {
//inside selection!
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w,get_row_height())),cache.selection_color);
}
+ if (in_search_result) {
+ Color border_color=(line==search_result_line && j>=search_result_col && j<search_result_col+search_text.length())?cache.font_color:cache.search_result_border_color;
+
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w,1)),border_color);
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y+get_row_height()-1 ), Size2i(char_w,1)),border_color);
+
+ if (j==search_text_col)
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(1,get_row_height())),border_color);
+ if (j==search_text_col+search_text.length()-1)
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin+char_w-1, ofs_y ), Size2i(1,get_row_height())),border_color);
+ }
+
if (highlight_all_occurrences) {
if (highlighted_text_col != -1) {
// if we are at the end check for new word on same line
if (j > highlighted_text_col+highlighted_text.length()) {
- highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, j);
+ highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE|SEARCH_WHOLE_WORDS, j);
}
bool in_highlighted_word = (j >= highlighted_text_col && j < highlighted_text_col+highlighted_text.length());
@@ -1347,7 +1394,7 @@ void TextEdit::_get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) co
col=text[row].size();
} else {
- col=p_mouse.x-(cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w);
+ col=p_mouse.x-(cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w+cache.breakpoint_gutter_width);
col+=cursor.x_ofs;
col=get_char_pos_for( col, get_line(row) );
}
@@ -1421,6 +1468,15 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
int row,col;
_get_mouse_pos(Point2i(mb.x,mb.y), row,col);
+ // toggle breakpoint on gutter click
+ if (draw_breakpoint_gutter) {
+ int gutter=cache.style_normal->get_margin(MARGIN_LEFT);
+ if (mb.x > gutter && mb.x <= gutter + cache.breakpoint_gutter_width + 3) {
+ set_line_as_breakpoint(row, !is_line_set_as_breakpoint(row));
+ return;
+ }
+ }
+
int prev_col=cursor.column;
int prev_line=cursor.line;
@@ -1820,7 +1876,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
}
if (clear) {
- begin_complex_operation();
+ if (!dobreak) {
+ begin_complex_operation();
+ }
selection.active=false;
update();
_remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column);
@@ -1892,7 +1950,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
if (completion_hint!="") {
completion_hint="";
update();
-
+ } else {
+ scancode_handled=false;
}
} break;
case KEY_TAB: {
@@ -2846,7 +2905,7 @@ void TextEdit::adjust_viewport_to_cursor() {
if (cursor.line_ofs>cursor.line)
cursor.line_ofs=cursor.line;
- int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w;
+ int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w-cache.breakpoint_gutter_width;
if (v_scroll->is_visible())
visible_width-=v_scroll->get_combined_minimum_size().width;
visible_width-=20; // give it a little more space
@@ -3075,7 +3134,8 @@ void TextEdit::insert_text_at_cursor(const String& p_text) {
}
Control::CursorShape TextEdit::get_cursor_shape(const Point2& p_pos) const {
- if(completion_active && completion_rect.has_point(p_pos)) {
+ int gutter=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w+cache.breakpoint_gutter_width;
+ if((completion_active && completion_rect.has_point(p_pos)) || p_pos.x < gutter) {
return CURSOR_ARROW;
}
return CURSOR_IBEAM;
@@ -3220,6 +3280,8 @@ void TextEdit::_update_caches() {
cache.breakpoint_color=get_color("breakpoint_color");
cache.brace_mismatch_color=get_color("brace_mismatch_color");
cache.word_highlighted_color=get_color("word_highlighted_color");
+ cache.search_result_color=get_color("search_result_color");
+ cache.search_result_border_color=get_color("search_result_border_color");
cache.line_spacing=get_constant("line_spacing");
cache.row_height = cache.font->get_height() + cache.line_spacing;
cache.tab_icon=get_icon("tab");
@@ -3481,12 +3543,26 @@ String TextEdit::get_word_under_cursor() const {
return text[cursor.line].substr(prev_cc, next_cc-prev_cc);
}
+void TextEdit::set_search_text(const String &p_search_text) {
+ search_text = p_search_text;
+}
+
+void TextEdit::set_search_flags(uint32_t p_flags) {
+ search_flags = p_flags;
+}
+
+void TextEdit::set_current_search_result(int line, int col) {
+ search_result_line = line;
+ search_result_col = col;
+ update();
+}
+
void TextEdit::set_highlight_all_occurrences(const bool p_enabled) {
highlight_all_occurrences = p_enabled;
update();
}
-int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_search, int p_from_column) {
+int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column) {
int col = -1;
if (p_key.length() > 0 && p_search.length() > 0) {
@@ -3494,12 +3570,15 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc
p_from_column = 0;
}
- while (col == -1 && p_from_column <= p_search.length()) {
- // match case
- col = p_search.findn(p_key, p_from_column);
+ while (col == -1 && p_from_column <= p_search.length()) {
+ if (p_search_flags&SEARCH_MATCH_CASE) {
+ col = p_search.find(p_key,p_from_column);
+ } else {
+ col = p_search.findn(p_key,p_from_column);
+ }
// whole words only
- if (col != -1) {
+ if (col != -1 && p_search_flags&SEARCH_WHOLE_WORDS) {
p_from_column=col;
if (col > 0 && _is_text_char(p_search[col-1])) {
@@ -3565,10 +3644,8 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li
//wrapped
if (p_search_flags&SEARCH_BACKWARDS) {
- text_line=text_line.substr(from_column,text_line.length());
from_column=text_line.length();
} else {
- text_line=text_line.substr(0,from_column);
from_column=0;
}
@@ -3579,7 +3656,6 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li
} else {
- //text_line=text_line.substr(0,p_from_column); //wrap around for missing begining.
if (p_search_flags&SEARCH_BACKWARDS)
from_column=text_line.length()-1;
else
@@ -3588,12 +3664,25 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li
pos=-1;
- if (!(p_search_flags&SEARCH_BACKWARDS)) {
+ int pos_from=0;
+ int last_pos=-1;
+ while ((last_pos=(p_search_flags&SEARCH_MATCH_CASE)?text_line.find(p_key,pos_from):text_line.findn(p_key,pos_from))!=-1) {
- pos = (p_search_flags&SEARCH_MATCH_CASE)?text_line.find(p_key,from_column):text_line.findn(p_key,from_column);
- } else {
+ if (p_search_flags&SEARCH_BACKWARDS) {
+
+ if (last_pos>from_column)
+ break;
+ pos=last_pos;
+
+ } else {
- pos = (p_search_flags&SEARCH_MATCH_CASE)?text_line.rfind(p_key,from_column):text_line.rfindn(p_key,from_column);
+ if (last_pos>=from_column) {
+ pos=last_pos;
+ break;
+ }
+ }
+
+ pos_from=last_pos+p_key.length();
}
if (pos!=-1 && (p_search_flags&SEARCH_WHOLE_WORDS)) {
@@ -4167,6 +4256,24 @@ void TextEdit::set_show_line_numbers(bool p_show) {
update();
}
+void TextEdit::set_draw_breakpoint_gutter(bool p_draw) {
+ draw_breakpoint_gutter = p_draw;
+ update();
+}
+
+bool TextEdit::is_drawing_breakpoint_gutter() const {
+ return draw_breakpoint_gutter;
+}
+
+void TextEdit::set_breakpoint_gutter_width(int p_gutter_width) {
+ breakpoint_gutter_width = p_gutter_width;
+ update();
+}
+
+int TextEdit::get_breakpoint_gutter_width() const {
+ return cache.breakpoint_gutter_width;
+}
+
bool TextEdit::is_text_field() const {
return true;
@@ -4308,6 +4415,8 @@ TextEdit::TextEdit() {
cache.row_height=1;
cache.line_spacing=1;
cache.line_number_w=1;
+ cache.breakpoint_gutter_width=0;
+ breakpoint_gutter_width = 0;
tab_size=4;
text.set_tab_size(tab_size);
@@ -4389,6 +4498,7 @@ TextEdit::TextEdit() {
completion_line_ofs=0;
tooltip_obj=NULL;
line_numbers=false;
+ draw_breakpoint_gutter=false;
next_operation_is_complex=false;
scroll_past_end_of_file_enabled=false;
auto_brace_completion_enabled=false;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index dbe6293240..24a72afd48 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -88,10 +88,13 @@ class TextEdit : public Control {
Color current_line_color;
Color brace_mismatch_color;
Color word_highlighted_color;
+ Color search_result_color;
+ Color search_result_border_color;
int row_height;
int line_spacing;
int line_number_w;
+ int breakpoint_gutter_width;
Size2 size;
} cache;
@@ -222,6 +225,8 @@ class TextEdit : public Control {
bool text_changed_dirty;
bool undo_enabled;
bool line_numbers;
+ bool draw_breakpoint_gutter;
+ int breakpoint_gutter_width;
bool highlight_all_occurrences;
bool scroll_past_end_of_file_enabled;
@@ -249,6 +254,11 @@ class TextEdit : public Control {
bool callhint_below;
Vector2 callhint_offset;
+ String search_text;
+ uint32_t search_flags;
+ int search_result_line;
+ int search_result_col;
+
int get_visible_rows() const;
int get_char_count();
@@ -287,7 +297,7 @@ class TextEdit : public Control {
String _base_get_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column) const;
void _base_remove_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column);
- int _get_column_pos_of_word(const String &p_key, const String &p_search, int p_from_column);
+ int _get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column);
DVector<int> _search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const;
@@ -408,6 +418,10 @@ public:
void select(int p_from_line,int p_from_column,int p_to_line,int p_to_column);
void deselect();
+ void set_search_text(const String& p_search_text);
+ void set_search_flags(uint32_t p_flags);
+ void set_current_search_result(int line, int col);
+
void set_highlight_all_occurrences(const bool p_enabled);
bool is_selection_active() const;
int get_selection_from_line() const;
@@ -451,6 +465,12 @@ public:
void set_show_line_numbers(bool p_show);
+ void set_draw_breakpoint_gutter(bool p_draw);
+ bool is_drawing_breakpoint_gutter() const;
+
+ void set_breakpoint_gutter_width(int p_gutter_width);
+ int get_breakpoint_gutter_width() const;
+
void set_tooltip_request_func(Object *p_obj, const StringName& p_function, const Variant& p_udata);
void set_completion(bool p_enabled,const Vector<String>& p_prefixes);
diff --git a/scene/gui/texture_frame.cpp b/scene/gui/texture_frame.cpp
index 73fecf591a..2fe8735fda 100644
--- a/scene/gui/texture_frame.cpp
+++ b/scene/gui/texture_frame.cpp
@@ -37,9 +37,31 @@ void TextureFrame::_notification(int p_what) {
return;
- Size2 s=expand?get_size():texture->get_size();
+
RID ci = get_canvas_item();
- draw_texture_rect(texture,Rect2(Point2(),s),false,modulate);
+
+ switch(stretch_mode) {
+ case STRETCH_SCALE_ON_EXPAND: {
+ Size2 s=expand?get_size():texture->get_size();
+ draw_texture_rect(texture,Rect2(Point2(),s),false,modulate);
+ } break;
+ case STRETCH_SCALE: {
+ draw_texture_rect(texture,Rect2(Point2(),get_size()),false,modulate);
+ } break;
+ case STRETCH_TILE: {
+ draw_texture_rect(texture,Rect2(Point2(),get_size()),true,modulate);
+ } break;
+ case STRETCH_KEEP: {
+ draw_texture_rect(texture,Rect2(Point2(),texture->get_size()),false,modulate);
+
+ } break;
+ case STRETCH_KEEP_CENTERED: {
+
+ Vector2 ofs = (get_size() - texture->get_size())/2;
+ draw_texture_rect(texture,Rect2(ofs,texture->get_size()),false,modulate);
+ } break;
+ }
+
/*
Vector<Point2> points;
@@ -76,11 +98,19 @@ void TextureFrame::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_modulate"), & TextureFrame::get_modulate );
ObjectTypeDB::bind_method(_MD("set_expand","enable"), & TextureFrame::set_expand );
ObjectTypeDB::bind_method(_MD("has_expand"), & TextureFrame::has_expand );
+ ObjectTypeDB::bind_method(_MD("set_stretch_mode","stretch_mode"), & TextureFrame::set_stretch_mode );
+ ObjectTypeDB::bind_method(_MD("get_stretch_mode"), & TextureFrame::get_stretch_mode );
ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") );
ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") );
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "expand" ), _SCS("set_expand"),_SCS("has_expand") );
+ ADD_PROPERTYNO( PropertyInfo( Variant::INT, "stretch_mode",PROPERTY_HINT_ENUM,"Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered"), _SCS("set_stretch_mode"),_SCS("get_stretch_mode") );
+ BIND_CONSTANT( STRETCH_SCALE_ON_EXPAND );
+ BIND_CONSTANT( STRETCH_SCALE );
+ BIND_CONSTANT( STRETCH_TILE );
+ BIND_CONSTANT( STRETCH_KEEP );
+ BIND_CONSTANT( STRETCH_KEEP_CENTERED );
}
@@ -121,12 +151,24 @@ bool TextureFrame::has_expand() const {
return expand;
}
+void TextureFrame::set_stretch_mode(StretchMode p_mode) {
+
+ stretch_mode=p_mode;
+ update();
+}
+
+TextureFrame::StretchMode TextureFrame::get_stretch_mode() const {
+
+ return stretch_mode;
+}
+
TextureFrame::TextureFrame() {
expand=false;
modulate=Color(1,1,1,1);
set_ignore_mouse(true);
+ stretch_mode=STRETCH_SCALE_ON_EXPAND;
}
diff --git a/scene/gui/texture_frame.h b/scene/gui/texture_frame.h
index e1f0de92df..a4acf588ea 100644
--- a/scene/gui/texture_frame.h
+++ b/scene/gui/texture_frame.h
@@ -36,10 +36,19 @@
class TextureFrame : public Control {
OBJ_TYPE(TextureFrame,Control);
-
+public:
+ enum StretchMode {
+ STRETCH_SCALE_ON_EXPAND, //default, for backwards compatibility
+ STRETCH_SCALE,
+ STRETCH_TILE,
+ STRETCH_KEEP,
+ STRETCH_KEEP_CENTERED,
+ };
+private:
bool expand;
Color modulate;
Ref<Texture> texture;
+ StretchMode stretch_mode;
protected:
void _notification(int p_what);
@@ -57,9 +66,13 @@ public:
void set_expand(bool p_expand);
bool has_expand() const;
+ void set_stretch_mode(StretchMode p_mode);
+ StretchMode get_stretch_mode() const;
+
TextureFrame();
~TextureFrame();
};
+VARIANT_ENUM_CAST( TextureFrame::StretchMode );
#endif // TEXTURE_FRAME_H
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index 24fe1e1bb3..d7f22c3228 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -1593,6 +1593,14 @@ void SceneTree::_live_edit_reparent_node_func(const NodePath& p_at,const NodePat
#endif
+
+
+void SceneTree::drop_files(const Vector<String>& p_files,int p_from_screen) {
+
+ emit_signal("files_dropped",p_files,p_from_screen);
+ MainLoop::drop_files(p_files,p_from_screen);
+}
+
void SceneTree::_bind_methods() {
@@ -1666,6 +1674,8 @@ void SceneTree::_bind_methods() {
ADD_SIGNAL( MethodInfo("idle_frame"));
ADD_SIGNAL( MethodInfo("fixed_frame"));
+ ADD_SIGNAL( MethodInfo("files_dropped",PropertyInfo(Variant::STRING_ARRAY,"files"),PropertyInfo(Variant::INT,"screen")) );
+
BIND_CONSTANT( GROUP_CALL_DEFAULT );
BIND_CONSTANT( GROUP_CALL_REVERSE );
BIND_CONSTANT( GROUP_CALL_REALTIME );
diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h
index b6a015c9ed..5fc9e0c1ae 100644
--- a/scene/main/scene_main_loop.h
+++ b/scene/main/scene_main_loop.h
@@ -344,6 +344,7 @@ public:
static SceneTree* get_singleton() { return singleton; }
+ void drop_files(const Vector<String>& p_files,int p_from_screen=0);
SceneTree();
~SceneTree();
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 8327473a60..1fd1c77dca 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -133,6 +133,7 @@
#include "scene/resources/mesh_data_tool.h"
#include "scene/resources/scene_preloader.h"
#include "scene/resources/dynamic_font.h"
+#include "scene/resources/dynamic_font_stb.h"
#include "scene/main/timer.h"
@@ -254,7 +255,6 @@ void register_scene_types() {
resource_loader_wav = memnew( ResourceFormatLoaderWAV );
ResourceLoader::add_resource_format_loader( resource_loader_wav );
-
resource_loader_dynamic_font = memnew( ResourceFormatLoaderDynamicFont );
ResourceLoader::add_resource_format_loader( resource_loader_dynamic_font );
@@ -578,8 +578,10 @@ void register_scene_types() {
ObjectTypeDB::register_type<Animation>();
ObjectTypeDB::register_virtual_type<Font>();
ObjectTypeDB::register_type<BitmapFont>();
+
ObjectTypeDB::register_type<DynamicFontData>();
ObjectTypeDB::register_type<DynamicFont>();
+
ObjectTypeDB::register_type<StyleBoxEmpty>();
ObjectTypeDB::register_type<StyleBoxTexture>();
ObjectTypeDB::register_type<StyleBoxFlat>();
@@ -647,6 +649,7 @@ void unregister_scene_types() {
memdelete( resource_loader_image );
memdelete( resource_loader_wav );
memdelete( resource_loader_dynamic_font );
+
#ifdef TOOLS_ENABLED
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 0c4d8ae841..9ebb7e7561 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -28,6 +28,7 @@
typedef Map<const void*,Ref<ImageTexture> > TexCacheMap;
static TexCacheMap *tex_cache;
+static int scale=1;
template<class T>
static Ref<StyleBoxTexture> make_stylebox(T p_src,float p_left, float p_top, float p_right, float p_botton,float p_margin_left=-1, float p_margin_top=-1, float p_margin_right=-1, float p_margin_botton=-1, bool p_draw_center=true) {
@@ -40,21 +41,24 @@ static Ref<StyleBoxTexture> make_stylebox(T p_src,float p_left, float p_top, flo
} else {
texture = Ref<ImageTexture>( memnew( ImageTexture ) );
- texture->create_from_image( Image(p_src),ImageTexture::FLAG_FILTER );
+ Image img(p_src);
+ if (scale>1)
+ img.expand_x2_hq2x();
+ texture->create_from_image( img,ImageTexture::FLAG_FILTER );
(*tex_cache)[p_src]=texture;
}
Ref<StyleBoxTexture> style( memnew( StyleBoxTexture ) );
style->set_texture(texture);
- style->set_margin_size( MARGIN_LEFT, p_left );
- style->set_margin_size( MARGIN_RIGHT, p_right );
- style->set_margin_size( MARGIN_BOTTOM, p_botton );
- style->set_margin_size( MARGIN_TOP, p_top );
- style->set_default_margin( MARGIN_LEFT, p_margin_left );
- style->set_default_margin( MARGIN_RIGHT, p_margin_right );
- style->set_default_margin( MARGIN_BOTTOM, p_margin_botton );
- style->set_default_margin( MARGIN_TOP, p_margin_top );
+ style->set_margin_size( MARGIN_LEFT, p_left * scale);
+ style->set_margin_size( MARGIN_RIGHT, p_right * scale);
+ style->set_margin_size( MARGIN_BOTTOM, p_botton * scale);
+ style->set_margin_size( MARGIN_TOP, p_top * scale);
+ style->set_default_margin( MARGIN_LEFT, p_margin_left * scale);
+ style->set_default_margin( MARGIN_RIGHT, p_margin_right * scale);
+ style->set_default_margin( MARGIN_BOTTOM, p_margin_botton * scale);
+ style->set_default_margin( MARGIN_TOP, p_margin_top * scale);
style->set_draw_center(p_draw_center);
return style;
@@ -63,10 +67,10 @@ static Ref<StyleBoxTexture> make_stylebox(T p_src,float p_left, float p_top, flo
static Ref<StyleBoxTexture> sb_expand(Ref<StyleBoxTexture> p_sbox,float p_left, float p_top, float p_right, float p_botton) {
- p_sbox->set_expand_margin_size(MARGIN_LEFT,p_left);
- p_sbox->set_expand_margin_size(MARGIN_TOP,p_top);
- p_sbox->set_expand_margin_size(MARGIN_RIGHT,p_right);
- p_sbox->set_expand_margin_size(MARGIN_BOTTOM,p_botton);
+ p_sbox->set_expand_margin_size(MARGIN_LEFT,p_left * scale);
+ p_sbox->set_expand_margin_size(MARGIN_TOP,p_top * scale);
+ p_sbox->set_expand_margin_size(MARGIN_RIGHT,p_right * scale);
+ p_sbox->set_expand_margin_size(MARGIN_BOTTOM,p_botton * scale);
return p_sbox;
}
@@ -75,7 +79,10 @@ static Ref<Texture> make_icon(T p_src) {
Ref<ImageTexture> texture( memnew( ImageTexture ) );
- texture->create_from_image( Image(p_src),ImageTexture::FLAG_FILTER );
+ Image img = Image(p_src);
+ if (scale>1)
+ img.expand_x2_hq2x();
+ texture->create_from_image( img,ImageTexture::FLAG_FILTER );
return texture;
}
@@ -170,27 +177,24 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left=-1, float p_margin_
Ref<StyleBox> style( memnew( StyleBoxEmpty) );
- style->set_default_margin( MARGIN_LEFT, p_margin_left );
- style->set_default_margin( MARGIN_RIGHT, p_margin_right );
- style->set_default_margin( MARGIN_BOTTOM, p_margin_botton );
- style->set_default_margin( MARGIN_TOP, p_margin_top );
+ style->set_default_margin( MARGIN_LEFT, p_margin_left * scale);
+ style->set_default_margin( MARGIN_RIGHT, p_margin_right * scale);
+ style->set_default_margin( MARGIN_BOTTOM, p_margin_botton * scale);
+ style->set_default_margin( MARGIN_TOP, p_margin_top * scale);
return style;
}
-#ifndef DEFAULT_THEME_DISABLED
-
-void make_default_theme() {
+void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<Font> & large_font,Ref<Texture>& default_icon, Ref<StyleBox>& default_style,bool p_hidpi) {
+ if (p_hidpi)
+ scale=2;
+ else
+ scale=1;
tex_cache = memnew( TexCacheMap );
- Ref<Theme> t( memnew( Theme ) );
-
//Ref<BitmapFont> default_font = make_font(_bi_font_normal_height,_bi_font_normal_ascent,_bi_font_normal_valign,_bi_font_normal_charcount,_bi_font_normal_characters,make_icon(font_normal_png));
- Ref<BitmapFont> default_font=make_font2(_builtin_normal_font_height,_builtin_normal_font_ascent,_builtin_normal_font_charcount,&_builtin_normal_font_charrects[0][0],_builtin_normal_font_kerning_pair_count,&_builtin_normal_font_kerning_pairs[0][0],_builtin_normal_font_img_width,_builtin_normal_font_img_height,_builtin_normal_font_img_data);
- Ref<BitmapFont> source_font=make_font2(_builtin_source_font_height,_builtin_source_font_ascent,_builtin_source_font_charcount,&_builtin_source_font_charrects[0][0],_builtin_source_font_kerning_pair_count,&_builtin_source_font_kerning_pairs[0][0],_builtin_source_font_img_width,_builtin_source_font_img_height,_builtin_source_font_img_data);
- Ref<BitmapFont> large_font=make_font2(_builtin_large_font_height,_builtin_large_font_ascent,_builtin_large_font_charcount,&_builtin_large_font_charrects[0][0],_builtin_large_font_kerning_pair_count,&_builtin_large_font_kerning_pairs[0][0],_builtin_large_font_img_width,_builtin_large_font_img_height,_builtin_large_font_img_data);
// Font Colors
@@ -213,7 +217,7 @@ void make_default_theme() {
Ref<StyleBoxTexture> focus = make_stylebox( focus_png,5,5,5,5);
for(int i=0;i<4;i++) {
- focus->set_expand_margin_size(Margin(i),1);
+ focus->set_expand_margin_size(Margin(i),1 *scale);
}
@@ -239,7 +243,7 @@ void make_default_theme() {
t->set_color("font_color_hover","Button", control_font_color_hover );
t->set_color("font_color_disabled","Button", control_font_color_disabled );
- t->set_constant("hseparation","Button", 2);
+ t->set_constant("hseparation","Button", 2 *scale);
// LinkButton
@@ -249,7 +253,7 @@ void make_default_theme() {
t->set_color("font_color_pressed","LinkButton", control_font_color_pressed );
t->set_color("font_color_hover","LinkButton", control_font_color_hover );
- t->set_constant("underline_spacing","LinkButton", 2 );
+ t->set_constant("underline_spacing","LinkButton", 2 *scale);
// ColorPickerButton
@@ -266,16 +270,16 @@ void make_default_theme() {
t->set_color("font_color_hover","ColorPickerButton", Color(1,1,1,1) );
t->set_color("font_color_disabled","ColorPickerButton", Color(0.9,0.9,0.9,0.3) );
- t->set_constant("hseparation","ColorPickerButton", 2 );
+ t->set_constant("hseparation","ColorPickerButton", 2 *scale);
// ToolButton
Ref<StyleBox> tb_empty = memnew( StyleBoxEmpty );
- tb_empty->set_default_margin(MARGIN_LEFT,6);
- tb_empty->set_default_margin(MARGIN_RIGHT,6);
- tb_empty->set_default_margin(MARGIN_TOP,4);
- tb_empty->set_default_margin(MARGIN_BOTTOM,4);
+ tb_empty->set_default_margin(MARGIN_LEFT,6 *scale);
+ tb_empty->set_default_margin(MARGIN_RIGHT,6 *scale);
+ tb_empty->set_default_margin(MARGIN_TOP,4 *scale);
+ tb_empty->set_default_margin(MARGIN_BOTTOM,4 *scale);
t->set_stylebox("normal","ToolButton", tb_empty);
t->set_stylebox("pressed","ToolButton", make_stylebox( button_pressed_png,4,4,4,4) );
@@ -316,8 +320,8 @@ void make_default_theme() {
t->set_color("font_color_hover","OptionButton", control_font_color_hover );
t->set_color("font_color_disabled","OptionButton", control_font_color_disabled );
- t->set_constant("hseparation","OptionButton", 2 );
- t->set_constant("arrow_margin","OptionButton", 2 );
+ t->set_constant("hseparation","OptionButton", 2 *scale);
+ t->set_constant("arrow_margin","OptionButton", 2 *scale);
@@ -336,7 +340,7 @@ void make_default_theme() {
t->set_color("font_color_hover","MenuButton", control_font_color_hover );
t->set_color("font_color_disabled","MenuButton", Color(1,1,1,0.3) );
- t->set_constant("hseparation","MenuButton", 3 );
+ t->set_constant("hseparation","MenuButton", 3 *scale);
// ButtonGroup
@@ -345,15 +349,15 @@ void make_default_theme() {
// CheckBox
Ref<StyleBox> cbx_empty = memnew( StyleBoxEmpty );
- cbx_empty->set_default_margin(MARGIN_LEFT,22);
- cbx_empty->set_default_margin(MARGIN_RIGHT,4);
- cbx_empty->set_default_margin(MARGIN_TOP,4);
- cbx_empty->set_default_margin(MARGIN_BOTTOM,5);
+ cbx_empty->set_default_margin(MARGIN_LEFT,22 *scale);
+ cbx_empty->set_default_margin(MARGIN_RIGHT,4 *scale);
+ cbx_empty->set_default_margin(MARGIN_TOP,4 *scale);
+ cbx_empty->set_default_margin(MARGIN_BOTTOM,5 *scale);
Ref<StyleBox> cbx_focus = focus;
- cbx_focus->set_default_margin(MARGIN_LEFT,4);
- cbx_focus->set_default_margin(MARGIN_RIGHT,22);
- cbx_focus->set_default_margin(MARGIN_TOP,4);
- cbx_focus->set_default_margin(MARGIN_BOTTOM,5);
+ cbx_focus->set_default_margin(MARGIN_LEFT,4 *scale);
+ cbx_focus->set_default_margin(MARGIN_RIGHT,22 *scale);
+ cbx_focus->set_default_margin(MARGIN_TOP,4 *scale);
+ cbx_focus->set_default_margin(MARGIN_BOTTOM,5 *scale);
t->set_stylebox("normal","CheckBox", cbx_empty );
t->set_stylebox("pressed","CheckBox", cbx_empty );
@@ -373,18 +377,18 @@ void make_default_theme() {
t->set_color("font_color_hover","CheckBox", control_font_color_hover );
t->set_color("font_color_disabled","CheckBox", control_font_color_disabled );
- t->set_constant("hseparation","CheckBox",4);
- t->set_constant("check_vadjust","CheckBox",0);
+ t->set_constant("hseparation","CheckBox",4 *scale);
+ t->set_constant("check_vadjust","CheckBox",0 *scale);
// CheckButton
Ref<StyleBox> cb_empty = memnew( StyleBoxEmpty );
- cb_empty->set_default_margin(MARGIN_LEFT,6);
- cb_empty->set_default_margin(MARGIN_RIGHT,70);
- cb_empty->set_default_margin(MARGIN_TOP,4);
- cb_empty->set_default_margin(MARGIN_BOTTOM,4);
+ cb_empty->set_default_margin(MARGIN_LEFT,6 *scale);
+ cb_empty->set_default_margin(MARGIN_RIGHT,70 *scale);
+ cb_empty->set_default_margin(MARGIN_TOP,4 *scale);
+ cb_empty->set_default_margin(MARGIN_BOTTOM,4 *scale);
t->set_stylebox("normal","CheckButton", cb_empty );
t->set_stylebox("pressed","CheckButton", cb_empty );
@@ -402,8 +406,8 @@ void make_default_theme() {
t->set_color("font_color_hover","CheckButton", control_font_color_hover );
t->set_color("font_color_disabled","CheckButton", control_font_color_disabled );
- t->set_constant("hseparation","CheckButton",4);
- t->set_constant("check_vadjust","CheckButton",0);
+ t->set_constant("hseparation","CheckButton",4 *scale);
+ t->set_constant("check_vadjust","CheckButton",0 *scale);
@@ -414,10 +418,10 @@ void make_default_theme() {
t->set_color("font_color","Label", Color(1,1,1) );
t->set_color("font_color_shadow","Label", Color(0,0,0,0) );
- t->set_constant("shadow_offset_x","Label", 1 );
- t->set_constant("shadow_offset_y","Label", 1 );
- t->set_constant("shadow_as_outline","Label", 0 );
- t->set_constant("line_spacing","Label", 3 );
+ t->set_constant("shadow_offset_x","Label", 1 *scale);
+ t->set_constant("shadow_offset_y","Label", 1 *scale);
+ t->set_constant("shadow_as_outline","Label", 0 *scale);
+ t->set_constant("line_spacing","Label", 3 *scale);
@@ -434,7 +438,7 @@ void make_default_theme() {
t->set_color("cursor_color","LineEdit", control_font_color_hover );
t->set_color("selection_color","LineEdit", font_color_selection );
- t->set_constant("minimum_spaces","LineEdit", 12 );
+ t->set_constant("minimum_spaces","LineEdit", 12 *scale);
@@ -468,14 +472,14 @@ void make_default_theme() {
t->set_color("mark_color","TextEdit", Color(1.0,0.4,0.4,0.4) );
t->set_color("breakpoint_color","TextEdit", Color(0.8,0.8,0.4,0.2) );
t->set_color("current_line_color","TextEdit", Color(0.25,0.25,0.26,0.8) );
- t->set_color("cursor_color","TextEdit", control_font_color );
+ t->set_color("caret_color","TextEdit", control_font_color );
t->set_color("symbol_color","TextEdit", control_font_color_hover );
t->set_color("brace_mismatch_color","TextEdit", Color(1,0.2,0.2) );
t->set_constant("completion_lines","TextEdit", 7 );
t->set_constant("completion_max_width","TextEdit", 50 );
t->set_constant("completion_scroll_width","TextEdit", 3 );
- t->set_constant("line_spacing","TextEdit",4 );
+ t->set_constant("line_spacing","TextEdit",4 *scale);
Ref<Texture> empty_icon = memnew( ImageTexture );
@@ -555,10 +559,10 @@ void make_default_theme() {
t->set_color("title_color","WindowDialog", Color(0,0,0) );
- t->set_constant("close_h_ofs","WindowDialog", 22 );
- t->set_constant("close_v_ofs","WindowDialog", 20 );
- t->set_constant("titlebar_height","WindowDialog", 18 );
- t->set_constant("title_height","WindowDialog", 20 );
+ t->set_constant("close_h_ofs","WindowDialog", 22 *scale);
+ t->set_constant("close_v_ofs","WindowDialog", 20 *scale);
+ t->set_constant("titlebar_height","WindowDialog", 18 *scale);
+ t->set_constant("title_height","WindowDialog", 20 *scale);
// File Dialog
@@ -572,7 +576,7 @@ void make_default_theme() {
Ref<StyleBoxTexture> selected = make_stylebox( selection_png,6,6,6,6);
for(int i=0;i<4;i++) {
- selected->set_expand_margin_size(Margin(i),2);
+ selected->set_expand_margin_size(Margin(i),2 *scale);
}
t->set_stylebox("panel","PopupPanel", style_pp );
@@ -598,8 +602,8 @@ void make_default_theme() {
t->set_color("font_color_disabled","PopupMenu", Color(0.4,0.4,0.4,0.8) );
t->set_color("font_color_hover","PopupMenu", control_font_color );
- t->set_constant("hseparation","PopupMenu",4);
- t->set_constant("vseparation","PopupMenu",4);
+ t->set_constant("hseparation","PopupMenu",4 *scale);
+ t->set_constant("vseparation","PopupMenu",4 *scale);
// GraphNode
@@ -614,14 +618,14 @@ void make_default_theme() {
t->set_stylebox("selectedframe","GraphNode", graphsbselected );
t->set_stylebox("defaultframe", "GraphNode", graphsbdefault );
t->set_stylebox("defaultfocus", "GraphNode", graphsbdeffocus );
- t->set_constant("separation","GraphNode", 1 );
+ t->set_constant("separation","GraphNode", 1 *scale);
t->set_icon("port","GraphNode", make_icon( graph_port_png ) );
t->set_icon("close","GraphNode", make_icon( graph_node_close_png ) );
t->set_font("title_font","GraphNode", default_font );
t->set_color("title_color","GraphNode", Color(0,0,0,1));
- t->set_constant("title_offset","GraphNode", 18);
- t->set_constant("close_offset","GraphNode", 18);
- t->set_constant("port_offset","GraphNode", 3);
+ t->set_constant("title_offset","GraphNode", 18 *scale);
+ t->set_constant("close_offset","GraphNode", 18 *scale);
+ t->set_constant("port_offset","GraphNode", 3 *scale);
// Tree
@@ -658,11 +662,11 @@ void make_default_theme() {
t->set_color("guide_color","Tree", Color(0,0,0,0.1) );
t->set_color("drop_position_color","Tree", Color(1,0.3,0.2) );
- t->set_constant("hseparation","Tree",4);
- t->set_constant("vseparation","Tree",4);
- t->set_constant("guide_width","Tree",2);
- t->set_constant("item_margin","Tree",12);
- t->set_constant("button_margin","Tree",4);
+ t->set_constant("hseparation","Tree",4 *scale);
+ t->set_constant("vseparation","Tree",4 *scale);
+ t->set_constant("guide_width","Tree",2 *scale);
+ t->set_constant("item_margin","Tree",12 *scale);
+ t->set_constant("button_margin","Tree",4 *scale);
// ItemList
@@ -674,7 +678,7 @@ void make_default_theme() {
t->set_constant("hseparation","ItemList",4);
t->set_constant("vseparation","ItemList",2);
t->set_constant("icon_margin","ItemList",4);
- t->set_constant("line_separation","ItemList",2);
+ t->set_constant("line_separation","ItemList",2 *scale);
t->set_font("font","ItemList", default_font );
t->set_color("font_color","ItemList", control_font_color_lower );
t->set_color("font_color_selected","ItemList", control_font_color_pressed );
@@ -695,8 +699,8 @@ void make_default_theme() {
Ref<StyleBoxTexture> tc_sb = sb_expand( make_stylebox( tab_container_bg_png,4,4,4,4,4,4,4,4),3,3,3,3);
- tc_sb->set_expand_margin_size(MARGIN_TOP,2);
- tc_sb->set_default_margin(MARGIN_TOP,8);
+ tc_sb->set_expand_margin_size(MARGIN_TOP,2 *scale);
+ tc_sb->set_default_margin(MARGIN_TOP,8 *scale);
t->set_stylebox("tab_fg","TabContainer", sb_expand( make_stylebox( tab_current_png,4,4,4,1,16,4,16,4),2,2,2,2) );
t->set_stylebox("tab_bg","TabContainer", sb_expand( make_stylebox( tab_behind_png,5,5,5,1,16,6,16,4),3,0,3,3) );
@@ -714,11 +718,11 @@ void make_default_theme() {
t->set_color("font_color_fg","TabContainer", control_font_color_hover );
t->set_color("font_color_bg","TabContainer", control_font_color_low );
- t->set_constant("side_margin","TabContainer", 8 );
- t->set_constant("top_margin","TabContainer", 24);
- t->set_constant("label_valign_fg","TabContainer", 0);
- t->set_constant("label_valign_bg","TabContainer", 2);
- t->set_constant("hseparation","TabContainer", 4);
+ t->set_constant("side_margin","TabContainer", 8 *scale);
+ t->set_constant("top_margin","TabContainer", 24 *scale);
+ t->set_constant("label_valign_fg","TabContainer", 0 *scale);
+ t->set_constant("label_valign_bg","TabContainer", 2 *scale);
+ t->set_constant("hseparation","TabContainer", 4 *scale);
@@ -741,10 +745,10 @@ void make_default_theme() {
t->set_color("font_color_fg","Tabs", control_font_color_hover );
t->set_color("font_color_bg","Tabs", control_font_color_low );
- t->set_constant("top_margin","Tabs", 24);
- t->set_constant("label_valign_fg","Tabs", 0);
- t->set_constant("label_valign_bg","Tabs", 2);
- t->set_constant("hseparation","Tabs", 4);
+ t->set_constant("top_margin","Tabs", 24 *scale);
+ t->set_constant("label_valign_fg","Tabs", 0 *scale);
+ t->set_constant("label_valign_bg","Tabs", 2 *scale);
+ t->set_constant("hseparation","Tabs", 4 *scale);
@@ -754,18 +758,17 @@ void make_default_theme() {
t->set_stylebox("separator","VSeparator", make_stylebox( hseparator_png,3,3,3,3) );
t->set_icon("close","Icons", make_icon(icon_close_png));
- t->set_font("source","Fonts", source_font);
t->set_font("normal","Fonts", default_font );
t->set_font("large","Fonts", large_font );
- t->set_constant("separation","HSeparator", 4);
- t->set_constant("separation","VSeparator", 4);
+ t->set_constant("separation","HSeparator", 4 *scale);
+ t->set_constant("separation","VSeparator", 4 *scale);
// Dialogs
- t->set_constant("margin","Dialogs",8);
- t->set_constant("button_margin","Dialogs",32);
+ t->set_constant("margin","Dialogs",8 *scale);
+ t->set_constant("button_margin","Dialogs",32 *scale);
@@ -778,11 +781,11 @@ void make_default_theme() {
// colorPicker
- t->set_constant("value_height","ColorPicker", 23 );
- t->set_constant("value_width","ColorPicker", 50);
- t->set_constant("color_width","ColorPicker", 100);
- t->set_constant("label_width","ColorPicker", 20);
- t->set_constant("hseparator","ColorPicker", 4);
+ t->set_constant("value_height","ColorPicker", 23 *scale);
+ t->set_constant("value_width","ColorPicker", 50 *scale);
+ t->set_constant("color_width","ColorPicker", 100 *scale);
+ t->set_constant("label_width","ColorPicker", 20 *scale);
+ t->set_constant("hseparator","ColorPicker", 4 *scale);
t->set_icon("screen_picker","ColorPicker", make_icon( icon_color_pick_png ) );
t->set_icon("add_preset","ColorPicker", make_icon( icon_add_png ) );
@@ -794,7 +797,7 @@ void make_default_theme() {
Ref<StyleBoxTexture> style_tt = make_stylebox( tooltip_bg_png,4,4,4,4);
for(int i=0;i<4;i++)
- style_tt->set_expand_margin_size((Margin)i,4);
+ style_tt->set_expand_margin_size((Margin)i,4 *scale);
t->set_stylebox("panel","TooltipPanel", style_tt );
@@ -822,9 +825,9 @@ void make_default_theme() {
t->set_color("font_color_selected","RichTextLabel", font_color_selection );
t->set_color("selection_color","RichTextLabel", Color(0.1,0.1,1,0.8) );
- t->set_constant("line_separation","RichTextLabel", 1 );
- t->set_constant("table_hseparation","RichTextLabel", 3 );
- t->set_constant("table_vseparation","RichTextLabel", 3 );
+ t->set_constant("line_separation","RichTextLabel", 1 *scale);
+ t->set_constant("table_hseparation","RichTextLabel", 3 *scale);
+ t->set_constant("table_vseparation","RichTextLabel", 3 *scale);
@@ -836,18 +839,18 @@ void make_default_theme() {
t->set_icon("grabber","VSplitContainer",make_icon(vsplitter_png));
t->set_icon("grabber","HSplitContainer",make_icon(hsplitter_png));
- t->set_constant("separation","HBoxContainer",4);
- t->set_constant("separation","VBoxContainer",4);
- t->set_constant("margin_left","MarginContainer",8);
- t->set_constant("margin_top","MarginContainer",0);
- t->set_constant("margin_right","MarginContainer",0);
- t->set_constant("margin_bottom","MarginContainer",0);
- t->set_constant("hseparation","GridContainer",4);
- t->set_constant("vseparation","GridContainer",4);
- t->set_constant("separation","HSplitContainer",12);
- t->set_constant("separation","VSplitContainer",12);
- t->set_constant("autohide","HSplitContainer",1);
- t->set_constant("autohide","VSplitContainer",1);
+ t->set_constant("separation","HBoxContainer",4 *scale);
+ t->set_constant("separation","VBoxContainer",4 *scale);
+ t->set_constant("margin_left","MarginContainer",8 *scale);
+ t->set_constant("margin_top","MarginContainer",0 *scale);
+ t->set_constant("margin_right","MarginContainer",0 *scale);
+ t->set_constant("margin_bottom","MarginContainer",0 *scale);
+ t->set_constant("hseparation","GridContainer",4 *scale);
+ t->set_constant("vseparation","GridContainer",4 *scale);
+ t->set_constant("separation","HSplitContainer",12 *scale);
+ t->set_constant("separation","VSplitContainer",12 *scale);
+ t->set_constant("autohide","HSplitContainer",1 *scale);
+ t->set_constant("autohide","VSplitContainer",1 *scale);
@@ -863,8 +866,8 @@ void make_default_theme() {
t->set_color("font_color","HButtonArray", control_font_color_low );
t->set_color("font_color_selected","HButtonArray", control_font_color_hover );
- t->set_constant("icon_separator","HButtonArray", 4 );
- t->set_constant("button_separator","HButtonArray", 8 );
+ t->set_constant("icon_separator","HButtonArray", 4 *scale );
+ t->set_constant("button_separator","HButtonArray", 8 *scale );
t->set_stylebox("focus","HButtonArray", focus );
@@ -881,8 +884,8 @@ void make_default_theme() {
t->set_color("font_color","VButtonArray", control_font_color_low );
t->set_color("font_color_selected","VButtonArray", control_font_color_hover );
- t->set_constant("icon_separator","VButtonArray", 4);
- t->set_constant("button_separator","VButtonArray", 8);
+ t->set_constant("icon_separator","VButtonArray", 4 *scale);
+ t->set_constant("button_separator","VButtonArray", 8 *scale);
t->set_stylebox("focus","VButtonArray", focus );
@@ -914,45 +917,31 @@ void make_default_theme() {
// Theme
- Theme::set_default( t );
- Theme::set_default_icon( make_icon(error_icon_png) );
- Theme::set_default_style( make_stylebox( error_icon_png,2,2,2,2) );
- Theme::set_default_font( default_font );
+ default_icon= make_icon(error_icon_png) ;
+ default_style = make_stylebox( error_icon_png,2,2,2,2) ;
memdelete( tex_cache );
}
-#else
-
-#include "error_icon.xpm"
-
void make_default_theme() {
- Ref<Theme> t( memnew( Theme ) );
-
+ Ref<Theme> t;
+ t.instance();
- Image error_img(error_icon_xpm);
- Ref<Texture> texture( memnew( Texture ) );
- texture->create_from_image( error_img );
-
- Ref<StyleBoxTexture> style( memnew( StyleBoxTexture ) );
- style->set_texture(texture);
-
- for(int i=0;i<4;i++) {
- style->set_margin_size( Margin(),8);
- style->set_default_margin( Margin(),8);
- }
+ Ref<StyleBox> default_style;
+ Ref<Texture> default_icon;
+ Ref<BitmapFont> default_font=make_font2(_builtin_normal_font_height,_builtin_normal_font_ascent,_builtin_normal_font_charcount,&_builtin_normal_font_charrects[0][0],_builtin_normal_font_kerning_pair_count,&_builtin_normal_font_kerning_pairs[0][0],_builtin_normal_font_img_width,_builtin_normal_font_img_height,_builtin_normal_font_img_data);
+ Ref<BitmapFont> large_font=make_font2(_builtin_large_font_height,_builtin_large_font_ascent,_builtin_large_font_charcount,&_builtin_large_font_charrects[0][0],_builtin_large_font_kerning_pair_count,&_builtin_large_font_kerning_pairs[0][0],_builtin_large_font_img_width,_builtin_large_font_img_height,_builtin_large_font_img_data);
+ fill_default_theme(t,default_font,large_font,default_icon,default_style,false);
- Ref<BitmapFont> f = make_default_font();
Theme::set_default( t );
- Theme::set_default_icon( texture );
- Theme::set_default_style( style );
- Theme::set_default_font( f );
+ Theme::set_default_icon( default_icon );
+ Theme::set_default_style( default_style );
+ Theme::set_default_font( default_font );
}
-#endif
void clear_default_theme() {
Theme::set_default( Ref<Theme>() );
diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h
index 44569ba192..1e3b4b4081 100644
--- a/scene/resources/default_theme/default_theme.h
+++ b/scene/resources/default_theme/default_theme.h
@@ -12,10 +12,12 @@
#ifndef DEFAULT_THEME_H
#define DEFAULT_THEME_H
+#include "scene/resources/theme.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
+void fill_default_theme(Ref<Theme>& theme,const Ref<Font> & default_font,const Ref<Font> & large_font,Ref<Texture>& default_icon, Ref<StyleBox>& default_style,bool p_hidpi);
void make_default_theme();
void clear_default_theme();
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index 19aa0e79cc..c76b5f3d3a 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -1,65 +1,11 @@
+#ifdef FREETYPE_ENABLED
#include "dynamic_font.h"
-#define STB_TRUETYPE_IMPLEMENTATION
-#include "stb_truetype.h"
#include "os/file_access.h"
-void DynamicFontData::lock() {
- fr=font_data.read();
-
- if (fr.ptr()!=last_data_ptr) {
-
- last_data_ptr=fr.ptr();
-
- if (!stbtt_InitFont(&info, last_data_ptr, 0)) {
- valid=false;
- } else {
- valid=true;
- }
-
- last_data_ptr=fr.ptr();
- }
-}
-
-void DynamicFontData::unlock() {
-
- fr = DVector<uint8_t>::Read();
-}
-
-void DynamicFontData::set_font_data(const DVector<uint8_t>& p_font) {
- //clear caches and stuff
- ERR_FAIL_COND(font_data.size()) ;
- font_data=p_font;
-
- lock();
-
- if (valid) {
- stbtt_GetFontVMetrics(&info, &ascent, &descent, &linegap);
- descent=-descent + linegap;
-
- for(int i=32;i<1024;i++) {
- for(int j=32;j<1024;j++) {
-
- int kern = stbtt_GetCodepointKernAdvance(&info, i,j);
- if (kern!=0) {
- KerningPairKey kpk;
- kpk.A=i;
- kpk.B=j;
- kerning_map[kpk]=kern;
- }
- }
- }
- }
-
- unlock();
- //clear existing stuff
-
- ERR_FAIL_COND(!valid);
-}
Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(int p_size) {
- ERR_FAIL_COND_V(!valid,Ref<DynamicFontAtSize>());
if (size_cache.has(p_size)) {
return Ref<DynamicFontAtSize>( size_cache[p_size] );
@@ -67,6 +13,7 @@ Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(int p_size) {
Ref<DynamicFontAtSize> dfas;
+
dfas.instance();
dfas->font=Ref<DynamicFontData>( this );
@@ -74,21 +21,34 @@ Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(int p_size) {
size_cache[p_size]=dfas.ptr();
dfas->size=p_size;
+ dfas->_load();
+
+ return dfas;
- lock();
+}
- dfas->scale = stbtt_ScaleForPixelHeight(&info, p_size);
+void DynamicFontData::set_font_ptr(const uint8_t* p_font_mem,int p_font_mem_size) {
- unlock();
+ font_mem=p_font_mem;
+ font_mem_size=p_font_mem_size;
+}
- return dfas;
+void DynamicFontData::set_font_path(const String& p_path) {
+
+ font_path=p_path;
+}
+
+void DynamicFontData::set_force_autohinter(bool p_force) {
+ force_autohinter=p_force;
}
DynamicFontData::DynamicFontData()
{
- last_data_ptr=NULL;
- valid=false;
+
+ force_autohinter=false;
+ font_mem=NULL;
+ font_mem_size=0;
}
DynamicFontData::~DynamicFontData()
@@ -100,22 +60,106 @@ DynamicFontData::~DynamicFontData()
////////////////////
+Error DynamicFontAtSize::_load() {
+
+
+ int error = FT_Init_FreeType( &library );
+
+ ERR_EXPLAIN(TTR("Error initializing FreeType."));
+ ERR_FAIL_COND_V( error !=0, ERR_CANT_CREATE );
+
+ if (font->font_path!=String()) {
+
+ FileAccess *f=FileAccess::open(font->font_path,FileAccess::READ);
+ ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
+
+ memset(&stream,0,sizeof(FT_StreamRec));
+ stream.base=NULL;
+ stream.size=f->get_len();
+ stream.pos=0;
+ stream.descriptor.pointer=f;
+ stream.read=_ft_stream_io;
+ stream.close=_ft_stream_close;
+
+ FT_Open_Args fargs;
+ memset(&fargs,0,sizeof(FT_Open_Args));
+ fargs.flags=FT_OPEN_STREAM;
+ fargs.stream=&stream;
+ error = FT_Open_Face( library,&fargs,0,&face);
+ } else if (font->font_mem) {
+
+ memset(&stream,0,sizeof(FT_StreamRec));
+ stream.base=(unsigned char*)font->font_mem;
+ stream.size=font->font_mem_size;
+ stream.pos=0;
+
+ FT_Open_Args fargs;
+ memset(&fargs,0,sizeof(FT_Open_Args));
+ fargs.memory_base=(unsigned char*)font->font_mem;
+ fargs.memory_size=font->font_mem_size;
+ fargs.flags= FT_OPEN_MEMORY;
+ fargs.stream=&stream;
+ error = FT_Open_Face( library,&fargs,0,&face);
+
+ } else {
+ ERR_EXPLAIN("DynamicFont uninitialized");
+ ERR_FAIL_V(ERR_UNCONFIGURED);
+ }
+
+ //error = FT_New_Face( library, src_path.utf8().get_data(),0,&face );
+
+ if ( error == FT_Err_Unknown_File_Format ) {
+ ERR_EXPLAIN(TTR("Unknown font format."));
+ FT_Done_FreeType( library );
+
+ } else if ( error ) {
+
+ ERR_EXPLAIN(TTR("Error loading font."));
+ FT_Done_FreeType( library );
+
+ }
+
+ ERR_FAIL_COND_V(error,ERR_FILE_CANT_OPEN);
+
+
+ /*error = FT_Set_Char_Size(face,0,64*size,512,512);
+
+ if ( error ) {
+ FT_Done_FreeType( library );
+ ERR_EXPLAIN(TTR("Invalid font size."));
+ ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER );
+ }*/
+
+ error = FT_Set_Pixel_Sizes(face,0,size);
+
+ ascent=face->size->metrics.ascender>>6;
+ descent=-face->size->metrics.descender>>6;
+ linegap=0;
+
+ //print_line("ASCENT: "+itos(ascent)+" descent "+itos(descent)+" hinted: "+itos(face->face_flags&FT_FACE_FLAG_HINTER));
+
+ valid=true;
+ return OK;
+}
+
float DynamicFontAtSize::get_height() const {
- return (font->ascent+font->descent)*scale;
+ return ascent+descent;
}
float DynamicFontAtSize::get_ascent() const {
- return font->ascent*scale;
+ return ascent;
}
float DynamicFontAtSize::get_descent() const {
- return font->descent*scale;
+ return descent;
}
Size2 DynamicFontAtSize::get_char_size(CharType p_char,CharType p_next) const {
+ if (!valid)
+ return Size2(1,1);
const_cast<DynamicFontAtSize*>(this)->_update_char(p_char);
const Character *c = char_map.getptr(p_char);
@@ -124,14 +168,9 @@ Size2 DynamicFontAtSize::get_char_size(CharType p_char,CharType p_next) const {
Size2 ret( c->advance, get_height());
if (p_next) {
- DynamicFontData::KerningPairKey kpk;
- kpk.A=p_char;
- kpk.B=p_next;
-
- const Map<DynamicFontData::KerningPairKey,int>::Element *K=font->kerning_map.find(kpk);
- if (K) {
- ret.x+=K->get()*scale;
- }
+ FT_Vector delta;
+ FT_Get_Kerning( face, p_char,p_next, FT_KERNING_DEFAULT, &delta );
+ ret.x+=delta.x>>6;
}
@@ -141,6 +180,9 @@ Size2 DynamicFontAtSize::get_char_size(CharType p_char,CharType p_next) const {
float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2& p_pos, const CharType& p_char,const CharType& p_next,const Color& p_modulate) const {
+ if (!valid)
+ return 0;
+
const_cast<DynamicFontAtSize*>(this)->_update_char(p_char);
const Character * c = char_map.getptr(p_char);
@@ -161,58 +203,84 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2& p_pos, const
float ret = c->advance;
if (p_next) {
- DynamicFontData::KerningPairKey kpk;
- kpk.A=p_char;
- kpk.B=p_next;
- const Map<DynamicFontData::KerningPairKey,int>::Element *K=font->kerning_map.find(kpk);
- if (K) {
- ret+=K->get()*scale;
- }
+ FT_Vector delta;
+ FT_Get_Kerning( face, p_char,p_next, FT_KERNING_DEFAULT, &delta );
+ ret+=delta.x>>6;
}
return ret;
}
+unsigned long DynamicFontAtSize::_ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count ) {
+
+
+ FileAccess *f=(FileAccess*)stream->descriptor.pointer;
+
+ if (f->get_pos()!=offset) {
+ f->seek(offset);
+
+ }
+
+ if (count==0)
+ return 0;
+
+ return f->get_buffer(buffer,count);
+}
+void DynamicFontAtSize::_ft_stream_close(FT_Stream stream) {
+
+ FileAccess *f=(FileAccess*)stream->descriptor.pointer;
+ f->close();
+ memdelete(f);
+}
+
void DynamicFontAtSize::_update_char(CharType p_char) {
if (char_map.has(p_char))
return;
- font->lock();
-
+ _THREAD_SAFE_METHOD_
- int w,h,xofs,yofs;
- unsigned char * cpbitmap = stbtt_GetCodepointBitmap(&font->info, scale, scale, p_char, &w, &h, &xofs, &yofs );
+ FT_GlyphSlot slot = face->glyph;
- if (!cpbitmap) {
- //no glyph
+ int error = FT_Load_Char( face, p_char, FT_LOAD_RENDER|(font->force_autohinter?FT_LOAD_FORCE_AUTOHINT:0) );
+ if (!error) {
+ error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
+ }
+ if (error) {
- int advance;
- stbtt_GetCodepointHMetrics(&font->info, p_char, &advance, 0);
+ int advance=0;
+ //stbtt_GetCodepointHMetrics(&font->info, p_char, &advance, 0);
//print_line("char has no bitmap: "+itos(p_char)+" but advance is "+itos(advance*scale));
Character ch;
ch.texture_idx=-1;
- ch.advance=advance*scale;
+ ch.advance=advance;
ch.h_align=0;
ch.v_align=0;
char_map[p_char]=ch;
- font->unlock();
return;
}
+
+
+ int w = slot->bitmap.width;
+ int h = slot->bitmap.rows;
+ int p = slot->bitmap.pitch;
+ int yofs=slot->bitmap_top;
+ int xofs=slot->bitmap_left;
+ int advance=slot->advance.x>>6;
+
+
int mw=w+rect_margin*2;
int mh=h+rect_margin*2;
if (mw>4096 || mh>4096) {
- stbtt_FreeBitmap(cpbitmap,NULL);
- font->unlock();
ERR_FAIL_COND(mw>4096);
ERR_FAIL_COND(mh>4096);
}
@@ -304,13 +372,14 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
{
DVector<uint8_t>::Write wr = tex.imgdata.write();
+
for(int i=0;i<h;i++) {
for(int j=0;j<w;j++) {
int ofs = ( (i+tex_y+rect_margin)*tex.texture_size+j+tex_x+rect_margin)*2;
ERR_FAIL_COND(ofs >= tex.imgdata.size());
wr[ofs+0]=255; //grayscale as 1
- wr[ofs+1]=cpbitmap[i*w+j]; //alpha as 0
+ wr[ofs+1]=slot->bitmap.buffer[i*slot->bitmap.width+j];
}
}
}
@@ -322,7 +391,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
if (tex.texture.is_null()) {
tex.texture.instance();
- tex.texture->create_from_image(img,Texture::FLAG_FILTER);
+ tex.texture->create_from_image(img,0/*Texture::FLAG_FILTER*/);
} else {
tex.texture->set_data(img); //update
}
@@ -337,13 +406,11 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
tex.offsets[k]=tex_y+mh;
}
- int advance;
- stbtt_GetCodepointHMetrics(&font->info, p_char, &advance, 0);
Character chr;
chr.h_align=xofs;
- chr.v_align=yofs + get_ascent();
- chr.advance=advance*scale;
+ chr.v_align=ascent-yofs;// + ascent - descent;
+ chr.advance=advance;
chr.texture_idx=tex_index;
@@ -353,21 +420,24 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
char_map[p_char]=chr;
- stbtt_FreeBitmap(cpbitmap,NULL);
-
- font->unlock();
}
DynamicFontAtSize::DynamicFontAtSize() {
+ valid=false;
rect_margin=1;
+ ascent=1;
+ descent=1;
+ linegap=1;
}
DynamicFontAtSize::~DynamicFontAtSize(){
- ERR_FAIL_COND(!font.ptr());
- font->size_cache.erase(size);
+ if (valid) {
+ FT_Done_FreeType( library );
+ font->size_cache.erase(size);
+ }
}
/////////////////////////
@@ -478,34 +548,21 @@ RES ResourceFormatLoaderDynamicFont::load(const String &p_path, const String& p_
if (r_error)
*r_error=ERR_FILE_CANT_OPEN;
+ Ref<DynamicFontData> dfont;
+ dfont.instance();;
+ dfont->set_font_path(p_path);
- FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
- ERR_FAIL_COND_V(!f,RES());
-
- DVector<uint8_t> data;
-
- data.resize(f->get_len());
-
- ERR_FAIL_COND_V(data.size()==0,RES());
-
- {
- DVector<uint8_t>::Write w = data.write();
- f->get_buffer(w.ptr(),data.size());
- }
-
- Ref<DynamicFontData> dfd;
- dfd.instance();
- dfd->set_font_data(data);
if (r_error)
*r_error=OK;
- return dfd;
+ return dfont;
}
void ResourceFormatLoaderDynamicFont::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("ttf");
+ p_extensions->push_back("otf");
}
bool ResourceFormatLoaderDynamicFont::handles_type(const String& p_type) const {
@@ -516,8 +573,10 @@ bool ResourceFormatLoaderDynamicFont::handles_type(const String& p_type) const {
String ResourceFormatLoaderDynamicFont::get_resource_type(const String &p_path) const {
String el = p_path.extension().to_lower();
- if (el=="ttf")
+ if (el=="ttf" || el=="otf")
return "DynamicFontData";
return "";
}
+
+#endif
diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h
index ba7249a7b7..f0cf80b042 100644
--- a/scene/resources/dynamic_font.h
+++ b/scene/resources/dynamic_font.h
@@ -1,10 +1,14 @@
-#ifndef DYNAMICFONT_H
-#define DYNAMICFONT_H
+#ifndef DYNAMIC_FONT_H
+#define DYNAMIC_FONT_H
-#include "font.h"
-#include "stb_truetype.h"
+#ifdef FREETYPE_ENABLED
+#include "scene/resources/font.h"
+#include "os/thread_safe.h"
#include "io/resource_loader.h"
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
class DynamicFontAtSize;
class DynamicFont;
@@ -13,39 +17,16 @@ class DynamicFontData : public Resource {
OBJ_TYPE(DynamicFontData,Resource);
- bool valid;
-
- DVector<uint8_t> font_data;
- DVector<uint8_t>::Read fr;
- const uint8_t* last_data_ptr;
-
- struct KerningPairKey {
-
- union {
- struct {
- uint32_t A,B;
- };
-
- uint64_t pair;
- };
-
- _FORCE_INLINE_ bool operator<(const KerningPairKey& p_r) const { return pair<p_r.pair; }
- };
- Map<KerningPairKey,int> kerning_map;
+ const uint8_t *font_mem;
+ int font_mem_size;
+ bool force_autohinter;
+ String font_path;
Map<int,DynamicFontAtSize*> size_cache;
-friend class DynamicFontAtSize;
-
- stbtt_fontinfo info;
- int ascent;
- int descent;
- int linegap;
-
- void lock();
- void unlock();
+ friend class DynamicFontAtSize;
friend class DynamicFont;
@@ -53,7 +34,10 @@ friend class DynamicFont;
Ref<DynamicFontAtSize> _get_dynamic_font_at_size(int p_size);
public:
- void set_font_data(const DVector<uint8_t>& p_font);
+ void set_font_ptr(const uint8_t* p_font_mem,int p_font_mem_size);
+ void set_font_path(const String& p_path);
+ void set_force_autohinter(bool p_force);
+
DynamicFontData();
~DynamicFontData();
};
@@ -61,11 +45,21 @@ public:
class DynamicFontAtSize : public Reference {
- OBJ_TYPE(DynamicFontAtSize,Reference);
+ OBJ_TYPE(DynamicFontAtSize,Reference)
+ _THREAD_SAFE_CLASS_
+ FT_Library library; /* handle to library */
+ FT_Face face; /* handle to face object */
+ FT_StreamRec stream;
+
+ int ascent;
+ int descent;
+ int linegap;
int rect_margin;
+ bool valid;
+
struct CharTexture {
DVector<uint8_t> imgdata;
@@ -88,6 +82,8 @@ class DynamicFontAtSize : public Reference {
};
+ static unsigned long _ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count );
+ static void _ft_stream_close(FT_Stream stream);
HashMap< CharType, Character > char_map;
@@ -95,13 +91,18 @@ class DynamicFontAtSize : public Reference {
friend class DynamicFontData;
Ref<DynamicFontData> font;
- float scale;
int size;
+
+
+ Error _load();
protected:
+
+
public:
+
float get_height() const;
float get_ascent() const;
@@ -126,7 +127,7 @@ class DynamicFont : public Font {
Ref<DynamicFontData> data;
Ref<DynamicFontAtSize> data_at_size;
int size;
-
+ bool valid;
protected:
@@ -171,5 +172,6 @@ public:
};
+#endif
-#endif // DYNAMICFONT_H
+#endif
diff --git a/scene/resources/dynamic_font_stb.cpp b/scene/resources/dynamic_font_stb.cpp
new file mode 100644
index 0000000000..344043fcdd
--- /dev/null
+++ b/scene/resources/dynamic_font_stb.cpp
@@ -0,0 +1,527 @@
+#include "dynamic_font_stb.h"
+
+#ifndef FREETYPE_ENABLED
+
+#define STB_TRUETYPE_IMPLEMENTATION
+#include "stb_truetype.h"
+#include "os/file_access.h"
+
+void DynamicFontData::lock() {
+
+ fr=font_data.read();
+
+ if (fr.ptr()!=last_data_ptr) {
+
+ last_data_ptr=fr.ptr();
+
+ if (!stbtt_InitFont(&info, last_data_ptr, 0)) {
+ valid=false;
+ } else {
+ valid=true;
+ }
+
+ last_data_ptr=fr.ptr();
+ }
+}
+
+void DynamicFontData::unlock() {
+
+ fr = DVector<uint8_t>::Read();
+}
+
+void DynamicFontData::set_font_data(const DVector<uint8_t>& p_font) {
+ //clear caches and stuff
+ ERR_FAIL_COND(font_data.size()) ;
+ font_data=p_font;
+
+ lock();
+
+ if (valid) {
+ stbtt_GetFontVMetrics(&info, &ascent, &descent, &linegap);
+ descent=-descent + linegap;
+
+ for(int i=32;i<1024;i++) {
+ for(int j=32;j<1024;j++) {
+
+ int kern = stbtt_GetCodepointKernAdvance(&info, i,j);
+ if (kern!=0) {
+ KerningPairKey kpk;
+ kpk.A=i;
+ kpk.B=j;
+ kerning_map[kpk]=kern;
+ }
+ }
+ }
+ }
+
+ unlock();
+ //clear existing stuff
+
+ ERR_FAIL_COND(!valid);
+}
+
+Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(int p_size) {
+
+ ERR_FAIL_COND_V(!valid,Ref<DynamicFontAtSize>());
+
+ if (size_cache.has(p_size)) {
+ return Ref<DynamicFontAtSize>( size_cache[p_size] );
+ }
+
+
+ Ref<DynamicFontAtSize> dfas;
+ dfas.instance();
+
+ dfas->font=Ref<DynamicFontData>( this );
+
+ size_cache[p_size]=dfas.ptr();
+
+ dfas->size=p_size;
+
+ lock();
+
+ dfas->scale = stbtt_ScaleForPixelHeight(&info, p_size);
+
+ unlock();
+
+ return dfas;
+
+}
+
+DynamicFontData::DynamicFontData()
+{
+ last_data_ptr=NULL;
+ valid=false;
+}
+
+DynamicFontData::~DynamicFontData()
+{
+
+}
+
+
+
+////////////////////
+
+float DynamicFontAtSize::get_height() const {
+
+ return (font->ascent+font->descent)*scale;
+}
+
+float DynamicFontAtSize::get_ascent() const {
+
+ return font->ascent*scale;
+}
+float DynamicFontAtSize::get_descent() const {
+
+ return font->descent*scale;
+}
+
+Size2 DynamicFontAtSize::get_char_size(CharType p_char,CharType p_next) const {
+
+ const_cast<DynamicFontAtSize*>(this)->_update_char(p_char);
+
+ const Character *c = char_map.getptr(p_char);
+ ERR_FAIL_COND_V(!c,Size2());
+
+ Size2 ret( c->advance, get_height());
+
+ if (p_next) {
+ DynamicFontData::KerningPairKey kpk;
+ kpk.A=p_char;
+ kpk.B=p_next;
+
+ const Map<DynamicFontData::KerningPairKey,int>::Element *K=font->kerning_map.find(kpk);
+ if (K) {
+ ret.x+=K->get()*scale;
+ }
+
+ }
+
+ return ret;
+}
+
+
+float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2& p_pos, const CharType& p_char,const CharType& p_next,const Color& p_modulate) const {
+
+ const_cast<DynamicFontAtSize*>(this)->_update_char(p_char);
+
+ const Character * c = char_map.getptr(p_char);
+
+ if (!c) {
+ return 0;
+ }
+
+ Point2 cpos=p_pos;
+ cpos.x+=c->h_align;
+ cpos.y-=get_ascent();
+ 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 );
+
+ //textures[c->texture_idx].texture->draw(p_canvas_item,Vector2());
+
+ float ret = c->advance;
+ if (p_next) {
+ DynamicFontData::KerningPairKey kpk;
+ kpk.A=p_char;
+ kpk.B=p_next;
+
+ const Map<DynamicFontData::KerningPairKey,int>::Element *K=font->kerning_map.find(kpk);
+ if (K) {
+ ret+=K->get()*scale;
+ }
+
+ }
+
+ return ret;
+}
+
+
+void DynamicFontAtSize::_update_char(CharType p_char) {
+
+ if (char_map.has(p_char))
+ return;
+
+ font->lock();
+
+
+ int w,h,xofs,yofs;
+ unsigned char * cpbitmap = stbtt_GetCodepointBitmap(&font->info, scale, scale, p_char, &w, &h, &xofs, &yofs );
+
+ if (!cpbitmap) {
+ //no glyph
+
+ int advance;
+ stbtt_GetCodepointHMetrics(&font->info, p_char, &advance, 0);
+ //print_line("char has no bitmap: "+itos(p_char)+" but advance is "+itos(advance*scale));
+ Character ch;
+ ch.texture_idx=-1;
+ ch.advance=advance*scale;
+ ch.h_align=0;
+ ch.v_align=0;
+
+ char_map[p_char]=ch;
+
+ font->unlock();
+
+ return;
+ }
+
+ int mw=w+rect_margin*2;
+ int mh=h+rect_margin*2;
+
+ if (mw>4096 || mh>4096) {
+
+ stbtt_FreeBitmap(cpbitmap,NULL);
+ font->unlock();
+ ERR_FAIL_COND(mw>4096);
+ ERR_FAIL_COND(mh>4096);
+ }
+
+ //find a texture to fit this...
+
+ int tex_index=-1;
+ int tex_x=0;
+ int tex_y=0;
+
+ for(int i=0;i<textures.size();i++) {
+
+ CharTexture &ct=textures[i];
+
+ if (mw > ct.texture_size || mh > ct.texture_size) //too big for this texture
+ continue;
+
+ tex_y=0x7FFFFFFF;
+ tex_x=0;
+
+ for(int j=0;j<ct.texture_size-mw;j++) {
+
+ int max_y=0;
+
+ for(int k=j;k<j+mw;k++) {
+
+ int y = ct.offsets[k];
+ if (y>max_y)
+ max_y=y;
+ }
+
+ if (max_y<tex_y) {
+ tex_y=max_y;
+ tex_x=j;
+ }
+ }
+
+ if (tex_y==0x7FFFFFFF || tex_y+mh > ct.texture_size)
+ continue; //fail, could not fit it here
+
+ tex_index=i;
+ break;
+ }
+
+// print_line("CHAR: "+String::chr(p_char)+" TEX INDEX: "+itos(tex_index)+" X: "+itos(tex_x)+" Y: "+itos(tex_y));
+
+ if (tex_index==-1) {
+ //could not find texture to fit, create one
+ tex_x = 0;
+ tex_y = 0;
+
+ int texsize = MAX(size*8,256);
+ if (mw>texsize)
+ texsize=mw; //special case, adapt to it?
+ if (mh>texsize)
+ texsize=mh; //special case, adapt to it?
+
+ texsize=nearest_power_of_2(texsize);
+
+ texsize=MIN(texsize,4096);
+
+
+ CharTexture tex;
+ tex.texture_size=texsize;
+ tex.imgdata.resize(texsize*texsize*2); //grayscale alpha
+
+ {
+ //zero texture
+ DVector<uint8_t>::Write w = tex.imgdata.write();
+ ERR_FAIL_COND(texsize*texsize*2 > tex.imgdata.size());
+ for(int i=0;i<texsize*texsize*2;i++) {
+ w[i]=0;
+ }
+ }
+ tex.offsets.resize(texsize);
+ for(int i=0;i<texsize;i++) //zero offsets
+ tex.offsets[i]=0;
+
+ textures.push_back(tex);
+ tex_index=textures.size()-1;
+
+ }
+
+
+ //fit character in char texture
+
+ CharTexture &tex=textures[tex_index];
+
+ {
+ DVector<uint8_t>::Write wr = tex.imgdata.write();
+
+ for(int i=0;i<h;i++) {
+ for(int j=0;j<w;j++) {
+
+ int ofs = ( (i+tex_y+rect_margin)*tex.texture_size+j+tex_x+rect_margin)*2;
+ ERR_FAIL_COND(ofs >= tex.imgdata.size());
+ wr[ofs+0]=255; //grayscale as 1
+ wr[ofs+1]=cpbitmap[i*w+j]; //alpha as 0
+ }
+ }
+ }
+
+ //blit to image and texture
+ {
+
+ Image img(tex.texture_size,tex.texture_size,0,Image::FORMAT_GRAYSCALE_ALPHA,tex.imgdata);
+
+ if (tex.texture.is_null()) {
+ tex.texture.instance();
+ tex.texture->create_from_image(img,Texture::FLAG_FILTER);
+ } else {
+ tex.texture->set_data(img); //update
+ }
+
+ }
+
+
+ // update height array
+
+ for(int k=tex_x;k<tex_x+mw;k++) {
+
+ tex.offsets[k]=tex_y+mh;
+ }
+
+ int advance;
+ stbtt_GetCodepointHMetrics(&font->info, p_char, &advance, 0);
+
+ Character chr;
+ chr.h_align=xofs;
+ chr.v_align=yofs + get_ascent();
+ chr.advance=advance*scale;
+ chr.texture_idx=tex_index;
+
+
+ chr.rect=Rect2(tex_x+rect_margin,tex_y+rect_margin,w,h);
+
+ //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;
+
+ stbtt_FreeBitmap(cpbitmap,NULL);
+
+ font->unlock();
+
+}
+
+DynamicFontAtSize::DynamicFontAtSize() {
+
+ rect_margin=1;
+}
+
+DynamicFontAtSize::~DynamicFontAtSize(){
+
+ ERR_FAIL_COND(!font.ptr());
+ font->size_cache.erase(size);
+}
+
+/////////////////////////
+
+
+void DynamicFont::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_font_data","data:DynamicFontData"),&DynamicFont::set_font_data);
+ ObjectTypeDB::bind_method(_MD("get_font_data:DynamicFontData"),&DynamicFont::get_font_data);
+
+ ObjectTypeDB::bind_method(_MD("set_size","data"),&DynamicFont::set_size);
+ ObjectTypeDB::bind_method(_MD("get_size"),&DynamicFont::get_size);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"size"),_SCS("set_size"),_SCS("get_size"));
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"font",PROPERTY_HINT_RESOURCE_TYPE,"DynamicFontData"),_SCS("set_font_data"),_SCS("get_font_data"));
+}
+
+
+void DynamicFont::set_font_data(const Ref<DynamicFontData>& p_data) {
+
+ data=p_data;
+ data_at_size=data->_get_dynamic_font_at_size(size);
+}
+
+Ref<DynamicFontData> DynamicFont::get_font_data() const{
+
+ return data;
+}
+
+void DynamicFont::set_size(int p_size){
+
+ if (size==p_size)
+ return;
+ size=p_size;
+ ERR_FAIL_COND(p_size<1);
+ if (!data.is_valid())
+ return;
+ data_at_size=data->_get_dynamic_font_at_size(size);
+
+}
+int DynamicFont::get_size() const{
+
+ return size;
+}
+
+float DynamicFont::get_height() const{
+
+ if (!data_at_size.is_valid())
+ return 1;
+
+ return data_at_size->get_height();
+}
+
+float DynamicFont::get_ascent() const{
+
+ if (!data_at_size.is_valid())
+ return 1;
+
+ return data_at_size->get_ascent();
+}
+
+float DynamicFont::get_descent() const{
+
+ if (!data_at_size.is_valid())
+ return 1;
+
+ return data_at_size->get_descent();
+
+}
+
+Size2 DynamicFont::get_char_size(CharType p_char,CharType p_next) const{
+
+ if (!data_at_size.is_valid())
+ return Size2(1,1);
+
+ return data_at_size->get_char_size(p_char,p_next);
+
+}
+
+bool DynamicFont::is_distance_field_hint() const{
+
+ return false;
+}
+
+float DynamicFont::draw_char(RID p_canvas_item, const Point2& p_pos, const CharType& p_char,const CharType& p_next,const Color& p_modulate) const {
+
+ if (!data_at_size.is_valid())
+ return 0;
+
+ return data_at_size->draw_char(p_canvas_item,p_pos,p_char,p_next,p_modulate);
+
+}
+
+DynamicFont::DynamicFont() {
+
+ size=16;
+}
+
+DynamicFont::~DynamicFont() {
+
+}
+
+/////////////////////////
+
+
+RES ResourceFormatLoaderDynamicFont::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_FILE_CANT_OPEN;
+
+
+ FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
+ ERR_FAIL_COND_V(!f,RES());
+
+ DVector<uint8_t> data;
+
+ data.resize(f->get_len());
+
+ ERR_FAIL_COND_V(data.size()==0,RES());
+
+ {
+ DVector<uint8_t>::Write w = data.write();
+ f->get_buffer(w.ptr(),data.size());
+ }
+
+ Ref<DynamicFontData> dfd;
+ dfd.instance();
+ dfd->set_font_data(data);
+
+ if (r_error)
+ *r_error=OK;
+
+ return dfd;
+}
+
+void ResourceFormatLoaderDynamicFont::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("ttf");
+}
+
+bool ResourceFormatLoaderDynamicFont::handles_type(const String& p_type) const {
+
+ return (p_type=="DynamicFontData");
+}
+
+String ResourceFormatLoaderDynamicFont::get_resource_type(const String &p_path) const {
+
+ String el = p_path.extension().to_lower();
+ if (el=="ttf")
+ return "DynamicFontData";
+ return "";
+}
+
+#endif
diff --git a/scene/resources/dynamic_font_stb.h b/scene/resources/dynamic_font_stb.h
new file mode 100644
index 0000000000..6b72fb3703
--- /dev/null
+++ b/scene/resources/dynamic_font_stb.h
@@ -0,0 +1,178 @@
+#ifndef DYNAMICFONT_STB_H
+#define DYNAMICFONT_STB_H
+
+#ifndef FREETYPE_ENABLED
+
+#include "font.h"
+#include "stb_truetype.h"
+#include "io/resource_loader.h"
+
+
+
+class DynamicFontAtSize;
+class DynamicFont;
+
+class DynamicFontData : public Resource {
+
+ OBJ_TYPE(DynamicFontData,Resource);
+
+ bool valid;
+
+ DVector<uint8_t> font_data;
+ DVector<uint8_t>::Read fr;
+ const uint8_t* last_data_ptr;
+
+ struct KerningPairKey {
+
+ union {
+ struct {
+ uint32_t A,B;
+ };
+
+ uint64_t pair;
+ };
+
+ _FORCE_INLINE_ bool operator<(const KerningPairKey& p_r) const { return pair<p_r.pair; }
+ };
+
+ Map<KerningPairKey,int> kerning_map;
+
+
+ Map<int,DynamicFontAtSize*> size_cache;
+
+friend class DynamicFontAtSize;
+
+ stbtt_fontinfo info;
+ int ascent;
+ int descent;
+ int linegap;
+
+ void lock();
+ void unlock();
+
+friend class DynamicFont;
+
+
+ Ref<DynamicFontAtSize> _get_dynamic_font_at_size(int p_size);
+public:
+
+ void set_font_data(const DVector<uint8_t>& p_font);
+ DynamicFontData();
+ ~DynamicFontData();
+};
+
+
+class DynamicFontAtSize : public Reference {
+
+ OBJ_TYPE(DynamicFontAtSize,Reference);
+
+
+ int rect_margin;
+
+ struct CharTexture {
+
+ DVector<uint8_t> imgdata;
+ int texture_size;
+ Vector<int> offsets;
+ Ref<ImageTexture> texture;
+ };
+
+ Vector<CharTexture> textures;
+
+ struct Character {
+
+ int texture_idx;
+ Rect2 rect;
+ float v_align;
+ float h_align;
+ float advance;
+
+ Character() { texture_idx=0; v_align=0; }
+ };
+
+
+
+ HashMap< CharType, Character > char_map;
+
+ _FORCE_INLINE_ void _update_char(CharType p_char);
+
+friend class DynamicFontData;
+ Ref<DynamicFontData> font;
+ float scale;
+ int size;
+
+protected:
+
+public:
+
+ float get_height() const;
+
+ float get_ascent() const;
+ float get_descent() const;
+
+ Size2 get_char_size(CharType p_char,CharType p_next=0) const;
+
+ float draw_char(RID p_canvas_item, const Point2& p_pos, const CharType& p_char,const CharType& p_next=0,const Color& p_modulate=Color(1,1,1)) const;
+
+
+
+ DynamicFontAtSize();
+ ~DynamicFontAtSize();
+};
+
+///////////////
+
+class DynamicFont : public Font {
+
+ OBJ_TYPE( DynamicFont, Font );
+
+ Ref<DynamicFontData> data;
+ Ref<DynamicFontAtSize> data_at_size;
+ int size;
+
+
+protected:
+
+ static void _bind_methods();
+
+public:
+
+ void set_font_data(const Ref<DynamicFontData>& p_data);
+ Ref<DynamicFontData> get_font_data() const;
+
+ void set_size(int p_size);
+ int get_size() const;
+
+ virtual float get_height() const;
+
+ virtual float get_ascent() const;
+ virtual float get_descent() const;
+
+ virtual Size2 get_char_size(CharType p_char,CharType p_next=0) const;
+
+ virtual bool is_distance_field_hint() const;
+
+ virtual float draw_char(RID p_canvas_item, const Point2& p_pos, const CharType& p_char,const CharType& p_next=0,const Color& p_modulate=Color(1,1,1)) const;
+
+ DynamicFont();
+ ~DynamicFont();
+
+};
+
+
+
+/////////////
+
+class ResourceFormatLoaderDynamicFont : public ResourceFormatLoader {
+public:
+
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String& p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+
+};
+
+
+#endif
+#endif // DYNAMICFONT_H
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 09c0a21f53..e6356d3366 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -30,7 +30,6 @@
#include "scene/resources/concave_polygon_shape.h"
#include "scene/resources/convex_polygon_shape.h"
#include "surface_tool.h"
-
static const char*_array_name[]={
"vertex_array",
"normal_array",
@@ -288,6 +287,7 @@ void Mesh::add_surface(PrimitiveType p_primitive,const Array& p_arrays,const Arr
triangle_mesh=Ref<TriangleMesh>();
_change_notify();
+ emit_changed();
}
@@ -387,6 +387,7 @@ void Mesh::surface_remove(int p_idx) {
triangle_mesh=Ref<TriangleMesh>();
_recompute_aabb();
_change_notify();
+ emit_changed();
}
@@ -491,6 +492,8 @@ void Mesh::add_surface_from_mesh_data(const Geometry::MeshData& p_mesh_data) {
surfaces.push_back(s);
_change_notify();
+
+ emit_changed();
}
RID Mesh::get_rid() const {
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index 7e8dd41ed9..164ae55c9f 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -176,4 +176,11 @@ SceneStringNames::SceneStringNames() {
path_pp=NodePath("..");
_default=StaticCString::create("default");
+
+ for(int i=0;i<MAX_MATERIALS;i++) {
+
+ mesh_materials[i]="material/"+itos(i);
+ }
+
+ _mesh_changed=StaticCString::create("_mesh_changed");
}
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 7143bd539f..32e51ce8f4 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -186,6 +186,12 @@ public:
StringName node_configuration_warning_changed;
+ enum {
+ MAX_MATERIALS=32
+ };
+ StringName mesh_materials[MAX_MATERIALS];
+ StringName _mesh_changed;
+
};