Merge pull request #30291 from akien-mga/3.0

Assorted cherry-picks from the master branch for Godot 3.0.7
This commit is contained in:
Rémi Verschelde 2019-07-09 08:46:19 +02:00 committed by GitHub
commit b896eb5fd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
148 changed files with 1290 additions and 983 deletions

View File

@ -2302,7 +2302,7 @@ void _Thread::_start_func(void *ud) {
} break; } break;
case Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: { case Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: {
reason = "Too Many Arguments"; reason = "Too Few Arguments";
} break; } break;
case Variant::CallError::CALL_ERROR_INVALID_METHOD: { case Variant::CallError::CALL_ERROR_INVALID_METHOD: {

View File

@ -1505,7 +1505,7 @@ Error Image::decompress() {
_image_decompress_pvrtc(this); _image_decompress_pvrtc(this);
else if (format == FORMAT_ETC && _image_decompress_etc1) else if (format == FORMAT_ETC && _image_decompress_etc1)
_image_decompress_etc1(this); _image_decompress_etc1(this);
else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RGB8A1 && _image_decompress_etc1) else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RGB8A1 && _image_decompress_etc2)
_image_decompress_etc2(this); _image_decompress_etc2(this);
else else
return ERR_UNAVAILABLE; return ERR_UNAVAILABLE;
@ -1636,7 +1636,8 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
return; return;
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size)); Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
PoolVector<uint8_t>::Write wp = data.write(); PoolVector<uint8_t>::Write wp = data.write();
uint8_t *dst_data_ptr = wp.ptr(); uint8_t *dst_data_ptr = wp.ptr();
@ -1684,7 +1685,8 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
return; return;
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size)); Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
PoolVector<uint8_t>::Write wp = data.write(); PoolVector<uint8_t>::Write wp = data.write();
uint8_t *dst_data_ptr = wp.ptr(); uint8_t *dst_data_ptr = wp.ptr();
@ -1735,7 +1737,8 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
return; return;
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size)); Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
lock(); lock();
Ref<Image> img = p_src; Ref<Image> img = p_src;
@ -1783,7 +1786,8 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
return; return;
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size)); Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
lock(); lock();
Ref<Image> img = p_src; Ref<Image> img = p_src;
@ -2299,6 +2303,9 @@ void Image::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data"); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data");
BIND_CONSTANT(MAX_WIDTH);
BIND_CONSTANT(MAX_HEIGHT);
BIND_ENUM_CONSTANT(FORMAT_L8); //luminance BIND_ENUM_CONSTANT(FORMAT_L8); //luminance
BIND_ENUM_CONSTANT(FORMAT_LA8); //luminance-alpha BIND_ENUM_CONSTANT(FORMAT_LA8); //luminance-alpha
BIND_ENUM_CONSTANT(FORMAT_R8); BIND_ENUM_CONSTANT(FORMAT_R8);

View File

@ -51,14 +51,14 @@ typedef Error (*SavePNGFunc)(const String &p_path, const Ref<Image> &p_img);
class Image : public Resource { class Image : public Resource {
GDCLASS(Image, Resource); GDCLASS(Image, Resource);
public:
static SavePNGFunc save_png_func;
enum { enum {
MAX_WIDTH = 16384, // force a limit somehow MAX_WIDTH = 16384, // force a limit somehow
MAX_HEIGHT = 16384 // force a limit somehow MAX_HEIGHT = 16384 // force a limit somehow
}; };
public:
static SavePNGFunc save_png_func;
enum Format { enum Format {
FORMAT_L8, //luminance FORMAT_L8, //luminance

View File

@ -291,7 +291,6 @@ uint8_t FileAccessCompressed::get_8() const {
} else { } else {
read_block--; read_block--;
at_end = true; at_end = true;
ret = 0;
} }
} }

View File

@ -117,7 +117,7 @@ IP_Address IP::resolve_hostname(const String &p_hostname, IP::Type p_type) {
resolver->mutex->lock(); resolver->mutex->lock();
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type); String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
if (resolver->cache.has(key)) { if (resolver->cache.has(key) && resolver->cache[key].is_valid()) {
IP_Address res = resolver->cache[key]; IP_Address res = resolver->cache[key];
resolver->mutex->unlock(); resolver->mutex->unlock();
return res; return res;
@ -144,7 +144,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type); String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
resolver->queue[id].hostname = p_hostname; resolver->queue[id].hostname = p_hostname;
resolver->queue[id].type = p_type; resolver->queue[id].type = p_type;
if (resolver->cache.has(key)) { if (resolver->cache.has(key) && resolver->cache[key].is_valid()) {
resolver->queue[id].response = resolver->cache[key]; resolver->queue[id].response = resolver->cache[key];
resolver->queue[id].status = IP::RESOLVER_STATUS_DONE; resolver->queue[id].status = IP::RESOLVER_STATUS_DONE;
} else { } else {

View File

@ -43,8 +43,7 @@ Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
return ERR_CANT_RESOLVE; return ERR_CANT_RESOLVE;
} }
connect_to_host(ip, p_port); return connect_to_host(ip, p_port);
return OK;
} }
void StreamPeerTCP::_bind_methods() { void StreamPeerTCP::_bind_methods() {

View File

@ -54,32 +54,25 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
int line = 1; int line = 1;
bool skip_this = false; bool skip_this = false;
bool skip_next = false; bool skip_next = false;
bool is_eof = false;
while (true) { while (!is_eof) {
String l = f->get_line(); String l = f->get_line().strip_edges();
is_eof = f->eof_reached();
if (f->eof_reached()) { // If we reached last line and it's not a content line, break, otherwise let processing that last loop
if (is_eof && l.empty()) {
if (status == STATUS_READING_STRING) { if (status == STATUS_READING_ID) {
memdelete(f);
if (msg_id != "") { ERR_EXPLAIN(p_path + ":" + itos(line) + " Unexpected EOF while reading 'msgid' at file: ");
if (!skip_this) ERR_FAIL_V(RES());
translation->add_message(msg_id, msg_str); } else {
} else if (config == "")
config = msg_str;
break; break;
}
} else if (status == STATUS_NONE)
break;
memdelete(f);
ERR_EXPLAIN(p_path + ":" + itos(line) + " Unexpected EOF while reading 'msgid' at file: ");
ERR_FAIL_V(RES());
} }
l = l.strip_edges();
if (l.begins_with("msgid")) { if (l.begins_with("msgid")) {
if (status == STATUS_READING_ID) { if (status == STATUS_READING_ID) {
@ -160,6 +153,15 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
f->close(); f->close();
memdelete(f); memdelete(f);
if (status == STATUS_READING_STRING) {
if (msg_id != "") {
if (!skip_this)
translation->add_message(msg_id, msg_str);
} else if (config == "")
config = msg_str;
}
if (config == "") { if (config == "") {
ERR_EXPLAIN("No config found in file: " + p_path); ERR_EXPLAIN("No config found in file: " + p_path);
ERR_FAIL_V(RES()); ERR_FAIL_V(RES());
@ -175,7 +177,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
String prop = c.substr(0, p).strip_edges(); String prop = c.substr(0, p).strip_edges();
String value = c.substr(p + 1, c.length()).strip_edges(); String value = c.substr(p + 1, c.length()).strip_edges();
if (prop == "X-Language") { if (prop == "X-Language" || prop == "Language") {
translation->set_locale(value); translation->set_locale(value);
} }
} }

View File

@ -397,7 +397,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
Map<Edge, RetFaceConnect>::Element *F = ret_edges.find(e); Map<Edge, RetFaceConnect>::Element *F = ret_edges.find(e);
ERR_CONTINUE(!F); ERR_CONTINUE(!F);
List<Geometry::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left; List<Geometry::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left;
ERR_CONTINUE(O == E); ERR_CONTINUE(O == E);
ERR_CONTINUE(O == NULL); ERR_CONTINUE(O == NULL);
@ -426,7 +425,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
Edge e2(idx, idxn); Edge e2(idx, idxn);
Map<Edge, RetFaceConnect>::Element *F2 = ret_edges.find(e2); Map<Edge, RetFaceConnect>::Element *F2 = ret_edges.find(e2);
ERR_CONTINUE(!F2); ERR_CONTINUE(!F2);
//change faceconnect, point to this face instead //change faceconnect, point to this face instead
if (F2->get().left == O) if (F2->get().left == O)
@ -439,6 +437,15 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
} }
} }
// remove all edge connections to this face
for (Map<Edge, RetFaceConnect>::Element *E = ret_edges.front(); E; E = E->next()) {
if (E->get().left == O)
E->get().left = NULL;
if (E->get().right == O)
E->get().right = NULL;
}
ret_edges.erase(F); //remove the edge ret_edges.erase(F); //remove the edge
ret_faces.erase(O); //remove the face ret_faces.erase(O); //remove the face
} }

View File

@ -1330,7 +1330,10 @@ Array Object::_get_incoming_connections() const {
void Object::get_signal_list(List<MethodInfo> *p_signals) const { void Object::get_signal_list(List<MethodInfo> *p_signals) const {
if (!script.is_null()) { if (!script.is_null()) {
Ref<Script>(script)->get_script_signal_list(p_signals); Ref<Script> scr = script;
if (scr.is_valid()) {
scr->get_script_signal_list(p_signals);
}
} }
ClassDB::get_signal_list(get_class_name(), p_signals); ClassDB::get_signal_list(get_class_name(), p_signals);

View File

@ -613,6 +613,9 @@ bool OS::has_feature(const String &p_feature) {
if (_check_internal_feature_support(p_feature)) if (_check_internal_feature_support(p_feature))
return true; return true;
if (ProjectSettings::get_singleton()->has_custom_feature(p_feature))
return true;
return false; return false;
} }

View File

@ -359,7 +359,7 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) {
//p_new_size = align(p_new_size) //p_new_size = align(p_new_size)
int _free = free_mem; // - static_area_size; int _free = free_mem; // - static_area_size;
if ((_free + aligned(e->len)) - alloc_size < 0) { if (uint32_t(_free + aligned(e->len)) < alloc_size) {
mt_unlock(); mt_unlock();
ERR_FAIL_V(ERR_OUT_OF_MEMORY); ERR_FAIL_V(ERR_OUT_OF_MEMORY);
}; };

View File

@ -137,7 +137,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
else { else {
if (p_name == CoreStringNames::get_singleton()->_custom_features) { if (p_name == CoreStringNames::get_singleton()->_custom_features) {
Vector<String> custom_feature_array = p_value; Vector<String> custom_feature_array = String(p_value).split(",");
for (int i = 0; i < custom_feature_array.size(); i++) { for (int i = 0; i < custom_feature_array.size(); i++) {
custom_features.insert(custom_feature_array[i]); custom_features.insert(custom_feature_array[i]);
@ -886,6 +886,10 @@ Variant ProjectSettings::get_setting(const String &p_setting) const {
return get(p_setting); return get(p_setting);
} }
bool ProjectSettings::has_custom_feature(const String &p_feature) const {
return custom_features.has(p_feature);
}
void ProjectSettings::_bind_methods() { void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting); ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting);

View File

@ -148,6 +148,8 @@ public:
void set_registering_order(bool p_enable); void set_registering_order(bool p_enable);
bool has_custom_feature(const String &p_feature) const;
ProjectSettings(); ProjectSettings();
~ProjectSettings(); ~ProjectSettings();
}; };

View File

@ -93,6 +93,7 @@ T *_nullptr() {
#undef CLAMP // override standard definition #undef CLAMP // override standard definition
#undef Error #undef Error
#undef OK #undef OK
#undef CONNECT_DEFERRED // override from Windows SDK, clashes with Object enum
#endif #endif
#include "int_types.h" #include "int_types.h"

View File

@ -885,8 +885,8 @@ String String::to_upper() const {
for (int i = 0; i < upper.size(); i++) { for (int i = 0; i < upper.size(); i++) {
const char s = upper[i]; const CharType s = upper[i];
const char t = _find_upper(s); const CharType t = _find_upper(s);
if (s != t) // avoid copy on write if (s != t) // avoid copy on write
upper[i] = t; upper[i] = t;
} }
@ -900,8 +900,8 @@ String String::to_lower() const {
for (int i = 0; i < lower.size(); i++) { for (int i = 0; i < lower.size(); i++) {
const char s = lower[i]; const CharType s = lower[i];
const char t = _find_lower(s); const CharType t = _find_lower(s);
if (s != t) // avoid copy on write if (s != t) // avoid copy on write
lower[i] = t; lower[i] = t;
} }
@ -3011,7 +3011,7 @@ String String::simplify_path() const {
} else if (s.begins_with("user://")) { } else if (s.begins_with("user://")) {
drive = "user://"; drive = "user://";
s = s.substr(6, s.length()); s = s.substr(7, s.length());
} else if (s.begins_with("/") || s.begins_with("\\")) { } else if (s.begins_with("/") || s.begins_with("\\")) {
drive = s.substr(0, 1); drive = s.substr(0, 1);
@ -3929,7 +3929,7 @@ String String::sprintf(const Array &values, bool *error) const {
str = str.pad_decimals(min_decimals); str = str.pad_decimals(min_decimals);
// Show sign // Show sign
if (show_sign && value >= 0) { if (show_sign && str.left(1) != "-") {
str = str.insert(0, "+"); str = str.insert(0, "+");
} }

View File

@ -2149,7 +2149,7 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
int idx = p_index; int idx = p_index;
if (idx < 0) if (idx < 0)
idx += 4; idx += 4;
if (idx >= 0 || idx < 4) { if (idx >= 0 && idx < 4) {
Color *v = reinterpret_cast<Color *>(_data._mem); Color *v = reinterpret_cast<Color *>(_data._mem);
(*v)[idx] = p_value; (*v)[idx] = p_value;
valid = true; valid = true;
@ -2524,7 +2524,7 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
int idx = p_index; int idx = p_index;
if (idx < 0) if (idx < 0)
idx += 4; idx += 4;
if (idx >= 0 || idx < 4) { if (idx >= 0 && idx < 4) {
const Color *v = reinterpret_cast<const Color *>(_data._mem); const Color *v = reinterpret_cast<const Color *>(_data._mem);
valid = true; valid = true;
return (*v)[idx]; return (*v)[idx];

View File

@ -228,31 +228,31 @@
Amount of weights/bone indices per vertex (always 4). Amount of weights/bone indices per vertex (always 4).
</constant> </constant>
<constant name="ARRAY_VERTEX" value="0" enum="ArrayType"> <constant name="ARRAY_VERTEX" value="0" enum="ArrayType">
Vertex array (array of [Vector3] vertices). [PoolVector3Array], [PoolVector2Array], or [Array] of vertex positions.
</constant> </constant>
<constant name="ARRAY_NORMAL" value="1" enum="ArrayType"> <constant name="ARRAY_NORMAL" value="1" enum="ArrayType">
Normal array (array of [Vector3] normals). [PoolVector3Array] of vertex normals.
</constant> </constant>
<constant name="ARRAY_TANGENT" value="2" enum="ArrayType"> <constant name="ARRAY_TANGENT" value="2" enum="ArrayType">
Tangent array, array of groups of 4 floats. first 3 floats determine the tangent, and the last the binormal direction as -1 or 1. [PoolRealArray] of vertex tangents. Each element in groups of 4 floats, first 3 floats determine the tangent, and the last the binormal direction as -1 or 1.
</constant> </constant>
<constant name="ARRAY_COLOR" value="3" enum="ArrayType"> <constant name="ARRAY_COLOR" value="3" enum="ArrayType">
Vertex array (array of [Color] colors). [PoolColorArray] of vertex colors.
</constant> </constant>
<constant name="ARRAY_TEX_UV" value="4" enum="ArrayType"> <constant name="ARRAY_TEX_UV" value="4" enum="ArrayType">
UV array (array of [Vector3] UVs or float array of groups of 2 floats (u,v)). [PoolVector2Array] for UV coordinates.
</constant> </constant>
<constant name="ARRAY_TEX_UV2" value="5" enum="ArrayType"> <constant name="ARRAY_TEX_UV2" value="5" enum="ArrayType">
Second UV array (array of [Vector3] UVs or float array of groups of 2 floats (u,v)). [PoolVector2Array] for second UV coordinates.
</constant> </constant>
<constant name="ARRAY_BONES" value="6" enum="ArrayType"> <constant name="ARRAY_BONES" value="6" enum="ArrayType">
Array of bone indices, as a float array. Each element in groups of 4 floats. [PoolRealArray] or [PoolIntArray] of bone indices. Each element in groups of 4 floats.
</constant> </constant>
<constant name="ARRAY_WEIGHTS" value="7" enum="ArrayType"> <constant name="ARRAY_WEIGHTS" value="7" enum="ArrayType">
Array of bone weights, as a float array. Each element in groups of 4 floats. [PoolRealArray] of bone weights. Each element in groups of 4 floats.
</constant> </constant>
<constant name="ARRAY_INDEX" value="8" enum="ArrayType"> <constant name="ARRAY_INDEX" value="8" enum="ArrayType">
[Array] of integers used as indices referencing vertices, colors, normals, tangents, and textures. All of those arrays must have the same number of elements as the vertex array. No index can be beyond the vertex array size. When this index array is present, it puts the function into "index mode," where the index selects the *i*'th vertex, normal, tangent, color, UV, etc. This means if you want to have different normals or colors along an edge, you have to duplicate the vertices. [PoolIntArray] of integers used as indices referencing vertices, colors, normals, tangents, and textures. All of those arrays must have the same number of elements as the vertex array. No index can be beyond the vertex array size. When this index array is present, it puts the function into "index mode," where the index selects the *i*'th vertex, normal, tangent, color, UV, etc. This means if you want to have different normals or colors along an edge, you have to duplicate the vertices.
For triangles, the index array is interpreted as triples, referring to the vertices of each triangle. For lines, the index array is in pairs indicating the start and end of each line. For triangles, the index array is interpreted as triples, referring to the vertices of each triangle. For lines, the index array is in pairs indicating the start and end of each line.
</constant> </constant>
<constant name="ARRAY_MAX" value="9" enum="ArrayType"> <constant name="ARRAY_MAX" value="9" enum="ArrayType">

View File

@ -156,7 +156,7 @@
Perspective Projection (object's size on the screen becomes smaller when far away). Perspective Projection (object's size on the screen becomes smaller when far away).
</constant> </constant>
<constant name="PROJECTION_ORTHOGONAL" value="1" enum="Projection"> <constant name="PROJECTION_ORTHOGONAL" value="1" enum="Projection">
Orthogonal Projection (objects remain the same size on the screen no matter how far away they are). Orthogonal Projection (objects remain the same size on the screen no matter how far away they are; also known as orthographic projection).
</constant> </constant>
<constant name="KEEP_WIDTH" value="0" enum="KeepAspect"> <constant name="KEEP_WIDTH" value="0" enum="KeepAspect">
Preserves the horizontal aspect ratio. Preserves the horizontal aspect ratio.

View File

@ -199,7 +199,7 @@
</methods> </methods>
<members> <members>
<member name="input_pickable" type="bool" setter="set_pickable" getter="is_pickable"> <member name="input_pickable" type="bool" setter="set_pickable" getter="is_pickable">
If [code]true[/code] this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. If [code]true[/code], this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. Requires at least one [code]collision_layer[/code] bit to be set.
</member> </member>
</members> </members>
<signals> <signals>
@ -211,17 +211,17 @@
<argument index="2" name="shape_idx" type="int"> <argument index="2" name="shape_idx" type="int">
</argument> </argument>
<description> <description>
Emitted when an input event occurs and [code]input_pickable[/code] is [code]true[/code]. See [method _input_event] for details. Emitted when an input event occurs. Requires [code]input_pickable[/code] to be [code]true[/code] and at least one [code]collision_layer[/code] bit to be set. See [method _input_event] for details.
</description> </description>
</signal> </signal>
<signal name="mouse_entered"> <signal name="mouse_entered">
<description> <description>
Emitted when the mouse pointer enters any of this object's shapes. Emitted when the mouse pointer enters any of this object's shapes. Requires [code]input_pickable[/code] to be [code]true[/code] and at least one [code]collision_layer[/code] bit to be set.
</description> </description>
</signal> </signal>
<signal name="mouse_exited"> <signal name="mouse_exited">
<description> <description>
Emitted when the mouse pointer exits all this object's shapes. Emitted when the mouse pointer exits all this object's shapes. Requires [code]input_pickable[/code] to be [code]true[/code] and at least one [code]collision_layer[/code] bit to be set.
</description> </description>
</signal> </signal>
</signals> </signals>

View File

@ -18,7 +18,7 @@
<argument index="0" name="point_cloud" type="PoolVector2Array"> <argument index="0" name="point_cloud" type="PoolVector2Array">
</argument> </argument>
<description> <description>
Currently, this method does nothing. Based on the set of points provided, this creates and assigns the [member points] property using the convex hull algorithm. Removing all unneeded points. See [method Geometry.convex_hull_2d] for details.
</description> </description>
</method> </method>
</methods> </methods>

View File

@ -4,7 +4,7 @@
Image datatype. Image datatype.
</brief_description> </brief_description>
<description> <description>
Native image datatype. Contains image data, which can be converted to a [Texture], and several functions to interact with it. The maximum width and height for an [code]Image[/code] is 16384 pixels. Native image datatype. Contains image data, which can be converted to a [Texture], and several functions to interact with it. The maximum width and height for an [code]Image[/code] are [constant MAX_WIDTH] and [constant MAX_HEIGHT].
</description> </description>
<tutorials> <tutorials>
</tutorials> </tutorials>
@ -431,6 +431,12 @@
</member> </member>
</members> </members>
<constants> <constants>
<constant name="MAX_WIDTH" value="16384">
The maximal width allowed for [code]Image[/code] resources.
</constant>
<constant name="MAX_HEIGHT" value="16384">
The maximal height allowed for [code]Image[/code] resources.
</constant>
<constant name="FORMAT_L8" value="0" enum="Format"> <constant name="FORMAT_L8" value="0" enum="Format">
</constant> </constant>
<constant name="FORMAT_LA8" value="1" enum="Format"> <constant name="FORMAT_LA8" value="1" enum="Format">

View File

@ -5,6 +5,7 @@
</brief_description> </brief_description>
<description> <description>
Can have [PathFollow2D] child-nodes moving along the [Curve2D]. See [PathFollow2D] for more information on this usage. Can have [PathFollow2D] child-nodes moving along the [Curve2D]. See [PathFollow2D] for more information on this usage.
Note that the path is considered as relative to the moved nodes (children of [PathFollow2D]) - usually the curve should start with a zero vector (0, 0).
</description> </description>
<tutorials> <tutorials>
</tutorials> </tutorials>

View File

@ -7,7 +7,8 @@
This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties. This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties.
A RigidBody2D has 4 behavior [member mode]s: Rigid, Static, Character, and Kinematic. A RigidBody2D has 4 behavior [member mode]s: Rigid, Static, Character, and Kinematic.
[b]Note:[/b] You should not change a RigidBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. [b]Note:[/b] You should not change a RigidBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state.
If you need to override the default physics behavior, you can write a custom force integration. See [member custom_integrator]. Please also keep in mind that physics bodies manage their own transform which overwrites the ones you set. So any direct or indirect transformation (including scaling of the node or its parent) will be visible in the editor only, and immediately reset at runtime.
If you need to override the default physics behavior or add a transformation at runtime, you can write a custom force integration. See [member custom_integrator].
</description> </description>
<tutorials> <tutorials>
</tutorials> </tutorials>

View File

@ -4,7 +4,7 @@
Vertical split container. Vertical split container.
</brief_description> </brief_description>
<description> <description>
Vertical split container. See [SplitContainer]. This goes from left to right. Vertical split container. See [SplitContainer]. This goes from top to bottom.
</description> </description>
<tutorials> <tutorials>
</tutorials> </tutorials>

View File

@ -191,7 +191,7 @@
<argument index="0" name="phi" type="float"> <argument index="0" name="phi" type="float">
</argument> </argument>
<description> <description>
Returns the vector rotated by [code]phi[/code] radians. Returns the vector rotated by [code]phi[/code] radians. See also [method @GDScript.deg2rad].
</description> </description>
</method> </method>
<method name="round"> <method name="round">

View File

@ -15,7 +15,8 @@
<return type="bool"> <return type="bool">
</return> </return>
<description> <description>
If [code]true[/code] the bounding box is on the screen. If [code]true[/code], the bounding box is on the screen.
Note: It takes one frame for the node's visibility to be assessed once added to the scene tree, so this method will return [code]false[/code] right after it is instantiated, even if it will be on screen in the draw pass.
</description> </description>
</method> </method>
</methods> </methods>

View File

@ -15,7 +15,8 @@
<return type="bool"> <return type="bool">
</return> </return>
<description> <description>
If [code]true[/code] the bounding rectangle is on the screen. If [code]true[/code], the bounding rectangle is on the screen.
Note: It takes one frame for the node's visibility to be assessed once added to the scene tree, so this method will return [code]false[/code] right after it is instantiated, even if it will be on screen in the draw pass.
</description> </description>
</method> </method>
</methods> </methods>

View File

@ -262,7 +262,7 @@ def rstize_text(text, cclass):
escape_post = True escape_post = True
# Properly escape things like `[Node]s` # Properly escape things like `[Node]s`
if escape_post and post_text and post_text[0].isalnum(): # not punctuation, escape if escape_post and post_text and (post_text[0].isalnum() or post_text[0] == "("): # not punctuation, escape
post_text = '\ ' + post_text post_text = '\ ' + post_text
next_brac_pos = post_text.find('[',0) next_brac_pos = post_text.find('[',0)

View File

@ -58,7 +58,10 @@ Error AudioDriverALSA::init_device() {
#define CHECK_FAIL(m_cond) \ #define CHECK_FAIL(m_cond) \
if (m_cond) { \ if (m_cond) { \
fprintf(stderr, "ALSA ERR: %s\n", snd_strerror(status)); \ fprintf(stderr, "ALSA ERR: %s\n", snd_strerror(status)); \
snd_pcm_close(pcm_handle); \ if (pcm_handle) { \
snd_pcm_close(pcm_handle); \
pcm_handle = NULL; \
} \
ERR_FAIL_COND_V(m_cond, ERR_CANT_OPEN); \ ERR_FAIL_COND_V(m_cond, ERR_CANT_OPEN); \
} }
@ -152,7 +155,6 @@ Error AudioDriverALSA::init() {
active = false; active = false;
thread_exited = false; thread_exited = false;
exit_thread = false; exit_thread = false;
pcm_open = false;
Error err = init_device(); Error err = init_device();
if (err == OK) { if (err == OK) {
@ -315,9 +317,9 @@ void AudioDriverALSA::unlock() {
void AudioDriverALSA::finish_device() { void AudioDriverALSA::finish_device() {
if (pcm_open) { if (pcm_handle) {
snd_pcm_close(pcm_handle); snd_pcm_close(pcm_handle);
pcm_open = NULL; pcm_handle = NULL;
} }
} }

View File

@ -66,7 +66,6 @@ class AudioDriverALSA : public AudioDriver {
bool active; bool active;
bool thread_exited; bool thread_exited;
mutable bool exit_thread; mutable bool exit_thread;
bool pcm_open;
public: public:
const char *get_name() const { const char *get_name() const {

View File

@ -191,11 +191,11 @@ void RasterizerCanvasGLES3::canvas_end() {
state.using_ninepatch = false; state.using_ninepatch = false;
} }
RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) { RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force) {
RasterizerStorageGLES3::Texture *tex_return = NULL; RasterizerStorageGLES3::Texture *tex_return = NULL;
if (p_texture == state.current_tex) { if (p_texture == state.current_tex && !p_force) {
tex_return = state.current_tex_ptr; tex_return = state.current_tex_ptr;
} else if (p_texture.is_valid()) { } else if (p_texture.is_valid()) {
@ -230,7 +230,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con
state.current_tex_ptr = NULL; state.current_tex_ptr = NULL;
} }
if (p_normal_map == state.current_normal) { if (p_normal_map == state.current_normal && !p_force) {
//do none //do none
state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, state.current_normal.is_valid()); state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, state.current_normal.is_valid());
@ -997,7 +997,7 @@ void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) {
state.using_texture_rect = true; state.using_texture_rect = true;
_set_texture_rect_mode(false); _set_texture_rect_mode(false);
_bind_canvas_texture(state.current_tex, state.current_normal); _bind_canvas_texture(state.current_tex, state.current_normal, true);
glEnable(GL_BLEND); glEnable(GL_BLEND);
} }
@ -1161,7 +1161,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
} }
int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX; int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX;
bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode == RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX); bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode == RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || (blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX && blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA));
bool reclip = false; bool reclip = false;
if (last_blend_mode != blend_mode) { if (last_blend_mode != blend_mode) {

View File

@ -120,7 +120,7 @@ public:
virtual void canvas_end(); virtual void canvas_end();
_FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false); _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false);
_FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map); _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force = false);
_FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs);
_FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);

View File

@ -1384,7 +1384,16 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->particle_valid_histories[1]) { if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->particle_valid_histories[1]) {
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer, this was used 2 frames ago so it should be good enough for flushing glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer, this was used 2 frames ago so it should be good enough for flushing
RasterizerGLES3Particle *particle_array = (RasterizerGLES3Particle *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); RasterizerGLES3Particle *particle_array;
#ifndef __EMSCRIPTEN__
particle_array = static_cast<RasterizerGLES3Particle *>(glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
#else
PoolVector<RasterizerGLES3Particle> particle_vector;
particle_vector.resize(particles->amount);
PoolVector<RasterizerGLES3Particle>::Write w = particle_vector.write();
particle_array = w.ptr();
glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), particle_array);
#endif
SortArray<RasterizerGLES3Particle, RasterizerGLES3ParticleSort> sorter; SortArray<RasterizerGLES3Particle, RasterizerGLES3ParticleSort> sorter;
@ -1396,7 +1405,17 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
sorter.sort(particle_array, particles->amount); sorter.sort(particle_array, particles->amount);
#ifndef __EMSCRIPTEN__
glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_ARRAY_BUFFER);
#else
w = PoolVector<RasterizerGLES3Particle>::Write();
particle_array = NULL;
{
PoolVector<RasterizerGLES3Particle>::Read r = particle_vector.read();
glBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), r.ptr());
}
particle_vector = PoolVector<RasterizerGLES3Particle>();
#endif
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) { if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) {
glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID
@ -2674,7 +2693,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform
CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview; CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview;
store_camera(shadow_mtx, &ubo_data.shadow_matrix1[16 * j]); store_camera(shadow_mtx, &ubo_data.shadow.matrix[16 * j]);
ubo_data.light_clamp[0] = atlas_rect.position.x; ubo_data.light_clamp[0] = atlas_rect.position.x;
ubo_data.light_clamp[1] = atlas_rect.position.y; ubo_data.light_clamp[1] = atlas_rect.position.y;
@ -2785,7 +2804,7 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c
Transform proj = (p_camera_inverse_transform * li->transform).inverse(); Transform proj = (p_camera_inverse_transform * li->transform).inverse();
store_transform(proj, ubo_data.shadow_matrix1); store_transform(proj, ubo_data.shadow.matrix1);
ubo_data.light_params[3] = 1.0; //means it has shadow ubo_data.light_params[3] = 1.0; //means it has shadow
ubo_data.light_clamp[0] = float(x) / atlas_size; ubo_data.light_clamp[0] = float(x) / atlas_size;
@ -2874,7 +2893,7 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c
CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview; CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview;
store_camera(shadow_mtx, ubo_data.shadow_matrix1); store_camera(shadow_mtx, ubo_data.shadow.matrix1);
} }
li->light_index = state.spot_light_count; li->light_index = state.spot_light_count;
@ -3554,7 +3573,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
} }
if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] || storage->frame.current_rt->width < 4 || storage->frame.current_rt->height < 4) { //no post process on small render targets
//no environment or transparent render, simply return and convert to SRGB //no environment or transparent render, simply return and convert to SRGB
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);

View File

@ -568,10 +568,15 @@ public:
float light_params[4]; //spot attenuation, spot angle, specular, shadow enabled float light_params[4]; //spot attenuation, spot angle, specular, shadow enabled
float light_clamp[4]; float light_clamp[4];
float light_shadow_color_contact[4]; float light_shadow_color_contact[4];
float shadow_matrix1[16]; //up to here for spot and omni, rest is for directional union {
float shadow_matrix2[16]; struct {
float shadow_matrix3[16]; float matrix1[16]; //up to here for spot and omni, rest is for directional
float shadow_matrix4[16]; float matrix2[16];
float matrix3[16];
float matrix4[16];
};
float matrix[4 * 16];
} shadow;
float shadow_split_offsets[4]; float shadow_split_offsets[4];
}; };

View File

@ -100,6 +100,19 @@
#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E #define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F #define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data) {
/* clang-format off */
EM_ASM({
GLctx.getBufferSubData($0, $1, HEAPU8, $2, $3);
}, target, offset, data, size);
/* clang-format on */
}
#endif
void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) { void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) {
#ifdef GLES_OVER_GL #ifdef GLES_OVER_GL
@ -909,7 +922,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, VS::CubeMapSi
#else #else
ERR_EXPLAIN("Sorry, It's not possible to obtain images back in OpenGL ES"); ERR_EXPLAIN("Sorry, It's not possible to obtain images back in OpenGL ES");
return Ref<Image>(); ERR_FAIL_V(Ref<Image>());
#endif #endif
} }
@ -3241,21 +3254,26 @@ PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, i
Surface *surface = mesh->surfaces[p_surface]; Surface *surface = mesh->surfaces[p_surface];
glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, surface->array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data, PoolVector<uint8_t>());
PoolVector<uint8_t> ret; PoolVector<uint8_t> ret;
ret.resize(surface->array_byte_size); ret.resize(surface->array_byte_size);
glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
{
PoolVector<uint8_t>::Write w = ret.write();
glGetBufferSubData(GL_ARRAY_BUFFER, 0, surface->array_byte_size, w.ptr());
}
#else
void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, surface->array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_NULL_V(data, PoolVector<uint8_t>());
{ {
PoolVector<uint8_t>::Write w = ret.write(); PoolVector<uint8_t>::Write w = ret.write();
copymem(w.ptr(), data, surface->array_byte_size); copymem(w.ptr(), data, surface->array_byte_size);
} }
glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_ARRAY_BUFFER);
#endif
glBindBuffer(GL_ARRAY_BUFFER, 0);
return ret; return ret;
} }
@ -3268,22 +3286,26 @@ PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_m
ERR_FAIL_COND_V(surface->index_array_len == 0, PoolVector<uint8_t>()); ERR_FAIL_COND_V(surface->index_array_len == 0, PoolVector<uint8_t>());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id);
void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data, PoolVector<uint8_t>());
PoolVector<uint8_t> ret; PoolVector<uint8_t> ret;
ret.resize(surface->index_array_byte_size); ret.resize(surface->index_array_byte_size);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id);
#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
{
PoolVector<uint8_t>::Write w = ret.write();
glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, w.ptr());
}
#else
void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_NULL_V(data, PoolVector<uint8_t>());
{ {
PoolVector<uint8_t>::Write w = ret.write(); PoolVector<uint8_t>::Write w = ret.write();
copymem(w.ptr(), data, surface->index_array_byte_size); copymem(w.ptr(), data, surface->index_array_byte_size);
} }
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
#endif
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return ret; return ret;
} }
@ -3324,23 +3346,26 @@ Vector<PoolVector<uint8_t> > RasterizerStorageGLES3::mesh_surface_get_blend_shap
for (int i = 0; i < mesh->surfaces[p_surface]->blend_shapes.size(); i++) { for (int i = 0; i < mesh->surfaces[p_surface]->blend_shapes.size(); i++) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->surfaces[p_surface]->blend_shapes[i].vertex_id);
void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data, Vector<PoolVector<uint8_t> >());
PoolVector<uint8_t> ret; PoolVector<uint8_t> ret;
ret.resize(mesh->surfaces[p_surface]->array_byte_size); ret.resize(mesh->surfaces[p_surface]->array_byte_size);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->surfaces[p_surface]->blend_shapes[i].vertex_id);
#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
{
PoolVector<uint8_t>::Write w = ret.write();
glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, w.ptr());
}
#else
void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data, Vector<PoolVector<uint8_t> >());
{ {
PoolVector<uint8_t>::Write w = ret.write(); PoolVector<uint8_t>::Write w = ret.write();
copymem(w.ptr(), data, mesh->surfaces[p_surface]->array_byte_size); copymem(w.ptr(), data, mesh->surfaces[p_surface]->array_byte_size);
} }
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
#endif
bsarr.push_back(ret); bsarr.push_back(ret);
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
} }
return bsarr; return bsarr;
@ -3799,7 +3824,8 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
int format_floats = multimesh->color_floats + multimesh->xform_floats; int format_floats = multimesh->color_floats + multimesh->xform_floats;
multimesh->data.resize(format_floats * p_instances); multimesh->data.resize(format_floats * p_instances);
for (int i = 0; i < p_instances; i += format_floats) {
for (int i = 0; i < p_instances * format_floats; i += format_floats) {
int color_from = 0; int color_from = 0;
@ -5607,9 +5633,21 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
const Particles *particles = particles_owner.getornull(p_particles); const Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND_V(!particles, AABB()); ERR_FAIL_COND_V(!particles, AABB());
const float *data;
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]);
float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT); #if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
PoolVector<uint8_t> vector;
vector.resize(particles->amount * 16 * 6);
{
PoolVector<uint8_t>::Write w = vector.write();
glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, w.ptr());
}
PoolVector<uint8_t>::Read r = vector.read();
data = reinterpret_cast<const float *>(r.ptr());
#else
data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT);
#endif
AABB aabb; AABB aabb;
Transform inv = particles->emission_transform.affine_inverse(); Transform inv = particles->emission_transform.affine_inverse();
@ -5626,7 +5664,13 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
aabb.expand_to(pos); aabb.expand_to(pos);
} }
#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
r = PoolVector<uint8_t>::Read();
vector = PoolVector<uint8_t>();
#else
glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_ARRAY_BUFFER);
#endif
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
float longest_axis = 0; float longest_axis = 0;
@ -7133,7 +7177,7 @@ void RasterizerStorageGLES3::initialize() {
config.etc2_supported = true; config.etc2_supported = true;
config.hdr_supported = false; config.hdr_supported = false;
config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_dxt1") || config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc"); config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_dxt1") || config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc"); config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc");
#endif #endif
config.pvrtc_supported = config.extensions.has("GL_IMG_texture_compression_pvrtc"); config.pvrtc_supported = config.extensions.has("GL_IMG_texture_compression_pvrtc");

View File

@ -42,6 +42,11 @@
#include "shaders/cubemap_filter.glsl.gen.h" #include "shaders/cubemap_filter.glsl.gen.h"
#include "shaders/particles.glsl.gen.h" #include "shaders/particles.glsl.gen.h"
// WebGL 2.0 has no MapBufferRange/UnmapBuffer, but offers a non-ES style BufferSubData API instead.
#ifdef __EMSCRIPTEN__
void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
#endif
class RasterizerCanvasGLES3; class RasterizerCanvasGLES3;
class RasterizerSceneGLES3; class RasterizerSceneGLES3;

View File

@ -729,7 +729,7 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String &p_code,
Vector<String> shader = p_code.split("\n"); Vector<String> shader = p_code.split("\n");
for (int i = 0; i < shader.size(); i++) { for (int i = 0; i < shader.size(); i++) {
print_line(itos(i) + " " + shader[i]); print_line(itos(i + 1) + " " + shader[i]);
} }
_err_print_error(NULL, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER); _err_print_error(NULL, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER);
@ -781,8 +781,6 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal"; actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map"; actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth"; actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth";
actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp";
actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color";
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture"; actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture";
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size"; actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture"; actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture";
@ -825,7 +823,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp"; actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp";
actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp"; actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp";
actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize"; actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize";
//actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"]=ShaderLanguage::TYPE_INT; actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "gl_InstanceID";
//builtins //builtins
@ -847,13 +845,11 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss";
actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy"; actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy";
actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
//actions[VS::SHADER_SPATIAL].renames["SSS_SPREAD"] = "sss_spread";
actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission"; actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission";
actions[VS::SHADER_SPATIAL].renames["AO"] = "ao"; actions[VS::SHADER_SPATIAL].renames["AO"] = "ao";
actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission"; actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission";
//actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord";
actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom";
actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv";
@ -895,8 +891,6 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";

View File

@ -141,7 +141,7 @@ void FileAccessWindows::close() {
} }
if (rename_error) { if (rename_error) {
attempts--; attempts--;
OS::get_singleton()->delay_usec(1000000); //wait 100msec and try again OS::get_singleton()->delay_usec(100000); // wait 100msec and try again
} }
} }

View File

@ -448,7 +448,7 @@ if env['tools']:
# Fonts # Fonts
flist = glob.glob(path + "/../thirdparty/fonts/*.ttf") flist = glob.glob(path + "/../thirdparty/fonts/*.ttf")
flist.append(glob.glob(path + "/../thirdparty/fonts/*.otf")) flist.extend(glob.glob(path + "/../thirdparty/fonts/*.otf"))
env.Depends('#editor/builtin_fonts.gen.h', flist) env.Depends('#editor/builtin_fonts.gen.h', flist)
env.CommandNoCache('#editor/builtin_fonts.gen.h', flist, make_fonts_header) env.CommandNoCache('#editor/builtin_fonts.gen.h', flist, make_fonts_header)

View File

@ -149,7 +149,6 @@ void EditorLog::_bind_methods() {
EditorLog::EditorLog() { EditorLog::EditorLog() {
VBoxContainer *vb = this; VBoxContainer *vb = this;
add_constant_override("separation", get_constant("separation", "VBoxContainer"));
HBoxContainer *hb = memnew(HBoxContainer); HBoxContainer *hb = memnew(HBoxContainer);
vb->add_child(hb); vb->add_child(hb);
@ -181,6 +180,8 @@ EditorLog::EditorLog() {
current = Thread::get_caller_id(); current = Thread::get_caller_id();
add_constant_override("separation", get_constant("separation", "VBoxContainer"));
EditorNode::get_undo_redo()->set_commit_notify_callback(_undo_redo_cbk, this); EditorNode::get_undo_redo()->set_commit_notify_callback(_undo_redo_cbk, this);
} }

View File

@ -2045,10 +2045,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break; } break;
case SETTINGS_EXPORT_PREFERENCES: {
//project_export_settings->popup_centered_ratio();
} break;
case FILE_IMPORT_SUBSCENE: { case FILE_IMPORT_SUBSCENE: {
//import_subscene->popup_centered_ratio(); //import_subscene->popup_centered_ratio();
@ -2490,7 +2486,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
export_template_manager->popup_manager(); export_template_manager->popup_manager();
} break; } break;
case SETTINGS_TOGGLE_FULLSCREN: { case SETTINGS_TOGGLE_FULLSCREEN: {
OS::get_singleton()->set_window_fullscreen(!OS::get_singleton()->is_window_fullscreen()); OS::get_singleton()->set_window_fullscreen(!OS::get_singleton()->is_window_fullscreen());
@ -4447,7 +4443,7 @@ void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) {
for (int i = 0; i < p_files.size(); i++) { for (int i = 0; i < p_files.size(); i++) {
String from = p_files[i]; String from = p_files[i];
if (!ResourceFormatImporter::get_singleton()->can_be_imported(from) && (just_copy.find(from.get_extension().to_lower()) != -1)) { if (!ResourceFormatImporter::get_singleton()->can_be_imported(from) && (just_copy.find(from.get_extension().to_lower()) == -1)) {
continue; continue;
} }
String to = to_path.plus_file(from.get_file()); String to = to_path.plus_file(from.get_file());
@ -5058,7 +5054,11 @@ EditorNode::EditorNode() {
srt->add_child(tabbar_container); srt->add_child(tabbar_container);
tabbar_container->add_child(scene_tabs); tabbar_container->add_child(scene_tabs);
distraction_free = memnew(ToolButton); distraction_free = memnew(ToolButton);
#ifdef OSX_ENABLED
distraction_free->set_shortcut(ED_SHORTCUT("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_D));
#else
distraction_free->set_shortcut(ED_SHORTCUT("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F11)); distraction_free->set_shortcut(ED_SHORTCUT("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F11));
#endif
distraction_free->set_tooltip(TTR("Toggle distraction-free mode.")); distraction_free->set_tooltip(TTR("Toggle distraction-free mode."));
distraction_free->connect("pressed", this, "_toggle_distraction_free_mode"); distraction_free->connect("pressed", this, "_toggle_distraction_free_mode");
distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons")); distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons"));
@ -5167,7 +5167,7 @@ EditorNode::EditorNode() {
p->add_shortcut(ED_SHORTCUT("editor/save_scene_as", TTR("Save Scene As..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_AS_SCENE); p->add_shortcut(ED_SHORTCUT("editor/save_scene_as", TTR("Save Scene As..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_AS_SCENE);
p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes", TTR("Save all Scenes"), KEY_MASK_ALT + KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_ALL_SCENES); p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes", TTR("Save all Scenes"), KEY_MASK_ALT + KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_ALL_SCENES);
p->add_separator(); p->add_separator();
p->add_shortcut(ED_SHORTCUT("editor/close_scene", TTR("Close Scene"), KEY_MASK_SHIFT + KEY_MASK_CTRL + KEY_W), FILE_CLOSE); p->add_shortcut(ED_SHORTCUT("editor/close_scene", TTR("Close Scene"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_W), FILE_CLOSE);
p->add_separator(); p->add_separator();
p->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT); p->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT);
p->add_separator(); p->add_separator();
@ -5221,7 +5221,7 @@ EditorNode::EditorNode() {
#ifdef OSX_ENABLED #ifdef OSX_ENABLED
p->add_item(TTR("Quit to Project List"), RUN_PROJECT_MANAGER, KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q); p->add_item(TTR("Quit to Project List"), RUN_PROJECT_MANAGER, KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q);
#else #else
p->add_item(TTR("Quit to Project List"), RUN_PROJECT_MANAGER, KEY_MASK_SHIFT + KEY_MASK_CTRL + KEY_Q); p->add_item(TTR("Quit to Project List"), RUN_PROJECT_MANAGER, KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Q);
#endif #endif
PanelContainer *editor_region = memnew(PanelContainer); PanelContainer *editor_region = memnew(PanelContainer);
@ -5270,7 +5270,11 @@ EditorNode::EditorNode() {
p->add_child(editor_layouts); p->add_child(editor_layouts);
editor_layouts->connect("id_pressed", this, "_layout_menu_option"); editor_layouts->connect("id_pressed", this, "_layout_menu_option");
p->add_submenu_item(TTR("Editor Layout"), "Layouts"); p->add_submenu_item(TTR("Editor Layout"), "Layouts");
p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREN); #ifdef OSX_ENABLED
p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_F), SETTINGS_TOGGLE_FULLSCREEN);
#else
p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREEN);
#endif
p->add_separator(); p->add_separator();
p->add_item(TTR("Manage Export Templates"), SETTINGS_MANAGE_EXPORT_TEMPLATES); p->add_item(TTR("Manage Export Templates"), SETTINGS_MANAGE_EXPORT_TEMPLATES);
@ -5311,7 +5315,11 @@ EditorNode::EditorNode() {
play_button->set_focus_mode(Control::FOCUS_NONE); play_button->set_focus_mode(Control::FOCUS_NONE);
play_button->connect("pressed", this, "_menu_option", make_binds(RUN_PLAY)); play_button->connect("pressed", this, "_menu_option", make_binds(RUN_PLAY));
play_button->set_tooltip(TTR("Play the project.")); play_button->set_tooltip(TTR("Play the project."));
#ifdef OSX_ENABLED
play_button->set_shortcut(ED_SHORTCUT("editor/play", TTR("Play"), KEY_MASK_CMD | KEY_B));
#else
play_button->set_shortcut(ED_SHORTCUT("editor/play", TTR("Play"), KEY_F5)); play_button->set_shortcut(ED_SHORTCUT("editor/play", TTR("Play"), KEY_F5));
#endif
pause_button = memnew(ToolButton); pause_button = memnew(ToolButton);
pause_button->set_toggle_mode(true); pause_button->set_toggle_mode(true);
@ -5320,7 +5328,11 @@ EditorNode::EditorNode() {
pause_button->set_tooltip(TTR("Pause the scene")); pause_button->set_tooltip(TTR("Pause the scene"));
pause_button->set_disabled(true); pause_button->set_disabled(true);
play_hb->add_child(pause_button); play_hb->add_child(pause_button);
#ifdef OSX_ENABLED
pause_button->set_shortcut(ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_Y));
#else
pause_button->set_shortcut(ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), KEY_F7)); pause_button->set_shortcut(ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), KEY_F7));
#endif
stop_button = memnew(ToolButton); stop_button = memnew(ToolButton);
play_hb->add_child(stop_button); play_hb->add_child(stop_button);
@ -5329,7 +5341,11 @@ EditorNode::EditorNode() {
stop_button->connect("pressed", this, "_menu_option", make_binds(RUN_STOP)); stop_button->connect("pressed", this, "_menu_option", make_binds(RUN_STOP));
stop_button->set_tooltip(TTR("Stop the scene.")); stop_button->set_tooltip(TTR("Stop the scene."));
stop_button->set_disabled(true); stop_button->set_disabled(true);
#ifdef OSX_ENABLED
stop_button->set_shortcut(ED_SHORTCUT("editor/stop", TTR("Stop"), KEY_MASK_CMD | KEY_PERIOD));
#else
stop_button->set_shortcut(ED_SHORTCUT("editor/stop", TTR("Stop"), KEY_F8)); stop_button->set_shortcut(ED_SHORTCUT("editor/stop", TTR("Stop"), KEY_F8));
#endif
run_native = memnew(EditorRunNative); run_native = memnew(EditorRunNative);
play_hb->add_child(run_native); play_hb->add_child(run_native);
@ -5347,7 +5363,11 @@ EditorNode::EditorNode() {
play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons")); play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons"));
play_scene_button->connect("pressed", this, "_menu_option", make_binds(RUN_PLAY_SCENE)); play_scene_button->connect("pressed", this, "_menu_option", make_binds(RUN_PLAY_SCENE));
play_scene_button->set_tooltip(TTR("Play the edited scene.")); play_scene_button->set_tooltip(TTR("Play the edited scene."));
#ifdef OSX_ENABLED
play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene", TTR("Play Scene"), KEY_MASK_CMD | KEY_R));
#else
play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene", TTR("Play Scene"), KEY_F6)); play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene", TTR("Play Scene"), KEY_F6));
#endif
play_custom_scene_button = memnew(ToolButton); play_custom_scene_button = memnew(ToolButton);
play_hb->add_child(play_custom_scene_button); play_hb->add_child(play_custom_scene_button);
@ -5356,7 +5376,11 @@ EditorNode::EditorNode() {
play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons")); play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons"));
play_custom_scene_button->connect("pressed", this, "_menu_option", make_binds(RUN_PLAY_CUSTOM_SCENE)); play_custom_scene_button->connect("pressed", this, "_menu_option", make_binds(RUN_PLAY_CUSTOM_SCENE));
play_custom_scene_button->set_tooltip(TTR("Play custom scene")); play_custom_scene_button->set_tooltip(TTR("Play custom scene"));
#ifdef OSX_ENABLED
play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R));
#else
play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F5)); play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F5));
#endif
progress_hb = memnew(BackgroundProgress); progress_hb = memnew(BackgroundProgress);
@ -5868,10 +5892,17 @@ EditorNode::EditorNode() {
print_handler.userdata = this; print_handler.userdata = this;
add_print_handler(&print_handler); add_print_handler(&print_handler);
#ifdef OSX_ENABLED
ED_SHORTCUT("editor/editor_2d", TTR("Open 2D Editor"), KEY_MASK_ALT | KEY_1);
ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_ALT | KEY_2);
ED_SHORTCUT("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_ALT | KEY_3);
ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_MASK_ALT | KEY_SPACE);
#else
ED_SHORTCUT("editor/editor_2d", TTR("Open 2D Editor"), KEY_F1); ED_SHORTCUT("editor/editor_2d", TTR("Open 2D Editor"), KEY_F1);
ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_F2); ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_F2);
ED_SHORTCUT("editor/editor_script", TTR("Open Script Editor"), KEY_F3); //hack neded for script editor F3 search to work :) Assign like this or don't use F3 ED_SHORTCUT("editor/editor_script", TTR("Open Script Editor"), KEY_F3); //hack neded for script editor F3 search to work :) Assign like this or don't use F3
ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_F4); ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_F4);
#endif
ED_SHORTCUT("editor/editor_assetlib", TTR("Open Asset Library")); ED_SHORTCUT("editor/editor_assetlib", TTR("Open Asset Library"));
ED_SHORTCUT("editor/editor_next", TTR("Open the next Editor")); ED_SHORTCUT("editor/editor_next", TTR("Open the next Editor"));
ED_SHORTCUT("editor/editor_prev", TTR("Open the previous Editor")); ED_SHORTCUT("editor/editor_prev", TTR("Open the previous Editor"));

View File

@ -173,14 +173,13 @@ private:
SETTINGS_UPDATE_ALWAYS, SETTINGS_UPDATE_ALWAYS,
SETTINGS_UPDATE_CHANGES, SETTINGS_UPDATE_CHANGES,
SETTINGS_UPDATE_SPINNER_HIDE, SETTINGS_UPDATE_SPINNER_HIDE,
SETTINGS_EXPORT_PREFERENCES,
SETTINGS_PREFERENCES, SETTINGS_PREFERENCES,
SETTINGS_LAYOUT_SAVE, SETTINGS_LAYOUT_SAVE,
SETTINGS_LAYOUT_DELETE, SETTINGS_LAYOUT_DELETE,
SETTINGS_LAYOUT_DEFAULT, SETTINGS_LAYOUT_DEFAULT,
SETTINGS_MANAGE_EXPORT_TEMPLATES, SETTINGS_MANAGE_EXPORT_TEMPLATES,
SETTINGS_PICK_MAIN_SCENE, SETTINGS_PICK_MAIN_SCENE,
SETTINGS_TOGGLE_FULLSCREN, SETTINGS_TOGGLE_FULLSCREEN,
SETTINGS_HELP, SETTINGS_HELP,
SCENE_TAB_CLOSE, SCENE_TAB_CLOSE,

View File

@ -68,13 +68,13 @@ void EditorProfiler::add_frame_metric(const Metric &p_metric, bool p_final) {
} }
updating_frame = false; updating_frame = false;
if (!frame_delay->is_processing()) { if (frame_delay->is_stopped()) {
frame_delay->set_wait_time(p_final ? 0.1 : 1); frame_delay->set_wait_time(p_final ? 0.1 : 1);
frame_delay->start(); frame_delay->start();
} }
if (!plot_delay->is_processing()) { if (plot_delay->is_stopped()) {
plot_delay->set_wait_time(0.1); plot_delay->set_wait_time(0.1);
plot_delay->start(); plot_delay->start();
} }

View File

@ -511,6 +511,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("filesystem/import/pvrtc_fast_conversion", false); _initial_set("filesystem/import/pvrtc_fast_conversion", false);
_initial_set("run/auto_save/save_before_running", true); _initial_set("run/auto_save/save_before_running", true);
// Output
hints["run/output/font_size"] = PropertyInfo(Variant::INT, "run/output/font_size", PROPERTY_HINT_RANGE, "8,96,1", PROPERTY_USAGE_DEFAULT);
_initial_set("run/output/always_clear_output_on_play", true); _initial_set("run/output/always_clear_output_on_play", true);
_initial_set("run/output/always_open_output_on_play", true); _initial_set("run/output/always_open_output_on_play", true);
_initial_set("run/output/always_close_output_on_stop", false); _initial_set("run/output/always_close_output_on_stop", false);
@ -734,12 +737,6 @@ void EditorSettings::create() {
// Validate/create data dir and subdirectories // Validate/create data dir and subdirectories
dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (dir->change_dir(data_path) != OK) {
ERR_PRINT("Cannot find path for data directory!");
memdelete(dir);
goto fail;
}
if (dir->change_dir(data_dir) != OK) { if (dir->change_dir(data_dir) != OK) {
dir->make_dir_recursive(data_dir); dir->make_dir_recursive(data_dir);
if (dir->change_dir(data_dir) != OK) { if (dir->change_dir(data_dir) != OK) {
@ -1351,33 +1348,9 @@ struct ShortCutMapping {
Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode) { Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode) {
#ifdef OSX_ENABLED #ifdef OSX_ENABLED
static const ShortCutMapping macos_mappings[] = { // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
{ "editor/play", KEY_MASK_CMD | KEY_B },
{ "editor/play_scene", KEY_MASK_CMD | KEY_R },
{ "editor/pause_scene", KEY_MASK_CMD | KEY_MASK_CTRL | KEY_Y },
{ "editor/stop", KEY_MASK_CMD | KEY_PERIOD },
{ "editor/play_custom_scene", KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_R },
{ "editor/editor_2d", KEY_MASK_ALT | KEY_1 },
{ "editor/editor_3d", KEY_MASK_ALT | KEY_2 },
{ "editor/editor_script", KEY_MASK_ALT | KEY_3 },
{ "editor/editor_help", KEY_MASK_ALT | KEY_SPACE },
{ "editor/fullscreen_mode", KEY_MASK_CMD | KEY_MASK_CTRL | KEY_F },
{ "editor/distraction_free_mode", KEY_MASK_CMD | KEY_MASK_CTRL | KEY_D },
{ "script_text_editor/contextual_help", KEY_MASK_ALT | KEY_MASK_SHIFT | KEY_SPACE },
{ "script_text_editor/find_next", KEY_MASK_CMD | KEY_G },
{ "script_text_editor/find_previous", KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G },
{ "script_text_editor/toggle_breakpoint", KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B }
};
if (p_keycode == KEY_DELETE) { if (p_keycode == KEY_DELETE) {
p_keycode = KEY_MASK_CMD | KEY_BACKSPACE; p_keycode = KEY_MASK_CMD | KEY_BACKSPACE;
} else {
for (int i = 0; i < sizeof(macos_mappings) / sizeof(ShortCutMapping); i++) {
if (p_path == macos_mappings[i].path) {
p_keycode = macos_mappings[i].keycode;
break;
}
}
} }
#endif #endif

View File

@ -992,6 +992,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("port_offset", "GraphNode", 14 * EDSCALE); theme->set_constant("port_offset", "GraphNode", 14 * EDSCALE);
theme->set_constant("title_h_offset", "GraphNode", -16 * EDSCALE); theme->set_constant("title_h_offset", "GraphNode", -16 * EDSCALE);
theme->set_constant("title_offset", "GraphNode", 20 * EDSCALE);
theme->set_constant("close_h_offset", "GraphNode", 20 * EDSCALE); theme->set_constant("close_h_offset", "GraphNode", 20 * EDSCALE);
theme->set_constant("close_offset", "GraphNode", 20 * EDSCALE); theme->set_constant("close_offset", "GraphNode", 20 * EDSCALE);
theme->set_icon("close", "GraphNode", theme->get_icon("GuiCloseCustomizable", "EditorIcons")); theme->set_icon("close", "GraphNode", theme->get_icon("GuiCloseCustomizable", "EditorIcons"));

View File

@ -121,7 +121,6 @@ void ExportTemplateManager::_update_template_list() {
void ExportTemplateManager::_download_template(const String &p_version) { void ExportTemplateManager::_download_template(const String &p_version) {
print_line("download " + p_version);
while (template_list->get_child_count()) { while (template_list->get_child_count()) {
memdelete(template_list->get_child(0)); memdelete(template_list->get_child(0));
} }
@ -226,7 +225,10 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_
version = data_str; version = data_str;
} }
fc++; if (file.get_file().size() != 0) {
fc++;
}
ret = unzGoToNextFile(pkg); ret = unzGoToNextFile(pkg);
} }
@ -266,6 +268,11 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_
String file = String(fname).get_file(); String file = String(fname).get_file();
if (file.size() == 0) {
ret = unzGoToNextFile(pkg);
continue;
}
Vector<uint8_t> data; Vector<uint8_t> data;
data.resize(info.uncompressed_size); data.resize(info.uncompressed_size);
@ -342,7 +349,6 @@ void ExportTemplateManager::_http_download_mirror_completed(int p_status, int p_
bool mirrors_found = false; bool mirrors_found = false;
Dictionary d = r; Dictionary d = r;
print_line(r);
if (d.has("mirrors")) { if (d.has("mirrors")) {
Array mirrors = d["mirrors"]; Array mirrors = d["mirrors"];
for (int i = 0; i < mirrors.size(); i++) { for (int i = 0; i < mirrors.size(); i++) {
@ -488,7 +494,6 @@ void ExportTemplateManager::_notification(int p_what) {
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
if (!is_visible_in_tree()) { if (!is_visible_in_tree()) {
print_line("closed");
download_templates->cancel_request(); download_templates->cancel_request();
set_process(false); set_process(false);
} }

View File

@ -339,7 +339,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) {
NodeMap nm; NodeMap nm;
nm.node = node; nm.node = node;
node_map[p_node->id] = nm; node_map[p_node->id] = nm;
node_name_map[p_node->name] = p_node->id; node_name_map[node->get_name()] = p_node->id;
Transform xf = p_node->default_transform; Transform xf = p_node->default_transform;
xf = collada.fix_transform(xf) * p_node->post_transform; xf = collada.fix_transform(xf) * p_node->post_transform;

View File

@ -1708,14 +1708,14 @@ void EditorSceneImporterGLTF::_generate_node(GLTFState &state, int p_node, Node
#endif #endif
for (int i = 0; i < n->children.size(); i++) { for (int i = 0; i < n->children.size(); i++) {
if (state.nodes[n->children[i]]->joints.size()) { if (state.nodes[n->children[i]]->joints.size()) {
_generate_bone(state, n->children[i], skeletons, Vector<int>(), node); _generate_bone(state, n->children[i], skeletons, node);
} else { } else {
_generate_node(state, n->children[i], node, p_owner, skeletons); _generate_node(state, n->children[i], node, p_owner, skeletons);
} }
} }
} }
void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vector<Skeleton *> &skeletons, const Vector<int> &p_parent_bones, Node *p_parent_node) { void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vector<Skeleton *> &skeletons, Node *p_parent_node) {
ERR_FAIL_INDEX(p_node, state.nodes.size()); ERR_FAIL_INDEX(p_node, state.nodes.size());
if (state.skeleton_nodes.has(p_node)) { if (state.skeleton_nodes.has(p_node)) {
@ -1730,30 +1730,28 @@ void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vecto
} }
GLTFNode *n = state.nodes[p_node]; GLTFNode *n = state.nodes[p_node];
Vector<int> parent_bones;
for (int i = 0; i < n->joints.size(); i++) { for (int i = 0; i < n->joints.size(); i++) {
ERR_FAIL_COND(n->joints[i].skin < 0); const int skin = n->joints[i].skin;
ERR_FAIL_COND(skin < 0);
int bone_index = n->joints[i].bone; Skeleton *s = skeletons[skin];
const GLTFNode *gltf_bone_node = state.nodes[state.skins[skin].bones[n->joints[i].bone].node];
const String bone_name = gltf_bone_node->name;
const int parent = gltf_bone_node->parent;
const int parent_index = s->find_bone(state.nodes[parent]->name);
Skeleton *s = skeletons[n->joints[i].skin]; s->add_bone(bone_name);
while (s->get_bone_count() <= bone_index) { const int bone_index = s->find_bone(bone_name);
s->add_bone("Bone " + itos(s->get_bone_count())); s->set_bone_parent(bone_index, parent_index);
} s->set_bone_rest(bone_index, state.skins[skin].bones[n->joints[i].bone].inverse_bind.affine_inverse());
if (p_parent_bones.size()) {
s->set_bone_parent(bone_index, p_parent_bones[i]);
}
s->set_bone_rest(bone_index, state.skins[n->joints[i].skin].bones[n->joints[i].bone].inverse_bind.affine_inverse());
n->godot_nodes.push_back(s); n->godot_nodes.push_back(s);
n->joints[i].godot_bone_index = bone_index; n->joints[i].godot_bone_index = bone_index;
parent_bones.push_back(bone_index);
} }
for (int i = 0; i < n->children.size(); i++) { for (int i = 0; i < n->children.size(); i++) {
_generate_bone(state, n->children[i], skeletons, parent_bones, p_parent_node); _generate_bone(state, n->children[i], skeletons, p_parent_node);
} }
} }
@ -2068,7 +2066,7 @@ Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, int p_bake_f
} }
for (int i = 0; i < state.root_nodes.size(); i++) { for (int i = 0; i < state.root_nodes.size(); i++) {
if (state.nodes[state.root_nodes[i]]->joints.size()) { if (state.nodes[state.root_nodes[i]]->joints.size()) {
_generate_bone(state, state.root_nodes[i], skeletons, Vector<int>(), root); _generate_bone(state, state.root_nodes[i], skeletons, root);
} else { } else {
_generate_node(state, state.root_nodes[i], root, root, skeletons); _generate_node(state, state.root_nodes[i], root, root, skeletons);
} }

View File

@ -311,7 +311,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Vector<Basis> _decode_accessor_as_basis(GLTFState &state, int p_accessor, bool p_for_vertex); Vector<Basis> _decode_accessor_as_basis(GLTFState &state, int p_accessor, bool p_for_vertex);
Vector<Transform> _decode_accessor_as_xform(GLTFState &state, int p_accessor, bool p_for_vertex); Vector<Transform> _decode_accessor_as_xform(GLTFState &state, int p_accessor, bool p_for_vertex);
void _generate_bone(GLTFState &state, int p_node, Vector<Skeleton *> &skeletons, const Vector<int> &p_parent_bones, Node *p_parent_node); void _generate_bone(GLTFState &state, int p_node, Vector<Skeleton *> &skeletons, Node *p_parent_node);
void _generate_node(GLTFState &state, int p_node, Node *p_parent, Node *p_owner, Vector<Skeleton *> &skeletons); void _generate_node(GLTFState &state, int p_node, Node *p_parent, Node *p_owner, Vector<Skeleton *> &skeletons);
void _import_animation(GLTFState &state, AnimationPlayer *ap, int index, int bake_fps, Vector<Skeleton *> skeletons); void _import_animation(GLTFState &state, AnimationPlayer *ap, int index, int bake_fps, Vector<Skeleton *> skeletons);

View File

@ -126,7 +126,12 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Spati
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT); ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
String p = l.replace("map_Kd", "").replace("\\", "/").strip_edges(); String p = l.replace("map_Kd", "").replace("\\", "/").strip_edges();
String path = base_path.plus_file(p); String path;
if (p.is_abs_path()) {
path = p;
} else {
path = base_path.plus_file(p);
}
Ref<Texture> texture = ResourceLoader::load(path); Ref<Texture> texture = ResourceLoader::load(path);
@ -141,7 +146,12 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Spati
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT); ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
String p = l.replace("map_Ks", "").replace("\\", "/").strip_edges(); String p = l.replace("map_Ks", "").replace("\\", "/").strip_edges();
String path = base_path.plus_file(p); String path;
if (p.is_abs_path()) {
path = p;
} else {
path = base_path.plus_file(p);
}
Ref<Texture> texture = ResourceLoader::load(path); Ref<Texture> texture = ResourceLoader::load(path);
@ -156,7 +166,12 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Spati
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT); ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
String p = l.replace("map_Ns", "").replace("\\", "/").strip_edges(); String p = l.replace("map_Ns", "").replace("\\", "/").strip_edges();
String path = base_path.plus_file(p); String path;
if (p.is_abs_path()) {
path = p;
} else {
path = base_path.plus_file(p);
}
Ref<Texture> texture = ResourceLoader::load(path); Ref<Texture> texture = ResourceLoader::load(path);

View File

@ -739,6 +739,10 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
_goto_line(p_row); _goto_line(p_row);
if (result.class_name.begins_with("_")) {
result.class_name = result.class_name.substr(1, result.class_name.length() - 1);
}
switch (result.type) { switch (result.type) {
case ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION: { case ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION: {
@ -1660,7 +1664,7 @@ void ScriptTextEditor::register_editor() {
ED_SHORTCUT("script_text_editor/select_all", TTR("Select All"), KEY_MASK_CMD | KEY_A); ED_SHORTCUT("script_text_editor/select_all", TTR("Select All"), KEY_MASK_CMD | KEY_A);
ED_SHORTCUT("script_text_editor/move_up", TTR("Move Up"), KEY_MASK_ALT | KEY_UP); ED_SHORTCUT("script_text_editor/move_up", TTR("Move Up"), KEY_MASK_ALT | KEY_UP);
ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KEY_MASK_ALT | KEY_DOWN); ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KEY_MASK_ALT | KEY_DOWN);
ED_SHORTCUT("script_text_editor/delete_line", TTR("Delete Line"), KEY_MASK_CTRL | KEY_MASK_SHIFT | KEY_K); ED_SHORTCUT("script_text_editor/delete_line", TTR("Delete Line"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_K);
//leave these at zero, same can be accomplished with tab/shift-tab, including selection //leave these at zero, same can be accomplished with tab/shift-tab, including selection
//the next/previous in history shortcut in this case makes a lot more sene. //the next/previous in history shortcut in this case makes a lot more sene.
@ -1673,34 +1677,46 @@ void ScriptTextEditor::register_editor() {
ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0); ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0);
#ifdef OSX_ENABLED #ifdef OSX_ENABLED
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C); ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C);
ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CTRL | KEY_SPACE);
#else #else
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD | KEY_B); ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD | KEY_B);
ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CMD | KEY_SPACE);
#endif #endif
ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CTRL | KEY_MASK_ALT | KEY_T); ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CMD | KEY_SPACE);
ED_SHORTCUT("script_text_editor/convert_indent_to_spaces", TTR("Convert Indent To Spaces"), KEY_MASK_CTRL | KEY_MASK_SHIFT | KEY_Y); ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_T);
ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent To Tabs"), KEY_MASK_CTRL | KEY_MASK_SHIFT | KEY_X); ED_SHORTCUT("script_text_editor/convert_indent_to_spaces", TTR("Convert Indent To Spaces"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Y);
ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent To Tabs"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_X);
ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KEY_MASK_CMD | KEY_I); ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KEY_MASK_CMD | KEY_I);
#ifdef OSX_ENABLED
ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B);
#else
ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9); ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9);
ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KEY_MASK_CTRL | KEY_MASK_SHIFT | KEY_F9); #endif
ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Goto Next Breakpoint"), KEY_MASK_CTRL | KEY_PERIOD); ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F9);
ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Goto Previous Breakpoint"), KEY_MASK_CTRL | KEY_COMMA); ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Goto Next Breakpoint"), KEY_MASK_CMD | KEY_PERIOD);
ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Goto Previous Breakpoint"), KEY_MASK_CMD | KEY_COMMA);
ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Convert To Uppercase"), KEY_MASK_SHIFT | KEY_F4); ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Convert To Uppercase"), KEY_MASK_SHIFT | KEY_F4);
ED_SHORTCUT("script_text_editor/convert_to_lowercase", TTR("Convert To Lowercase"), KEY_MASK_SHIFT | KEY_F3); ED_SHORTCUT("script_text_editor/convert_to_lowercase", TTR("Convert To Lowercase"), KEY_MASK_SHIFT | KEY_F3);
ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KEY_MASK_SHIFT | KEY_F2); ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KEY_MASK_SHIFT | KEY_F2);
ED_SHORTCUT("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F); ED_SHORTCUT("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F);
#ifdef OSX_ENABLED
ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_MASK_CMD | KEY_G);
ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G);
#else
ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_F3); ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_F3);
ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3); ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3);
#endif
ED_SHORTCUT("script_text_editor/replace", TTR("Replace..."), KEY_MASK_CMD | KEY_R); ED_SHORTCUT("script_text_editor/replace", TTR("Replace..."), KEY_MASK_CMD | KEY_R);
ED_SHORTCUT("script_text_editor/goto_function", TTR("Goto Function..."), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_F); ED_SHORTCUT("script_text_editor/goto_function", TTR("Goto Function..."), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_F);
ED_SHORTCUT("script_text_editor/goto_line", TTR("Goto Line..."), KEY_MASK_CMD | KEY_L); ED_SHORTCUT("script_text_editor/goto_line", TTR("Goto Line..."), KEY_MASK_CMD | KEY_L);
#ifdef OSX_ENABLED
ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_ALT | KEY_MASK_SHIFT | KEY_SPACE);
#else
ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_SHIFT | KEY_F1); ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_SHIFT | KEY_F1);
#endif
ScriptEditor::register_create_script_editor_function(create_editor); ScriptEditor::register_create_script_editor_function(create_editor);
} }

View File

@ -595,7 +595,7 @@ bool SpriteFramesEditor::can_drop_data_fw(const Point2 &p_point, const Variant &
return false; return false;
for (int i = 0; i < files.size(); i++) { for (int i = 0; i < files.size(); i++) {
String file = files[0]; String file = files[i];
String ftype = EditorFileSystem::get_singleton()->get_file_type(file); String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
if (!ClassDB::is_parent_class(ftype, "Texture")) { if (!ClassDB::is_parent_class(ftype, "Texture")) {

View File

@ -70,6 +70,9 @@ void ProjectExportDialog::popup_export() {
} }
_update_presets(); _update_presets();
if (presets->get_current() >= 0) {
_edit_preset(presets->get_current()); // triggers rescan for templates if newly installed
}
// Restore valid window bounds or pop up at default size. // Restore valid window bounds or pop up at default size.
if (EditorSettings::get_singleton()->has_setting("interface/dialogs/export_bounds")) { if (EditorSettings::get_singleton()->has_setting("interface/dialogs/export_bounds")) {
@ -141,7 +144,6 @@ void ProjectExportDialog::_update_presets() {
if (current_idx != -1) { if (current_idx != -1) {
presets->select(current_idx); presets->select(current_idx);
//_edit_preset(current_idx);
} }
updating = false; updating = false;
@ -154,6 +156,7 @@ void ProjectExportDialog::_edit_preset(int p_index) {
name->set_editable(false); name->set_editable(false);
runnable->set_disabled(true); runnable->set_disabled(true);
parameters->edit(NULL); parameters->edit(NULL);
presets->unselect_all();
delete_preset->set_disabled(true); delete_preset->set_disabled(true);
sections->hide(); sections->hide();
patches->clear(); patches->clear();
@ -215,7 +218,7 @@ void ProjectExportDialog::_edit_preset(int p_index) {
if (error != String()) { if (error != String()) {
Vector<String> items = error.split("\n"); Vector<String> items = error.split("\n", false);
error = ""; error = "";
for (int i = 0; i < items.size(); i++) { for (int i = 0; i < items.size(); i++) {
if (i > 0) if (i > 0)
@ -425,11 +428,9 @@ void ProjectExportDialog::_delete_preset() {
void ProjectExportDialog::_delete_preset_confirm() { void ProjectExportDialog::_delete_preset_confirm() {
int idx = presets->get_current(); int idx = presets->get_current();
parameters->edit(NULL); //to avoid crash
_edit_preset(-1); _edit_preset(-1);
EditorExport::get_singleton()->remove_export_preset(idx); EditorExport::get_singleton()->remove_export_preset(idx);
_update_presets(); _update_presets();
_edit_preset(presets->get_current());
} }
Variant ProjectExportDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) { Variant ProjectExportDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
@ -742,7 +743,7 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) {
Error err = platform->export_project(current, export_debug->is_pressed(), p_path, 0); Error err = platform->export_project(current, export_debug->is_pressed(), p_path, 0);
if (err != OK) { if (err != OK) {
error_dialog->set_text(TTR("Export templates for this platform are missing/corrupted: ") + platform->get_name()); error_dialog->set_text(TTR("Export templates for this platform are missing/corrupted:") + " " + platform->get_name());
error_dialog->show(); error_dialog->show();
error_dialog->popup_centered_minsize(Size2(300, 80)); error_dialog->popup_centered_minsize(Size2(300, 80));
ERR_PRINT("Failed to export project"); ERR_PRINT("Failed to export project");
@ -942,7 +943,7 @@ ProjectExportDialog::ProjectExportDialog() {
export_error = memnew(Label); export_error = memnew(Label);
main_vb->add_child(export_error); main_vb->add_child(export_error);
export_error->hide(); export_error->hide();
export_error->add_color_override("font_color", get_color("error_color", "Editor")); export_error->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor"));
export_templates_error = memnew(HBoxContainer); export_templates_error = memnew(HBoxContainer);
main_vb->add_child(export_templates_error); main_vb->add_child(export_templates_error);
@ -950,7 +951,7 @@ ProjectExportDialog::ProjectExportDialog() {
Label *export_error2 = memnew(Label); Label *export_error2 = memnew(Label);
export_templates_error->add_child(export_error2); export_templates_error->add_child(export_error2);
export_error2->add_color_override("font_color", get_color("error_color", "Editor")); export_error2->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor"));
export_error2->set_text(" - " + TTR("Export templates for this platform are missing:") + " "); export_error2->set_text(" - " + TTR("Export templates for this platform are missing:") + " ");
error_dialog = memnew(AcceptDialog); error_dialog = memnew(AcceptDialog);
@ -961,6 +962,7 @@ ProjectExportDialog::ProjectExportDialog() {
LinkButton *download_templates = memnew(LinkButton); LinkButton *download_templates = memnew(LinkButton);
download_templates->set_text(TTR("Manage Export Templates")); download_templates->set_text(TTR("Manage Export Templates"));
download_templates->set_v_size_flags(SIZE_SHRINK_CENTER);
export_templates_error->add_child(download_templates); export_templates_error->add_child(download_templates);
download_templates->connect("pressed", this, "_open_export_template_manager"); download_templates->connect("pressed", this, "_open_export_template_manager");

View File

@ -2397,10 +2397,12 @@ void PropertyEditor::_check_reload_status(const String &p_name, TreeItem *item)
if (!has_reload && !obj->get_script().is_null()) { if (!has_reload && !obj->get_script().is_null()) {
Ref<Script> scr = obj->get_script(); Ref<Script> scr = obj->get_script();
Variant orig_value; if (scr.is_valid()) {
if (scr->get_property_default_value(p_name, orig_value)) { Variant orig_value;
if (orig_value != obj->get(p_name)) { if (scr->get_property_default_value(p_name, orig_value)) {
has_reload = true; if (orig_value != obj->get(p_name)) {
has_reload = true;
}
} }
} }
} }
@ -3558,11 +3560,13 @@ void PropertyEditor::update_tree() {
if (!has_reload && !obj->get_script().is_null()) { if (!has_reload && !obj->get_script().is_null()) {
Ref<Script> scr = obj->get_script(); Ref<Script> scr = obj->get_script();
Variant orig_value; if (scr.is_valid()) {
if (scr->get_property_default_value(p.name, orig_value)) { Variant orig_value;
if (orig_value != obj->get(p.name)) { if (scr->get_property_default_value(p.name, orig_value)) {
item->add_button(1, get_icon("ReloadSmall", "EditorIcons"), 3); if (orig_value != obj->get(p.name)) {
has_reload = true; item->add_button(1, get_icon("ReloadSmall", "EditorIcons"), 3);
has_reload = true;
}
} }
} }
} }
@ -3950,9 +3954,11 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
if (!obj->get_script().is_null()) { if (!obj->get_script().is_null()) {
Ref<Script> scr = obj->get_script(); Ref<Script> scr = obj->get_script();
Variant orig_value; if (scr.is_valid()) {
if (scr->get_property_default_value(prop, orig_value)) { Variant orig_value;
_edit_set(prop, orig_value); if (scr->get_property_default_value(prop, orig_value)) {
_edit_set(prop, orig_value);
}
} }
} }

View File

@ -537,6 +537,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
auto_build_solutions = true; auto_build_solutions = true;
editor = true; editor = true;
} else if (I->get() == "--export" || I->get() == "--export-debug") { // Export project
editor = true;
main_args.push_back(I->get());
#endif #endif
} else if (I->get() == "--no-window") { // disable window creation, Windows only } else if (I->get() == "--no-window") { // disable window creation, Windows only
@ -1286,20 +1290,10 @@ bool Main::start() {
removal_docs.push_back(args[j]); removal_docs.push_back(args[j]);
} else if (args[i] == "--export") { } else if (args[i] == "--export") {
editor = true; //needs editor editor = true; //needs editor
if (i + 1 < args.size()) { _export_preset = args[i + 1];
_export_preset = args[i + 1];
} else {
ERR_PRINT("Export preset name not specified");
return false;
}
} else if (args[i] == "--export-debug") { } else if (args[i] == "--export-debug") {
editor = true; //needs editor editor = true; //needs editor
if (i + 1 < args.size()) { _export_preset = args[i + 1];
_export_preset = args[i + 1];
} else {
ERR_PRINT("Export preset name not specified");
return false;
}
export_debug = true; export_debug = true;
#endif #endif
} else { } else {
@ -1703,6 +1697,7 @@ bool Main::start() {
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
if (project_manager || (script == "" && test == "" && game_path == "" && !editor)) { if (project_manager || (script == "" && test == "" && game_path == "" && !editor)) {
Engine::get_singleton()->set_editor_hint(true);
ProjectManager *pmanager = memnew(ProjectManager); ProjectManager *pmanager = memnew(ProjectManager);
ProgressDialog *progress_dialog = memnew(ProgressDialog); ProgressDialog *progress_dialog = memnew(ProgressDialog);
pmanager->add_child(progress_dialog); pmanager->add_child(progress_dialog);

View File

@ -180,7 +180,7 @@ static String dump_node_code(SL::Node *p_node, int p_level) {
String scode = dump_node_code(bnode->statements[i], p_level); String scode = dump_node_code(bnode->statements[i], p_level);
if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW) { if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW) {
code += scode; //use directly code += scode; //use directly
} else { } else {
code += _mktab(p_level) + scode + ";\n"; code += _mktab(p_level) + scode + ";\n";

View File

@ -51,8 +51,8 @@ bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) co
if (needs) { if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
if (m_pickRay && gObj->is_ray_pickable()) { if (m_pickRay && !gObj->is_ray_pickable()) {
return true; return false;
} else if (m_exclude->has(gObj->get_self())) { } else if (m_exclude->has(gObj->get_self())) {
return false; return false;
} }
@ -235,6 +235,7 @@ btScalar GodotRestInfoContactResultCallback::addSingleResult(btManifoldPoint &cp
colObj = static_cast<CollisionObjectBullet *>(colObj1Wrap->getCollisionObject()->getUserPointer()); colObj = static_cast<CollisionObjectBullet *>(colObj1Wrap->getCollisionObject()->getUserPointer());
m_result->shape = cp.m_index1; m_result->shape = cp.m_index1;
B_TO_G(cp.getPositionWorldOnB(), m_result->point); B_TO_G(cp.getPositionWorldOnB(), m_result->point);
B_TO_G(cp.m_normalWorldOnB, m_result->normal);
m_rest_info_bt_point = cp.getPositionWorldOnB(); m_rest_info_bt_point = cp.getPositionWorldOnB();
m_rest_info_collision_object = colObj1Wrap->getCollisionObject(); m_rest_info_collision_object = colObj1Wrap->getCollisionObject();
} else { } else {

View File

@ -291,6 +291,9 @@ void ConvexPolygonShapeBullet::setup(const Vector<Vector3> &p_vertices) {
} }
btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
if (!vertices.size())
// This is necessary since 0 vertices
return prepare(ShapeBullet::create_shape_empty());
btCollisionShape *cs(ShapeBullet::create_shape_convex(vertices)); btCollisionShape *cs(ShapeBullet::create_shape_convex(vertices));
cs->setLocalScaling(p_implicit_scale); cs->setLocalScaling(p_implicit_scale);
prepare(cs); prepare(cs);

View File

@ -108,8 +108,8 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path,
uint32_t magic = f->get_32(); uint32_t magic = f->get_32();
uint32_t hsize = f->get_32(); uint32_t hsize = f->get_32();
uint32_t flags = f->get_32(); uint32_t flags = f->get_32();
uint32_t width = f->get_32();
uint32_t height = f->get_32(); uint32_t height = f->get_32();
uint32_t width = f->get_32();
uint32_t pitch = f->get_32(); uint32_t pitch = f->get_32();
/* uint32_t depth = */ f->get_32(); /* uint32_t depth = */ f->get_32();
uint32_t mipmaps = f->get_32(); uint32_t mipmaps = f->get_32();

View File

@ -59,6 +59,7 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int
ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE);
ENetAddress address; ENetAddress address;
memset(&address, 0, sizeof(address));
#ifdef GODOT_ENET #ifdef GODOT_ENET
if (bind_ip.is_wildcard()) { if (bind_ip.is_wildcard()) {

View File

@ -36,7 +36,3 @@ env_etc.add_source_files(env.modules_sources, "*.cpp")
# upstream uses c++11 # upstream uses c++11
if (not env_etc.msvc): if (not env_etc.msvc):
env_etc.Append(CCFLAGS="-std=c++11") env_etc.Append(CCFLAGS="-std=c++11")
# -ffast-math seems to be incompatible with ec2comp on recent versions of
# GCC and Clang
if '-ffast-math' in env_etc['CCFLAGS']:
env_etc['CCFLAGS'].remove('-ffast-math')

View File

@ -150,7 +150,10 @@ Ref<Script> NativeScript::get_base_script() const {
if (!script_data) if (!script_data)
return Ref<Script>(); return Ref<Script>();
Ref<NativeScript> ns = Ref<NativeScript>(NSL->create_script()); NativeScript *script = (NativeScript *)NSL->create_script();
Ref<NativeScript> ns = Ref<NativeScript>(script);
ERR_FAIL_COND_V(!ns.is_valid(), Ref<Script>());
ns->set_class_name(script_data->base); ns->set_class_name(script_data->base);
ns->set_library(get_library()); ns->set_library(get_library());
return ns; return ns;
@ -358,14 +361,13 @@ void NativeScript::get_script_property_list(List<PropertyInfo> *p_list) const {
NativeScriptDesc *script_data = get_script_desc(); NativeScriptDesc *script_data = get_script_desc();
Set<StringName> existing_properties; Set<StringName> existing_properties;
List<PropertyInfo>::Element *original_back = p_list->back();
while (script_data) { while (script_data) {
List<PropertyInfo>::Element *insert_position = p_list->front(); List<PropertyInfo>::Element *insert_position = original_back;
bool insert_before = true;
for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) { for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
if (!existing_properties.has(E.key())) { if (!existing_properties.has(E.key())) {
insert_position = insert_before ? p_list->insert_before(insert_position, E.get().info) : p_list->insert_after(insert_position, E.get().info); insert_position = p_list->insert_after(insert_position, E.get().info);
insert_before = false;
existing_properties.insert(E.key()); existing_properties.insert(E.key());
} }
} }

View File

@ -84,35 +84,20 @@ StringName PluginScript::get_instance_base_type() const {
} }
void PluginScript::update_exports() { void PluginScript::update_exports() {
// TODO
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
#if 0
ASSERT_SCRIPT_VALID(); ASSERT_SCRIPT_VALID();
if (/*changed &&*/ placeholders.size()) { //hm :( if (placeholders.size()) {
//update placeholders if any //update placeholders if any
Map<StringName, Variant> propdefvalues; Map<StringName, Variant> propdefvalues;
List<PropertyInfo> propinfos; List<PropertyInfo> propinfos;
const String *props = (const String *)pybind_get_prop_list(_py_exposed_class);
for (int i = 0; props[i] != ""; ++i) { get_script_property_list(&propinfos);
const String propname = props[i];
pybind_get_prop_default_value(_py_exposed_class, propname.c_str(), (godot_variant *)&propdefvalues[propname]);
pybind_prop_info raw_info;
pybind_get_prop_info(_py_exposed_class, propname.c_str(), &raw_info);
PropertyInfo info;
info.type = (Variant::Type)raw_info.type;
info.name = propname;
info.hint = (PropertyHint)raw_info.hint;
info.hint_string = *(String *)&raw_info.hint_string;
info.usage = raw_info.usage;
propinfos.push_back(info);
}
for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
E->get()->update(propinfos, propdefvalues); E->get()->update(propinfos, _properties_default_values);
} }
} }
#endif #endif
#endif
} }
// TODO: rename p_this "p_owner" ? // TODO: rename p_this "p_owner" ?

View File

@ -726,6 +726,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
case GDScriptParser::OperatorNode::OP_NEG: { case GDScriptParser::OperatorNode::OP_NEG: {
if (!_create_unary_operator(codegen, on, Variant::OP_NEGATE, p_stack_level)) return -1; if (!_create_unary_operator(codegen, on, Variant::OP_NEGATE, p_stack_level)) return -1;
} break; } break;
case GDScriptParser::OperatorNode::OP_POS: {
if (!_create_unary_operator(codegen, on, Variant::OP_POSITIVE, p_stack_level)) return -1;
} break;
case GDScriptParser::OperatorNode::OP_NOT: { case GDScriptParser::OperatorNode::OP_NOT: {
if (!_create_unary_operator(codegen, on, Variant::OP_NOT, p_stack_level)) return -1; if (!_create_unary_operator(codegen, on, Variant::OP_NOT, p_stack_level)) return -1;
} break; } break;

View File

@ -256,7 +256,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif #endif
uint32_t alloca_size = 0; uint32_t alloca_size = 0;
GDScript *_class; GDScript *script;
int ip = 0; int ip = 0;
int line = _initial_line; int line = _initial_line;
@ -267,7 +267,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
line = p_state->line; line = p_state->line;
ip = p_state->ip; ip = p_state->ip;
alloca_size = p_state->stack.size(); alloca_size = p_state->stack.size();
_class = p_state->_class; script = p_state->script.ptr();
p_instance = p_state->instance; p_instance = p_state->instance;
defarg = p_state->defarg; defarg = p_state->defarg;
self = p_state->self; self = p_state->self;
@ -331,9 +331,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else { } else {
self = p_instance->owner; self = p_instance->owner;
} }
_class = p_instance->script.ptr(); script = p_instance->script.ptr();
} else { } else {
_class = _script; script = _script;
} }
} }
@ -358,7 +358,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#define GET_VARIANT_PTR(m_v, m_code_ofs) \ #define GET_VARIANT_PTR(m_v, m_code_ofs) \
Variant *m_v; \ Variant *m_v; \
m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text); \ m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, stack, err_text); \
if (unlikely(!m_v)) \ if (unlikely(!m_v)) \
OPCODE_BREAK; OPCODE_BREAK;
@ -367,7 +367,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#define CHECK_SPACE(m_space) #define CHECK_SPACE(m_space)
#define GET_VARIANT_PTR(m_v, m_code_ofs) \ #define GET_VARIANT_PTR(m_v, m_code_ofs) \
Variant *m_v; \ Variant *m_v; \
m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text); m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, stack, err_text);
#endif #endif
@ -991,11 +991,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
gdfs->state.stack_size = _stack_size; gdfs->state.stack_size = _stack_size;
gdfs->state.self = self; gdfs->state.self = self;
gdfs->state.alloca_size = alloca_size; gdfs->state.alloca_size = alloca_size;
gdfs->state._class = _class; gdfs->state.script = Ref<GDScript>(_script);
gdfs->state.ip = ip + ipofs; gdfs->state.ip = ip + ipofs;
gdfs->state.line = line; gdfs->state.line = line;
gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : 0; gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : 0;
gdfs->state.script_id = _class->get_instance_id();
//gdfs->state.result_pos=ip+ipofs-1; //gdfs->state.result_pos=ip+ipofs-1;
gdfs->state.defarg = defarg; gdfs->state.defarg = defarg;
gdfs->state.instance = p_instance; gdfs->state.instance = p_instance;
@ -1278,8 +1277,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
String err_file; String err_file;
if (p_instance) if (p_instance)
err_file = p_instance->script->path; err_file = p_instance->script->path;
else if (_class) else if (script)
err_file = _class->path; err_file = script->path;
if (err_file == "") if (err_file == "")
err_file = "<built-in>"; err_file = "<built-in>";
String err_func = name; String err_func = name;
@ -1484,17 +1483,14 @@ GDScriptFunction::~GDScriptFunction() {
Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
#ifdef DEBUG_ENABLED
if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) { if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
#ifdef DEBUG_ENABLED
ERR_EXPLAIN("Resumed after yield, but class instance is gone"); ERR_EXPLAIN("Resumed after yield, but class instance is gone");
ERR_FAIL_V(Variant()); ERR_FAIL_V(Variant());
} #else
return Variant();
if (state.script_id && !ObjectDB::get_instance(state.script_id)) {
ERR_EXPLAIN("Resumed after yield, but script is gone");
ERR_FAIL_V(Variant());
}
#endif #endif
}
Variant arg; Variant arg;
r_error.error = Variant::CallError::CALL_OK; r_error.error = Variant::CallError::CALL_OK;
@ -1537,7 +1533,7 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar
GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret); GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret);
if (gdfs && gdfs->function == function) { if (gdfs && gdfs->function == function) {
completed = false; completed = false;
gdfs->previous_state = Ref<GDScriptFunctionState>(this); gdfs->first_state = first_state.is_valid() ? first_state : Ref<GDScriptFunctionState>(this);
} }
} }
@ -1545,10 +1541,10 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar
state.result = Variant(); state.result = Variant();
if (completed) { if (completed) {
GDScriptFunctionState *state = this; if (first_state.is_valid()) {
while (state != NULL) { first_state->emit_signal("completed", ret);
state->emit_signal("completed", ret); } else {
state = *(state->previous_state); emit_signal("completed", ret);
} }
} }
@ -1564,9 +1560,6 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
//class instance gone? //class instance gone?
if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) if (state.instance_id && !ObjectDB::get_instance(state.instance_id))
return false; return false;
//script gone?
if (state.script_id && !ObjectDB::get_instance(state.script_id))
return false;
} }
return true; return true;
@ -1575,17 +1568,14 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
Variant GDScriptFunctionState::resume(const Variant &p_arg) { Variant GDScriptFunctionState::resume(const Variant &p_arg) {
ERR_FAIL_COND_V(!function, Variant()); ERR_FAIL_COND_V(!function, Variant());
#ifdef DEBUG_ENABLED
if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) { if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
#ifdef DEBUG_ENABLED
ERR_EXPLAIN("Resumed after yield, but class instance is gone"); ERR_EXPLAIN("Resumed after yield, but class instance is gone");
ERR_FAIL_V(Variant()); ERR_FAIL_V(Variant());
} #else
return Variant();
if (state.script_id && !ObjectDB::get_instance(state.script_id)) {
ERR_EXPLAIN("Resumed after yield, but script is gone");
ERR_FAIL_V(Variant());
}
#endif #endif
}
state.result = p_arg; state.result = p_arg;
Variant::CallError err; Variant::CallError err;
@ -1599,7 +1589,7 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret); GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret);
if (gdfs && gdfs->function == function) { if (gdfs && gdfs->function == function) {
completed = false; completed = false;
gdfs->previous_state = Ref<GDScriptFunctionState>(this); gdfs->first_state = first_state.is_valid() ? first_state : Ref<GDScriptFunctionState>(this);
} }
} }
@ -1607,10 +1597,10 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
state.result = Variant(); state.result = Variant();
if (completed) { if (completed) {
GDScriptFunctionState *state = this; if (first_state.is_valid()) {
while (state != NULL) { first_state->emit_signal("completed", ret);
state->emit_signal("completed", ret); } else {
state = *(state->previous_state); emit_signal("completed", ret);
} }
} }

View File

@ -174,15 +174,13 @@ private:
public: public:
struct CallState { struct CallState {
ObjectID instance_id; //by debug only ObjectID instance_id;
ObjectID script_id;
GDScriptInstance *instance; GDScriptInstance *instance;
Vector<uint8_t> stack; Vector<uint8_t> stack;
int stack_size; int stack_size;
Variant self; Variant self;
uint32_t alloca_size; uint32_t alloca_size;
GDScript *_class; Ref<GDScript> script;
int ip; int ip;
int line; int line;
int defarg; int defarg;
@ -234,7 +232,7 @@ class GDScriptFunctionState : public Reference {
GDScriptFunction *function; GDScriptFunction *function;
GDScriptFunction::CallState state; GDScriptFunction::CallState state;
Variant _signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error); Variant _signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
Ref<GDScriptFunctionState> previous_state; Ref<GDScriptFunctionState> first_state;
protected: protected:
static void _bind_methods(); static void _bind_methods();

View File

@ -82,6 +82,7 @@ def configure(env):
mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0'] mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0']
if env['platform'] == 'windows': if env['platform'] == 'windows':
mono_root = ''
if bits == '32': if bits == '32':
if os.getenv('MONO32_PREFIX'): if os.getenv('MONO32_PREFIX'):
mono_root = os.getenv('MONO32_PREFIX') mono_root = os.getenv('MONO32_PREFIX')
@ -263,11 +264,13 @@ def pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext):
def pkgconfig_try_find_mono_version(): def pkgconfig_try_find_mono_version():
from compat import decode_utf8
lines = subprocess.check_output(['pkg-config', 'monosgen-2', '--modversion']).splitlines() lines = subprocess.check_output(['pkg-config', 'monosgen-2', '--modversion']).splitlines()
greater_version = None greater_version = None
for line in lines: for line in lines:
try: try:
version = LooseVersion(line) version = LooseVersion(decode_utf8(line))
if greater_version is None or version > greater_version: if greater_version is None or version > greater_version:
greater_version = version greater_version = version
except ValueError: except ValueError:

View File

@ -40,7 +40,7 @@ def _reg_open_key_bits(key, subkey, bits):
def _find_mono_in_reg(subkey, bits): def _find_mono_in_reg(subkey, bits):
try: try:
with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey: with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
value, regtype = winreg.QueryValueEx(hKey, 'SdkInstallRoot') value = winreg.QueryValueEx(hKey, 'SdkInstallRoot')[0]
return value return value
except (WindowsError, OSError): except (WindowsError, OSError):
return None return None
@ -49,7 +49,7 @@ def _find_mono_in_reg(subkey, bits):
def _find_mono_in_reg_old(subkey, bits): def _find_mono_in_reg_old(subkey, bits):
try: try:
with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey: with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
default_clr, regtype = winreg.QueryValueEx(hKey, 'DefaultCLR') default_clr = winreg.QueryValueEx(hKey, 'DefaultCLR')[0]
if default_clr: if default_clr:
return _find_mono_in_reg(subkey + '\\' + default_clr, bits) return _find_mono_in_reg(subkey + '\\' + default_clr, bits)
return None return None
@ -91,7 +91,13 @@ def find_msbuild_tools_path_reg():
if not val: if not val:
raise ValueError('Value of `installationPath` entry is empty') raise ValueError('Value of `installationPath` entry is empty')
return os.path.join(val, "MSBuild\\15.0\\Bin") # Since VS2019, the directory is simply named "Current"
msbuild_dir = os.path.join(val, 'MSBuild\\Current\\Bin')
if os.path.isdir(msbuild_dir):
return msbuild_dir
# Directory name "15.0" is used in VS 2017
return os.path.join(val, 'MSBuild\\15.0\\Bin')
raise ValueError('Cannot find `installationPath` entry') raise ValueError('Cannot find `installationPath` entry')
except ValueError as e: except ValueError as e:
@ -106,7 +112,7 @@ def find_msbuild_tools_path_reg():
try: try:
subkey = r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0' subkey = r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0'
with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey: with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
value, regtype = winreg.QueryValueEx(hKey, 'MSBuildToolsPath') value = winreg.QueryValueEx(hKey, 'MSBuildToolsPath')[0]
return value return value
except (WindowsError, OSError): except (WindowsError, OSError):
return '' return ''

View File

@ -29,6 +29,7 @@
/*************************************************************************/ /*************************************************************************/
#include "mono_reg_utils.h" #include "mono_reg_utils.h"
#include "core/os/dir_access.h"
#ifdef WINDOWS_ENABLED #ifdef WINDOWS_ENABLED
@ -202,6 +203,13 @@ String find_msbuild_tools_path() {
val += "\\"; val += "\\";
} }
// Since VS2019, the directory is simply named "Current"
String msbuild_dir = val + "MSBuild\\Current\\Bin";
if (DirAccess::exists(msbuild_dir)) {
return msbuild_dir;
}
// Directory name "15.0" is used in VS 2017
return val + "MSBuild\\15.0\\Bin"; return val + "MSBuild\\15.0\\Bin";
} }
} }

View File

@ -69,7 +69,7 @@ struct ThreadLocalStorage::Impl {
#define _CALLBACK_FUNC_ #define _CALLBACK_FUNC_
#endif #endif
Impl(void _CALLBACK_FUNC_ (*p_destr_callback_func)(void *)) { Impl(void (_CALLBACK_FUNC_ *p_destr_callback_func)(void *)) {
#ifdef WINDOWS_ENABLED #ifdef WINDOWS_ENABLED
dwFlsIndex = FlsAlloc(p_destr_callback_func); dwFlsIndex = FlsAlloc(p_destr_callback_func);
ERR_FAIL_COND(dwFlsIndex == FLS_OUT_OF_INDEXES); ERR_FAIL_COND(dwFlsIndex == FLS_OUT_OF_INDEXES);
@ -95,7 +95,7 @@ void ThreadLocalStorage::set_value(void *p_value) const {
pimpl->set_value(p_value); pimpl->set_value(p_value);
} }
void ThreadLocalStorage::alloc(void _CALLBACK_FUNC_ (*p_destr_callback)(void *)) { void ThreadLocalStorage::alloc(void (_CALLBACK_FUNC_ *p_destr_callback)(void *)) {
pimpl = memnew(ThreadLocalStorage::Impl(p_destr_callback)); pimpl = memnew(ThreadLocalStorage::Impl(p_destr_callback));
} }

View File

@ -76,7 +76,7 @@ struct ThreadLocalStorage {
void *get_value() const; void *get_value() const;
void set_value(void *p_value) const; void set_value(void *p_value) const;
void alloc(void _CALLBACK_FUNC_ (*p_dest_callback)(void *)); void alloc(void (_CALLBACK_FUNC_ *p_dest_callback)(void *));
void free(); void free();
private: private:

View File

@ -178,13 +178,17 @@ void RegEx::clear() {
if (sizeof(CharType) == 2) { if (sizeof(CharType) == 2) {
if (code) if (code) {
pcre2_code_free_16((pcre2_code_16 *)code); pcre2_code_free_16((pcre2_code_16 *)code);
code = NULL;
}
} else { } else {
if (code) if (code) {
pcre2_code_free_32((pcre2_code_32 *)code); pcre2_code_free_32((pcre2_code_32 *)code);
code = NULL;
}
} }
} }

View File

@ -81,6 +81,7 @@ void image_decompress_squish(Image *p_image) {
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
} }
#ifdef TOOLS_ENABLED
void image_compress_squish(Image *p_image, Image::CompressSource p_source) { void image_compress_squish(Image *p_image, Image::CompressSource p_source) {
if (p_image->get_format() >= Image::FORMAT_DXT1) if (p_image->get_format() >= Image::FORMAT_DXT1)
@ -176,3 +177,4 @@ void image_compress_squish(Image *p_image, Image::CompressSource p_source) {
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
} }
} }
#endif

View File

@ -33,7 +33,9 @@
#include "image.h" #include "image.h"
#ifdef TOOLS_ENABLED
void image_compress_squish(Image *p_image, Image::CompressSource p_source); void image_compress_squish(Image *p_image, Image::CompressSource p_source);
#endif
void image_decompress_squish(Image *p_image); void image_decompress_squish(Image *p_image);
#endif // IMAGE_COMPRESS_SQUISH_H #endif // IMAGE_COMPRESS_SQUISH_H

View File

@ -29,17 +29,14 @@
/*************************************************************************/ /*************************************************************************/
#include "register_types.h" #include "register_types.h"
#ifdef TOOLS_ENABLED
#include "image_compress_squish.h" #include "image_compress_squish.h"
void register_squish_types() { void register_squish_types() {
#ifdef TOOLS_ENABLED
Image::set_compress_bc_func(image_compress_squish); Image::set_compress_bc_func(image_compress_squish);
#endif
Image::_image_decompress_bc = image_decompress_squish; Image::_image_decompress_bc = image_decompress_squish;
} }
void unregister_squish_types() {} void unregister_squish_types() {}
#endif

View File

@ -28,7 +28,5 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#ifdef TOOLS_ENABLED
void register_squish_types(); void register_squish_types();
void unregister_squish_types(); void unregister_squish_types();
#endif

View File

@ -110,7 +110,12 @@ Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const PoolVector<uint8_t
float upscale = upsample ? 2.0 : 1.0; float upscale = upsample ? 2.0 : 1.0;
int w = (int)(svg_image->width * p_scale * upscale); int w = (int)(svg_image->width * p_scale * upscale);
ERR_EXPLAIN(vformat("Can't create image from SVG with scale %s, the resulting image size exceeds max width.", rtos(p_scale)));
ERR_FAIL_COND_V(w > Image::MAX_WIDTH, ERR_PARAMETER_RANGE_ERROR);
int h = (int)(svg_image->height * p_scale * upscale); int h = (int)(svg_image->height * p_scale * upscale);
ERR_EXPLAIN(vformat("Can't create image from SVG with scale %s, the resulting image size exceeds max height.", rtos(p_scale)));
ERR_FAIL_COND_V(h > Image::MAX_HEIGHT, ERR_PARAMETER_RANGE_ERROR);
PoolVector<uint8_t> dst_image; PoolVector<uint8_t> dst_image;
dst_image.resize(w * h * 4); dst_image.resize(w * h * 4);

View File

@ -250,8 +250,9 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
if (tga_header.image_width <= 0 || tga_header.image_height <= 0) if (tga_header.image_width <= 0 || tga_header.image_height <= 0)
err = FAILED; err = FAILED;
if (tga_header.pixel_depth != 8 && tga_header.pixel_depth != 24 && tga_header.pixel_depth != 32) if (!(tga_header.pixel_depth == 8 || tga_header.pixel_depth == 24 || tga_header.pixel_depth == 32)) {
err = FAILED; err = FAILED;
}
if (err == OK) { if (err == OK) {
f->seek(f->get_position() + tga_header.id_length); f->seek(f->get_position() + tga_header.id_length);

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ResourceImporterTheora" inherits="ResourceImporter" category="Core" version="3.0.7">
<brief_description>
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<demos>
</demos>
<methods>
</methods>
<constants>
</constants>
</class>

View File

@ -29,18 +29,22 @@
/*************************************************************************/ /*************************************************************************/
#include "register_types.h" #include "register_types.h"
#include "resource_importer_theora.h"
#include "video_stream_theora.h" #include "video_stream_theora.h"
static ResourceFormatLoaderTheora *resource_loader_theora = NULL;
void register_theora_types() { void register_theora_types() {
#ifdef TOOLS_ENABLED resource_loader_theora = memnew(ResourceFormatLoaderTheora);
Ref<ResourceImporterTheora> theora_import; ResourceLoader::add_resource_format_loader(resource_loader_theora, true);
theora_import.instance();
ResourceFormatImporter::get_singleton()->add_importer(theora_import);
#endif
ClassDB::register_class<VideoStreamTheora>(); ClassDB::register_class<VideoStreamTheora>();
} }
void unregister_theora_types() { void unregister_theora_types() {
if (resource_loader_theora) {
memdelete(resource_loader_theora);
}
} }

View File

@ -1,90 +0,0 @@
/*************************************************************************/
/* resource_importer_theora.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "resource_importer_theora.h"
#include "io/resource_saver.h"
#include "os/file_access.h"
#include "scene/resources/texture.h"
String ResourceImporterTheora::get_importer_name() const {
return "Theora";
}
String ResourceImporterTheora::get_visible_name() const {
return "Theora";
}
void ResourceImporterTheora::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("ogv");
p_extensions->push_back("ogm");
}
String ResourceImporterTheora::get_save_extension() const {
return "ogvstr";
}
String ResourceImporterTheora::get_resource_type() const {
return "VideoStreamTheora";
}
bool ResourceImporterTheora::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
return true;
}
int ResourceImporterTheora::get_preset_count() const {
return 0;
}
String ResourceImporterTheora::get_preset_name(int p_idx) const {
return String();
}
void ResourceImporterTheora::get_import_options(List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true));
}
Error ResourceImporterTheora::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) {
VideoStreamTheora *stream = memnew(VideoStreamTheora);
stream->set_file(p_source_file);
Ref<VideoStreamTheora> ogv_stream = Ref<VideoStreamTheora>(stream);
return ResourceSaver::save(p_save_path + ".ogvstr", ogv_stream);
}
ResourceImporterTheora::ResourceImporterTheora() {
}

View File

@ -1,58 +0,0 @@
/*************************************************************************/
/* resource_importer_theora.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RESOURCEIMPORTEROGGTHEORA_H
#define RESOURCEIMPORTEROGGTHEORA_H
#include "video_stream_theora.h"
#include "core/io/resource_import.h"
class ResourceImporterTheora : public ResourceImporter {
GDCLASS(ResourceImporterTheora, ResourceImporter)
public:
virtual String get_importer_name() const;
virtual String get_visible_name() const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual String get_save_extension() const;
virtual String get_resource_type() const;
virtual int get_preset_count() const;
virtual String get_preset_name(int p_idx) const;
virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const;
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL);
ResourceImporterTheora();
};
#endif // RESOURCEIMPORTEROGGTHEORA_H

View File

@ -730,3 +730,46 @@ void VideoStreamTheora::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_file", "get_file"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_file", "get_file");
} }
////////////
RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_original_path, Error *r_error) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
memdelete(f);
return RES();
}
VideoStreamTheora *stream = memnew(VideoStreamTheora);
stream->set_file(p_path);
Ref<VideoStreamTheora> ogv_stream = Ref<VideoStreamTheora>(stream);
if (r_error) {
*r_error = OK;
}
return ogv_stream;
}
void ResourceFormatLoaderTheora::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("ogv");
}
bool ResourceFormatLoaderTheora::handles_type(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "VideoStream");
}
String ResourceFormatLoaderTheora::get_resource_type(const String &p_path) const {
String el = p_path.get_extension().to_lower();
if (el == "ogv")
return "VideoStreamTheora";
return "";
}

View File

@ -163,7 +163,6 @@ public:
class VideoStreamTheora : public VideoStream { class VideoStreamTheora : public VideoStream {
GDCLASS(VideoStreamTheora, VideoStream); GDCLASS(VideoStreamTheora, VideoStream);
RES_BASE_EXTENSION("ogvstr");
String file; String file;
int audio_track; int audio_track;
@ -186,4 +185,12 @@ public:
VideoStreamTheora() { audio_track = 0; } VideoStreamTheora() { audio_track = 0; }
}; };
class ResourceFormatLoaderTheora : 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

View File

@ -131,7 +131,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
Image::Format format; Image::Format format;
int output_channels = 0; int output_channels = 0;
if (idxA > 0) { if (idxA != -1) {
imgdata.resize(exr_image.width * exr_image.height * 8); //RGBA16 imgdata.resize(exr_image.width * exr_image.height * 8); //RGBA16
format = Image::FORMAT_RGBAH; format = Image::FORMAT_RGBAH;
@ -187,7 +187,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
const float *b_channel_start = reinterpret_cast<const float *>(tile.images[idxB]); const float *b_channel_start = reinterpret_cast<const float *>(tile.images[idxB]);
const float *a_channel_start = NULL; const float *a_channel_start = NULL;
if (idxA > 0) { if (idxA != -1) {
a_channel_start = reinterpret_cast<const float *>(tile.images[idxA]); a_channel_start = reinterpret_cast<const float *>(tile.images[idxA]);
} }
@ -216,7 +216,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
*row_w++ = Math::make_half_float(color.g); *row_w++ = Math::make_half_float(color.g);
*row_w++ = Math::make_half_float(color.b); *row_w++ = Math::make_half_float(color.b);
if (idxA > 0) { if (idxA != -1) {
*row_w++ = Math::make_half_float(*a_channel++); *row_w++ = Math::make_half_float(*a_channel++);
} }
} }

View File

@ -1274,7 +1274,7 @@ void VisualScriptEditor::_on_nodes_duplicate() {
Ref<VisualScriptNode> node = script->get_node(edited_func, F->get()); Ref<VisualScriptNode> node = script->get_node(edited_func, F->get());
Ref<VisualScriptNode> dupe = node->duplicate(); Ref<VisualScriptNode> dupe = node->duplicate(true);
int new_id = idc++; int new_id = idc++;
to_select.insert(new_id); to_select.insert(new_id);
@ -2958,7 +2958,7 @@ void VisualScriptEditor::_menu_option(int p_what) {
return; return;
} }
if (node.is_valid()) { if (node.is_valid()) {
clipboard->nodes[id] = node->duplicate(); clipboard->nodes[id] = node->duplicate(true);
clipboard->nodes_positions[id] = script->get_node_position(edited_func, id); clipboard->nodes_positions[id] = script->get_node_position(edited_func, id);
} }
} }

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ResourceImporterWebm" inherits="ResourceImporter" category="Core" version="3.0.7">
<brief_description>
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<demos>
</demos>
<methods>
</methods>
<constants>
</constants>
</class>

View File

@ -38,7 +38,6 @@ libvpx_sources = [
"vp8/decoder/decodemv.c", "vp8/decoder/decodemv.c",
"vp8/decoder/detokenize.c", "vp8/decoder/detokenize.c",
"vp8/decoder/onyxd_if.c", "vp8/decoder/onyxd_if.c",
"vp8/decoder/threading.c",
"vp9/vp9_dx_iface.c", "vp9/vp9_dx_iface.c",
@ -102,6 +101,10 @@ libvpx_sources = [
"vpx_util/vpx_thread.c" "vpx_util/vpx_thread.c"
] ]
libvpx_sources_mt = [
"vp8/decoder/threading.c",
]
libvpx_sources_intrin_x86 = [ libvpx_sources_intrin_x86 = [
"vp8/common/x86/filter_x86.c", "vp8/common/x86/filter_x86.c",
"vp8/common/x86/loopfilter_x86.c", "vp8/common/x86/loopfilter_x86.c",
@ -231,6 +234,7 @@ libvpx_sources_arm_neon_gas_apple = [
] ]
libvpx_sources = [libvpx_dir + file for file in libvpx_sources] libvpx_sources = [libvpx_dir + file for file in libvpx_sources]
libvpx_sources_mt = [libvpx_dir + file for file in libvpx_sources_mt]
libvpx_sources_intrin_x86 = [libvpx_dir + file for file in libvpx_sources_intrin_x86] libvpx_sources_intrin_x86 = [libvpx_dir + file for file in libvpx_sources_intrin_x86]
libvpx_sources_intrin_x86_mmx = [libvpx_dir + file for file in libvpx_sources_intrin_x86_mmx] libvpx_sources_intrin_x86_mmx = [libvpx_dir + file for file in libvpx_sources_intrin_x86_mmx]
libvpx_sources_intrin_x86_sse2 = [libvpx_dir + file for file in libvpx_sources_intrin_x86_sse2] libvpx_sources_intrin_x86_sse2 = [libvpx_dir + file for file in libvpx_sources_intrin_x86_sse2]
@ -253,6 +257,8 @@ env_webm.Append(CPPPATH=[libvpx_dir])
env_libvpx = env.Clone() env_libvpx = env.Clone()
env_libvpx.Append(CPPPATH=[libvpx_dir]) env_libvpx.Append(CPPPATH=[libvpx_dir])
webm_multithread = env["platform"] != 'javascript'
cpu_bits = env["bits"] cpu_bits = env["bits"]
osx_fat = (env["platform"] == 'osx' and cpu_bits == 'fat') osx_fat = (env["platform"] == 'osx' and cpu_bits == 'fat')
webm_cpu_x86 = False webm_cpu_x86 = False
@ -348,6 +354,10 @@ if webm_simd_optimizations == False:
print("WebM SIMD optimizations are disabled. Check if your CPU architecture, CPU bits or platform are supported!") print("WebM SIMD optimizations are disabled. Check if your CPU architecture, CPU bits or platform are supported!")
env_libvpx.add_source_files(env.modules_sources, libvpx_sources) env_libvpx.add_source_files(env.modules_sources, libvpx_sources)
if webm_multithread:
env_libvpx.add_source_files(env.modules_sources, libvpx_sources_mt)
if webm_cpu_x86: if webm_cpu_x86:
is_clang_or_gcc = ('gcc' in env["CC"]) or ('clang' in env["CC"]) or ("OSXCROSS_ROOT" in os.environ) is_clang_or_gcc = ('gcc' in env["CC"]) or ('clang' in env["CC"]) or ("OSXCROSS_ROOT" in os.environ)

View File

@ -29,18 +29,22 @@
/*************************************************************************/ /*************************************************************************/
#include "register_types.h" #include "register_types.h"
#include "resource_importer_webm.h"
#include "video_stream_webm.h" #include "video_stream_webm.h"
static ResourceFormatLoaderWebm *resource_loader_webm = NULL;
void register_webm_types() { void register_webm_types() {
#ifdef TOOLS_ENABLED resource_loader_webm = memnew(ResourceFormatLoaderWebm);
Ref<ResourceImporterWebm> webm_import; ResourceLoader::add_resource_format_loader(resource_loader_webm, true);
webm_import.instance();
ResourceFormatImporter::get_singleton()->add_importer(webm_import);
#endif
ClassDB::register_class<VideoStreamWebm>(); ClassDB::register_class<VideoStreamWebm>();
} }
void unregister_webm_types() { void unregister_webm_types() {
if (resource_loader_webm) {
memdelete(resource_loader_webm);
}
} }

View File

@ -1,96 +0,0 @@
/*************************************************************************/
/* resource_importer_webm.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "resource_importer_webm.h"
#include "io/resource_saver.h"
#include "os/file_access.h"
#include "scene/resources/texture.h"
#include "video_stream_webm.h"
String ResourceImporterWebm::get_importer_name() const {
return "Webm";
}
String ResourceImporterWebm::get_visible_name() const {
return "Webm";
}
void ResourceImporterWebm::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("webm");
}
String ResourceImporterWebm::get_save_extension() const {
return "webmstr";
}
String ResourceImporterWebm::get_resource_type() const {
return "VideoStreamWebm";
}
bool ResourceImporterWebm::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
return true;
}
int ResourceImporterWebm::get_preset_count() const {
return 0;
}
String ResourceImporterWebm::get_preset_name(int p_idx) const {
return String();
}
void ResourceImporterWebm::get_import_options(List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true));
}
Error ResourceImporterWebm::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) {
FileAccess *f = FileAccess::open(p_source_file, FileAccess::READ);
if (!f) {
ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
}
memdelete(f);
VideoStreamWebm *stream = memnew(VideoStreamWebm);
stream->set_file(p_source_file);
Ref<VideoStreamWebm> webm_stream = Ref<VideoStreamWebm>(stream);
return ResourceSaver::save(p_save_path + ".webmstr", webm_stream);
}
ResourceImporterWebm::ResourceImporterWebm() {
}

View File

@ -1,56 +0,0 @@
/*************************************************************************/
/* resource_importer_webm.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RESOURCEIMPORTERWEBM_H
#define RESOURCEIMPORTERWEBM_H
#include "io/resource_import.h"
class ResourceImporterWebm : public ResourceImporter {
GDCLASS(ResourceImporterWebm, ResourceImporter)
public:
virtual String get_importer_name() const;
virtual String get_visible_name() const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual String get_save_extension() const;
virtual String get_resource_type() const;
virtual int get_preset_count() const;
virtual String get_preset_name(int p_idx) const;
virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const;
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL);
ResourceImporterWebm();
};
#endif // RESOURCEIMPORTERWEBM_H

View File

@ -443,3 +443,46 @@ void VideoStreamWebm::set_audio_track(int p_track) {
audio_track = p_track; audio_track = p_track;
} }
////////////
RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_original_path, Error *r_error) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
memdelete(f);
return RES();
}
VideoStreamWebm *stream = memnew(VideoStreamWebm);
stream->set_file(p_path);
Ref<VideoStreamWebm> webm_stream = Ref<VideoStreamWebm>(stream);
if (r_error) {
*r_error = OK;
}
return webm_stream;
}
void ResourceFormatLoaderWebm::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("webm");
}
bool ResourceFormatLoaderWebm::handles_type(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "VideoStream");
}
String ResourceFormatLoaderWebm::get_resource_type(const String &p_path) const {
String el = p_path.get_extension().to_lower();
if (el == "webm")
return "VideoStreamWebm";
return "";
}

View File

@ -109,7 +109,6 @@ private:
class VideoStreamWebm : public VideoStream { class VideoStreamWebm : public VideoStream {
GDCLASS(VideoStreamWebm, VideoStream); GDCLASS(VideoStreamWebm, VideoStream);
RES_BASE_EXTENSION("webmstr");
String file; String file;
int audio_track; int audio_track;
@ -127,4 +126,12 @@ public:
virtual void set_audio_track(int p_track); virtual void set_audio_track(int p_track);
}; };
class ResourceFormatLoaderWebm : 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 // VIDEO_STREAM_WEBM_H #endif // VIDEO_STREAM_WEBM_H

View File

@ -14,9 +14,9 @@ apply plugin: 'com.android.application'
allprojects { allprojects {
repositories { repositories {
jcenter()
mavenCentral() mavenCentral()
google() google()
jcenter()
$$GRADLE_REPOSITORY_URLS$$ $$GRADLE_REPOSITORY_URLS$$
} }
} }

View File

@ -150,7 +150,7 @@ def configure(env):
if (env["target"].startswith("release")): if (env["target"].startswith("release")):
env.Append(LINKFLAGS=['-O2']) env.Append(LINKFLAGS=['-O2'])
env.Append(CPPFLAGS=['-O2', '-DNDEBUG', '-ffast-math', '-funsafe-math-optimizations', '-fomit-frame-pointer']) env.Append(CPPFLAGS=['-O2', '-DNDEBUG', '-fomit-frame-pointer'])
if (can_vectorize): if (can_vectorize):
env.Append(CPPFLAGS=['-ftree-vectorize']) env.Append(CPPFLAGS=['-ftree-vectorize'])
if (env["target"] == "release_debug"): if (env["target"] == "release_debug"):

View File

@ -228,7 +228,7 @@ class EditorExportAndroid : public EditorExportPlatform {
}; };
Vector<Device> devices; Vector<Device> devices;
bool devices_changed; volatile bool devices_changed;
Mutex *device_lock; Mutex *device_lock;
Thread *device_thread; Thread *device_thread;
volatile bool quit_request; volatile bool quit_request;
@ -345,8 +345,7 @@ class EditorExportAndroid : public EditorExportPlatform {
} }
d.name = vendor + " " + device; d.name = vendor + " " + device;
//print_line("name: "+d.name); if (device == String()) continue;
//print_line("description: "+d.description);
} }
ndevices.push_back(d); ndevices.push_back(d);
@ -1156,7 +1155,10 @@ public:
virtual bool poll_devices() { virtual bool poll_devices() {
bool dc = devices_changed; bool dc = devices_changed;
devices_changed = false; if (dc) {
// don't clear unless we're reporting true, to avoid race
devices_changed = false;
}
return dc; return dc;
} }
@ -1859,9 +1861,9 @@ public:
run_icon->create_from_image(img); run_icon->create_from_image(img);
device_lock = Mutex::create(); device_lock = Mutex::create();
device_thread = Thread::create(_device_poll_thread, this);
devices_changed = true; devices_changed = true;
quit_request = false; quit_request = false;
device_thread = Thread::create(_device_poll_thread, this);
} }
~EditorExportAndroid() { ~EditorExportAndroid() {

View File

@ -202,48 +202,65 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
return i; return i;
} }
} }
onInputDeviceAdded(device_id);
return joy_devices.size() - 1; return -1;
} }
@Override @Override
public void onInputDeviceAdded(int deviceId) { public void onInputDeviceAdded(int deviceId) {
joystick joy = new joystick(); int id = find_joy_device(deviceId);
joy.device_id = deviceId;
final int id = joy_devices.size(); // Check if the device has not been already added
InputDevice device = mInputManager.getInputDevice(deviceId); if (id < 0) {
final String name = device.getName(); InputDevice device = mInputManager.getInputDevice(deviceId);
joy.name = device.getName();
joy.axes = new ArrayList<InputDevice.MotionRange>(); id = joy_devices.size();
joy.hats = new ArrayList<InputDevice.MotionRange>();
List<InputDevice.MotionRange> ranges = device.getMotionRanges(); joystick joy = new joystick();
Collections.sort(ranges, new RangeComparator()); joy.device_id = deviceId;
for (InputDevice.MotionRange range : ranges) { joy.name = device.getName();
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) { joy.axes = new ArrayList<InputDevice.MotionRange>();
joy.hats.add(range); joy.hats = new ArrayList<InputDevice.MotionRange>();
} else {
joy.axes.add(range); List<InputDevice.MotionRange> ranges = device.getMotionRanges();
Collections.sort(ranges, new RangeComparator());
for (InputDevice.MotionRange range : ranges) {
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
joy.hats.add(range);
} else {
joy.axes.add(range);
}
} }
joy_devices.add(joy);
final int device_id = id;
final String name = joy.name;
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.joyconnectionchanged(device_id, true, name);
}
});
} }
joy_devices.add(joy);
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.joyconnectionchanged(id, true, name);
}
});
} }
@Override @Override
public void onInputDeviceRemoved(int deviceId) { public void onInputDeviceRemoved(int deviceId) {
final int id = find_joy_device(deviceId); final int device_id = find_joy_device(deviceId);
joy_devices.remove(id);
queueEvent(new Runnable() { // Check if the evice has not been already removed
@Override if (device_id > -1) {
public void run() { joy_devices.remove(device_id);
GodotLib.joyconnectionchanged(id, false, "");
} queueEvent(new Runnable() {
}); @Override
public void run() {
GodotLib.joyconnectionchanged(device_id, false, "");
}
});
}
} }
@Override @Override
@ -264,15 +281,18 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
if ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || (source & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD || (source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) { if ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || (source & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD || (source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) {
final int button = get_godot_button(keyCode); final int button = get_godot_button(keyCode);
final int device = find_joy_device(event.getDeviceId()); final int device_id = find_joy_device(event.getDeviceId());
queueEvent(new Runnable() { // Check if the device exists
@Override if (device_id > -1) {
public void run() { queueEvent(new Runnable() {
GodotLib.joybutton(device, button, false); @Override
} public void run() {
}); GodotLib.joybutton(device_id, button, false);
return true; }
});
return true;
}
} else { } else {
final int chr = event.getUnicodeChar(0); final int chr = event.getUnicodeChar(0);
queueEvent(new Runnable() { queueEvent(new Runnable() {
@ -282,6 +302,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
} }
}); });
}; };
return super.onKeyUp(keyCode, event); return super.onKeyUp(keyCode, event);
}; };
@ -306,18 +327,20 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
if (event.getRepeatCount() > 0) // ignore key echo if (event.getRepeatCount() > 0) // ignore key echo
return true; return true;
final int button = get_godot_button(keyCode); final int button = get_godot_button(keyCode);
final int device = find_joy_device(event.getDeviceId()); final int device_id = find_joy_device(event.getDeviceId());
//Log.e(TAG, String.format("joy button down! button %x, %d, device %d", keyCode, button, device));
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.joybutton(device, button, true);
}
});
return true;
// Check if the device exists
if (device_id > -1) {
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.joybutton(device_id, button, true);
}
});
return true;
}
} else { } else {
final int chr = event.getUnicodeChar(0); final int chr = event.getUnicodeChar(0);
queueEvent(new Runnable() { queueEvent(new Runnable() {
@ -327,6 +350,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
} }
}); });
}; };
return super.onKeyDown(keyCode, event); return super.onKeyDown(keyCode, event);
} }
@ -336,33 +360,35 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) { if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) {
final int device_id = find_joy_device(event.getDeviceId()); final int device_id = find_joy_device(event.getDeviceId());
joystick joy = joy_devices.get(device_id);
for (int i = 0; i < joy.axes.size(); i++) { // Check if the device exists
InputDevice.MotionRange range = joy.axes.get(i); if (device_id > -1) {
final float value = (event.getAxisValue(range.getAxis()) - range.getMin()) / range.getRange() * 2.0f - 1.0f; joystick joy = joy_devices.get(device_id);
//Log.e(TAG, String.format("axis event: %d, value %f", i, value));
final int idx = i;
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.joyaxis(device_id, idx, value);
}
});
}
for (int i = 0; i < joy.hats.size(); i += 2) { for (int i = 0; i < joy.axes.size(); i++) {
final int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis())); InputDevice.MotionRange range = joy.axes.get(i);
final int hatY = Math.round(event.getAxisValue(joy.hats.get(i + 1).getAxis())); final float value = (event.getAxisValue(range.getAxis()) - range.getMin()) / range.getRange() * 2.0f - 1.0f;
//Log.e(TAG, String.format("HAT EVENT %d, %d", hatX, hatY)); final int idx = i;
queueEvent(new Runnable() { queueEvent(new Runnable() {
@Override @Override
public void run() { public void run() {
GodotLib.joyhat(device_id, hatX, hatY); GodotLib.joyaxis(device_id, idx, value);
} }
}); });
}
for (int i = 0; i < joy.hats.size(); i += 2) {
final int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis()));
final int hatY = Math.round(event.getAxisValue(joy.hats.get(i + 1).getAxis()));
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.joyhat(device_id, hatX, hatY);
}
});
}
return true;
} }
return true;
}; };
return super.onGenericMotionEvent(event); return super.onGenericMotionEvent(event);

View File

@ -37,14 +37,14 @@ def configure(env):
## Build type ## Build type
if (env["target"] == "release"): if (env["target"] == "release"):
env.Prepend(CCFLAGS=['-O3', '-ffast-math']) env.Prepend(CCFLAGS=['-O3'])
if (env["debug_symbols"] == "yes"): if (env["debug_symbols"] == "yes"):
env.Prepend(CCFLAGS=['-g1']) env.Prepend(CCFLAGS=['-g1'])
if (env["debug_symbols"] == "full"): if (env["debug_symbols"] == "full"):
env.Prepend(CCFLAGS=['-g2']) env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "release_debug"): elif (env["target"] == "release_debug"):
env.Prepend(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED']) env.Prepend(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
if (env["debug_symbols"] == "yes"): if (env["debug_symbols"] == "yes"):
env.Prepend(CCFLAGS=['-g1']) env.Prepend(CCFLAGS=['-g1'])
if (env["debug_symbols"] == "full"): if (env["debug_symbols"] == "full"):

View File

@ -47,7 +47,7 @@ def configure(env):
if (env["target"].startswith("release")): if (env["target"].startswith("release")):
env.Append(CPPFLAGS=['-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1']) env.Append(CPPFLAGS=['-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1'])
env.Append(CPPFLAGS=['-O2', '-ftree-vectorize', '-fomit-frame-pointer', '-ffast-math', '-funsafe-math-optimizations']) env.Append(CPPFLAGS=['-O2', '-ftree-vectorize', '-fomit-frame-pointer'])
env.Append(LINKFLAGS=['-O2']) env.Append(LINKFLAGS=['-O2'])
if env["target"] == "release_debug": if env["target"] == "release_debug":

View File

@ -85,7 +85,8 @@ Rect2 _get_ios_window_safe_area(float p_window_width, float p_window_height) {
} }
ERR_FAIL_COND_V(insets.left < 0 || insets.top < 0 || insets.right < 0 || insets.bottom < 0, ERR_FAIL_COND_V(insets.left < 0 || insets.top < 0 || insets.right < 0 || insets.bottom < 0,
Rect2(0, 0, p_window_width, p_window_height)); Rect2(0, 0, p_window_width, p_window_height));
return Rect2(insets.left, insets.top, p_window_width - insets.right - insets.left, p_window_height - insets.bottom - insets.top); UIEdgeInsets window_insets = UIEdgeInsetsMake(_points_to_pixels(insets.top), _points_to_pixels(insets.left), _points_to_pixels(insets.bottom), _points_to_pixels(insets.right));
return Rect2(window_insets.left, window_insets.top, p_window_width - window_insets.right - window_insets.left, p_window_height - window_insets.bottom - window_insets.top);
} }
bool _play_video(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { bool _play_video(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) {

Some files were not shown because too many files have changed in this diff Show More