Conflicts:
	demos/2d/polygon_path_finder_demo/.fscache
This commit is contained in:
Carl Olsson 2015-02-11 21:15:49 +10:00
commit 573ae5dd92
35 changed files with 1384 additions and 194 deletions

3
.gitignore vendored
View file

@ -19,6 +19,9 @@ tools/editor/register_exporters.cpp
tools/editor/doc_data_compressed.h
tools/editor/editor_icons.cpp
-fpic
.fscache
make.bat
log.txt
# Android specific
platform/android/java/local.properties

View file

@ -487,7 +487,7 @@ struct test_27_data {
bool test_27() {
OS::get_singleton()->print("\n\nTest 26: begins_with\n");
OS::get_singleton()->print("\n\nTest 27: begins_with\n");
test_27_data tc[] = {
{"res://foobar", "res://", true},
{"res", "res://", false},
@ -504,11 +504,348 @@ bool test_27() {
}
if (!state) {
OS::get_singleton()->print("\n\t Failure on:\n\t\tstring: ", tc[i].data, "\n\t\tbegin: ", tc[i].begin, "\n\t\texpected: ", tc[i].expected ? "true" : "false", "\n");
break;
}
};
return state;
};
bool test_28() {
OS::get_singleton()->print("\n\nTest 28: sprintf\n");
bool success, state = true;
char output_format[] = "\tTest:\t%ls => %ls (%s)\n";
String format, output;
Array args;
// %%
format = "fish %% frog";
args.clear();
output = format.sprintf(args);
success = (output == String("fish % frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
//////// INTS
// Int
format = "fish %d frog";
args.clear();
args.push_back(5);
output = format.sprintf(args);
success = (output == String("fish 5 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Int left padded with zeroes.
format = "fish %05d frog";
args.clear();
args.push_back(5);
output = format.sprintf(args);
success = (output == String("fish 00005 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Int left padded with spaces.
format = "fish %5d frog";
args.clear();
args.push_back(5);
output = format.sprintf(args);
success = (output == String("fish 5 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Int right padded with spaces.
format = "fish %-5d frog";
args.clear();
args.push_back(5);
output = format.sprintf(args);
success = (output == String("fish 5 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Int with sign (positive).
format = "fish %+d frog";
args.clear();
args.push_back(5);
output = format.sprintf(args);
success = (output == String("fish +5 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Negative int.
format = "fish %d frog";
args.clear();
args.push_back(-5);
output = format.sprintf(args);
success = (output == String("fish -5 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Hex (lower)
format = "fish %x frog";
args.clear();
args.push_back(45);
output = format.sprintf(args);
success = (output == String("fish 2d frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Hex (upper)
format = "fish %X frog";
args.clear();
args.push_back(45);
output = format.sprintf(args);
success = (output == String("fish 2D frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Octal
format = "fish %o frog";
args.clear();
args.push_back(99);
output = format.sprintf(args);
success = (output == String("fish 143 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
////// REALS
// Real
format = "fish %f frog";
args.clear();
args.push_back(99.99);
output = format.sprintf(args);
success = (output == String("fish 99.990000 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Real left-padded
format = "fish %11f frog";
args.clear();
args.push_back(99.99);
output = format.sprintf(args);
success = (output == String("fish 99.990000 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Real right-padded
format = "fish %-11f frog";
args.clear();
args.push_back(99.99);
output = format.sprintf(args);
success = (output == String("fish 99.990000 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Real given int.
format = "fish %f frog";
args.clear();
args.push_back(99);
output = format.sprintf(args);
success = (output == String("fish 99.000000 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Real with sign (positive).
format = "fish %+f frog";
args.clear();
args.push_back(99.99);
output = format.sprintf(args);
success = (output == String("fish +99.990000 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Real with 1 decimals.
format = "fish %.1f frog";
args.clear();
args.push_back(99.99);
output = format.sprintf(args);
success = (output == String("fish 100.0 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Real with 12 decimals.
format = "fish %.12f frog";
args.clear();
args.push_back(99.99);
output = format.sprintf(args);
success = (output == String("fish 99.990000000000 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Real with no decimals.
format = "fish %.f frog";
args.clear();
args.push_back(99.99);
output = format.sprintf(args);
success = (output == String("fish 100 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
/////// Strings.
// String
format = "fish %s frog";
args.clear();
args.push_back("cheese");
output = format.sprintf(args);
success = (output == String("fish cheese frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// String left-padded
format = "fish %10s frog";
args.clear();
args.push_back("cheese");
output = format.sprintf(args);
success = (output == String("fish cheese frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// String right-padded
format = "fish %-10s frog";
args.clear();
args.push_back("cheese");
output = format.sprintf(args);
success = (output == String("fish cheese frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
///// Characters
// Character as string.
format = "fish %c frog";
args.clear();
args.push_back("A");
output = format.sprintf(args);
success = (output == String("fish A frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Character as int.
format = "fish %c frog";
args.clear();
args.push_back(65);
output = format.sprintf(args);
success = (output == String("fish A frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
///// Dynamic width
// String dynamic width
format = "fish %*s frog";
args.clear();
args.push_back(10);
args.push_back("cheese");
output = format.sprintf(args);
success = (output == String("fish cheese frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Int dynamic width
format = "fish %*d frog";
args.clear();
args.push_back(10);
args.push_back(99);
output = format.sprintf(args);
success = (output == String("fish 99 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Float dynamic width
format = "fish %*.*f frog";
args.clear();
args.push_back(10);
args.push_back(3);
args.push_back(99.99);
output = format.sprintf(args);
success = (output == String("fish 99.990 frog"));
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
///// Errors
// More formats than arguments.
format = "fish %s %s frog";
args.clear();
args.push_back("cheese");
output = format.sprintf(args);
success = (output == "");
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// More arguments than formats.
format = "fish %s frog";
args.clear();
args.push_back("hello");
args.push_back("cheese");
output = format.sprintf(args);
success = (output == "");
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Incomplete format.
format = "fish %10";
args.clear();
args.push_back("cheese");
output = format.sprintf(args);
success = (output == "");
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Bad character in format string
format = "fish %&f frog";
args.clear();
args.push_back("cheese");
output = format.sprintf(args);
success = (output == "");
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Too many decimals.
format = "fish %2.2.2f frog";
args.clear();
args.push_back(99.99);
output = format.sprintf(args);
success = (output == "");
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// * not a number
format = "fish %*f frog";
args.clear();
args.push_back("cheese");
args.push_back(99.99);
output = format.sprintf(args);
success = (output == "");
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Character too long.
format = "fish %c frog";
args.clear();
args.push_back("sc");
output = format.sprintf(args);
success = (output == "");
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
// Character bad type.
format = "fish %c frog";
args.clear();
args.push_back(Array());
output = format.sprintf(args);
success = (output == "");
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
return state;
}
typedef bool (*TestFunc)(void);
TestFunc test_funcs[] = {
@ -540,6 +877,7 @@ TestFunc test_funcs[] = {
test_25,
test_26,
test_27,
test_28,
0
};

View file

@ -273,7 +273,7 @@ Error HTTPClient::poll(){
while(true) {
uint8_t byte;
int rec=0;
Error err = connection->get_partial_data(&byte,1,rec);
Error err = _get_http_data(&byte,1,rec);
if (err!=OK) {
close();
status=STATUS_CONNECTION_ERROR;
@ -417,7 +417,7 @@ ByteArray HTTPClient::read_response_body_chunk() {
//reading len
uint8_t b;
int rec=0;
err = connection->get_partial_data(&b,1,rec);
err = _get_http_data(&b,1,rec);
if (rec==0)
break;
@ -471,7 +471,7 @@ ByteArray HTTPClient::read_response_body_chunk() {
} else {
int rec=0;
err = connection->get_partial_data(&chunk[chunk.size()-chunk_left],chunk_left,rec);
err = _get_http_data(&chunk[chunk.size()-chunk_left],chunk_left,rec);
if (rec==0) {
break;
}
@ -502,18 +502,23 @@ ByteArray HTTPClient::read_response_body_chunk() {
}
} else {
int to_read = MIN(body_left,read_chunk_size);
ByteArray ret;
ret.resize(MAX(body_left,tmp_read.size()));
ret.resize(to_read);
ByteArray::Write w = ret.write();
int _offset = 0;
while (body_left > 0) {
ByteArray::Write r = tmp_read.write();
while (to_read > 0) {
int rec=0;
err = connection->get_partial_data(r.ptr(),MIN(body_left,tmp_read.size()),rec);
err = _get_http_data(w.ptr()+_offset,to_read,rec);
if (rec>0) {
copymem(w.ptr()+_offset,r.ptr(),rec);
body_left-=rec;
to_read-=rec;
_offset += rec;
} else {
if (to_read>0) //ended up reading less
ret.resize(_offset);
break;
}
}
if (body_left==0) {
@ -557,6 +562,20 @@ bool HTTPClient::is_blocking_mode_enabled() const{
return blocking;
}
Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received) {
if (blocking) {
Error err = connection->get_data(p_buffer,p_bytes);
if (err==OK)
r_received=p_bytes;
else
r_received=0;
return err;
} else {
return connection->get_partial_data(p_buffer,p_bytes,r_received);
}
}
void HTTPClient::_bind_methods() {
@ -574,6 +593,7 @@ void HTTPClient::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_response_headers_as_dictionary"),&HTTPClient::_get_response_headers_as_dictionary);
ObjectTypeDB::bind_method(_MD("get_response_body_length"),&HTTPClient::get_response_body_length);
ObjectTypeDB::bind_method(_MD("read_response_body_chunk"),&HTTPClient::read_response_body_chunk);
ObjectTypeDB::bind_method(_MD("set_read_chunk_size","bytes"),&HTTPClient::set_read_chunk_size);
ObjectTypeDB::bind_method(_MD("set_blocking_mode","enabled"),&HTTPClient::set_blocking_mode);
ObjectTypeDB::bind_method(_MD("is_blocking_mode_enabled"),&HTTPClient::is_blocking_mode_enabled);
@ -664,6 +684,11 @@ void HTTPClient::_bind_methods() {
}
void HTTPClient::set_read_chunk_size(int p_size) {
ERR_FAIL_COND(p_size<256 || p_size>(1<<24));
read_chunk_size=p_size;
}
HTTPClient::HTTPClient(){
tcp_connection = StreamPeerTCP::create_ref();
@ -677,7 +702,7 @@ HTTPClient::HTTPClient(){
response_num=0;
ssl=false;
blocking=false;
tmp_read.resize(4096);
read_chunk_size=4096;
}
HTTPClient::~HTTPClient(){

View file

@ -157,7 +157,10 @@ private:
static void _bind_methods();
StringArray _get_response_headers();
Dictionary _get_response_headers_as_dictionary();
ByteArray tmp_read;
int read_chunk_size;
Error _get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received);
public:
@ -185,6 +188,7 @@ public:
void set_blocking_mode(bool p_enable); //useful mostly if running in a thread
bool is_blocking_mode_enabled() const;
void set_read_chunk_size(int p_size);
Error poll();

View file

@ -130,7 +130,7 @@ void ResourceImportMetadata::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_editor","name"),&ResourceImportMetadata::set_editor);
ObjectTypeDB::bind_method(_MD("get_editor"),&ResourceImportMetadata::get_editor);
ObjectTypeDB::bind_method(_MD("add_source","path","md5"),&ResourceImportMetadata::add_source);
ObjectTypeDB::bind_method(_MD("add_source","path","md5"),&ResourceImportMetadata::add_source, "");
ObjectTypeDB::bind_method(_MD("get_source_path","idx"),&ResourceImportMetadata::get_source_path);
ObjectTypeDB::bind_method(_MD("get_source_md5","idx"),&ResourceImportMetadata::get_source_md5);
ObjectTypeDB::bind_method(_MD("remove_source","idx"),&ResourceImportMetadata::remove_source);

View file

@ -34,6 +34,7 @@
#include "io/md5.h"
#include "ucaps.h"
#include "color.h"
#include "variant.h"
#define MAX_DIGITS 6
#define UPPERCASE(m_c) (((m_c)>='a' && (m_c)<='z')?((m_c)-('a'-'A')):(m_c))
#define LOWERCASE(m_c) (((m_c)>='A' && (m_c)<='Z')?((m_c)+('a'-'A')):(m_c))
@ -981,7 +982,7 @@ String String::num(double p_num,int p_decimals) {
}
String String::num_int64(int64_t p_num) {
String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
bool sign=p_num<0;
int64_t num=ABS(p_num);
@ -990,7 +991,7 @@ String String::num_int64(int64_t p_num) {
int chars=0;
do {
n/=10;
n/=base;
chars++;
} while(n);
@ -1002,8 +1003,15 @@ String String::num_int64(int64_t p_num) {
c[chars]=0;
n=num;
do {
c[--chars]='0'+(n%10);
n/=10;
int mod = n%base;
if (mod >= 10) {
char a = (capitalize_hex ? 'A' : 'a');
c[--chars]=a+(mod - 10);
} else {
c[--chars]='0'+mod;
}
n/=base;
} while(n);
if (sign)
@ -3518,4 +3526,284 @@ String rtoss(double p_val) {
return String::num_scientific(p_val);
}
// Right-pad with a character.
String String::rpad(int min_length, const String& character) const {
String s = *this;
int padding = min_length - s.length();
if (padding > 0) {
for (int i = 0; i < padding; i++) s = s + character;
}
return s;
}
// Left-pad with a character.
String String::lpad(int min_length, const String& character) const {
String s = *this;
int padding = min_length - s.length();
if (padding > 0) {
for (int i = 0; i < padding; i++) s = character + s;
}
return s;
}
// sprintf is implemented in GDScript via:
// "fish %s pie" % "frog"
// "fish %s %d pie" % ["frog", 12]
String String::sprintf(const Array& values) const {
String formatted;
CharType* self = (CharType*)c_str();
int num_items = values.size();
bool in_format = false;
int value_index = 0;
int min_chars;
int min_decimals;
bool in_decimals;
bool pad_with_zeroes;
bool left_justified;
bool show_sign;
for (; *self; self++) {
const CharType c = *self;
if (in_format) { // We have % - lets see what else we get.
switch (c) {
case '%': { // Replace %% with %
formatted += chr(c);
in_format = false;
break;
}
case 'd': // Integer (signed)
case 'o': // Octal
case 'x': // Hexadecimal (lowercase)
case 'X': { // Hexadecimal (uppercase)
if (value_index >= values.size()) {
ERR_EXPLAIN("not enough arguments for format string");
ERR_FAIL_V("");
}
if (!values[value_index].is_num()) {
ERR_EXPLAIN("a number is required");
ERR_FAIL_V("");
}
int64_t value = values[value_index];
int base;
bool capitalize = false;
switch (c) {
case 'd': base = 10; break;
case 'o': base = 8; break;
case 'x': base = 16; break;
case 'X': base = 16; capitalize = true; break;
}
// Get basic number.
String str = String::num_int64(value, base, capitalize);
// Sign.
if (show_sign && value >= 0) {
str = str.insert(0, "+");
}
// Padding.
String pad_char = pad_with_zeroes ? String("0") : String(" ");
if (left_justified) {
str = str.rpad(min_chars, pad_char);
} else {
str = str.lpad(min_chars, pad_char);
}
formatted += str;
++value_index;
in_format = false;
break;
}
case 'f': { // Float
if (value_index >= values.size()) {
ERR_EXPLAIN("not enough arguments for format string");
ERR_FAIL_V("");
}
if (!values[value_index].is_num()) {
ERR_EXPLAIN("a number is required");
ERR_FAIL_V("");
}
double value = values[value_index];
String str = String::num(value, min_decimals);
// Pad decimals out.
str = str.pad_decimals(min_decimals);
// Show sign
if (show_sign && value >= 0) {
str = str.insert(0, "+");
}
// Padding
if (left_justified) {
str = str.rpad(min_chars);
} else {
str = str.lpad(min_chars);
}
formatted += str;
++value_index;
in_format = false;
break;
}
case 's': { // String
if (value_index >= values.size()) {
ERR_EXPLAIN("not enough arguments for format string");
ERR_FAIL_V("");
}
String str = values[value_index];
// Padding.
if (left_justified) {
str = str.rpad(min_chars);
} else {
str = str.lpad(min_chars);
}
formatted += str;
++value_index;
in_format = false;
break;
}
case 'c': {
if (value_index >= values.size()) {
ERR_EXPLAIN("not enough arguments for format string");
ERR_FAIL_V("");
}
// Convert to character.
String str;
if (values[value_index].is_num()) {
int value = values[value_index];
if (value < 0) {
ERR_EXPLAIN("unsigned byte integer is lower than maximum")
ERR_FAIL_V("");
} else if (value > 255) {
ERR_EXPLAIN("unsigned byte integer is greater than maximum")
ERR_FAIL_V("");
}
str = chr(values[value_index]);
} else if (values[value_index].get_type() == Variant::STRING) {
str = values[value_index];
if (str.length() != 1) {
ERR_EXPLAIN("%c requires number or single-character string");
ERR_FAIL_V("");
}
} else {
ERR_EXPLAIN("%c requires number or single-character string");
ERR_FAIL_V("");
}
// Padding.
if (left_justified) {
str = str.rpad(min_chars);
} else {
str = str.lpad(min_chars);
}
formatted += str;
++value_index;
in_format = false;
break;
}
case '-': { // Left justify
left_justified = true;
break;
}
case '+': { // Show + if positive.
show_sign = true;
break;
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
int n = c - '0';
if (in_decimals) {
min_decimals *= 10;
min_decimals += n;
} else {
if (c == '0' && min_chars == 0) {
pad_with_zeroes = true;
} else {
min_chars *= 10;
min_chars += n;
}
}
break;
}
case '.': { // Float separtor.
if (in_decimals) {
ERR_EXPLAIN("too many decimal points in format");
ERR_FAIL_V("");
}
in_decimals = true;
min_decimals = 0; // We want to add the value manually.
break;
}
case '*': { // Dyanmic width, based on value.
if (value_index >= values.size()) {
ERR_EXPLAIN("not enough arguments for format string");
ERR_FAIL_V("");
}
if (!values[value_index].is_num()) {
ERR_EXPLAIN("* wants number");
ERR_FAIL_V("");
}
int size = values[value_index];
if (in_decimals) {
min_decimals = size;
} else {
min_chars = size;
}
++value_index;
break;
}
default: {
ERR_EXPLAIN("unsupported format character");
ERR_FAIL_V("");
}
}
} else { // Not in format string.
switch (c) {
case '%':
in_format = true;
// Back to defaults:
min_chars = 0;
min_decimals = 6;
pad_with_zeroes = false;
left_justified = false;
show_sign = false;
in_decimals = false;
break;
default:
formatted += chr(c);
}
}
}
if (in_format) {
ERR_EXPLAIN("incomplete format");
ERR_FAIL_V("");
}
if (value_index != values.size()) {
ERR_EXPLAIN("not all arguments converted during string formatting");
ERR_FAIL_V("");
}
return formatted;
}

View file

@ -31,6 +31,7 @@
#include "typedefs.h"
#include "vector.h"
#include "array.h"
/**
@author red <red@killy>
@ -127,10 +128,13 @@ public:
String insert(int p_at_pos,String p_string) const;
String pad_decimals(int p_digits) const;
String pad_zeros(int p_digits) const;
String lpad(int min_length,const String& character=" ") const;
String rpad(int min_length,const String& character=" ") const;
String sprintf(const Array& values) const;
static String num(double p_num,int p_decimals=-1);
static String num_scientific(double p_num);
static String num_real(double p_num);
static String num_int64(int64_t p_num);
static String num_int64(int64_t p_num,int base=10,bool capitalize_hex=false);
static String chr(CharType p_char);
static String md5(const uint8_t *p_md5);
bool is_numeric() const;
@ -203,7 +207,7 @@ public:
String xml_unescape() const;
String c_escape() const;
String c_unescape() const;
String percent_encode() const;
String percent_decode() const;

View file

@ -736,6 +736,20 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
}
#endif
_RETURN( p_a._data._int % p_b._data._int );
} else if (p_a.type==STRING) {
const String *str=reinterpret_cast<const String*>(p_a._data._mem);
if (p_b.type==ARRAY) {
// e.g. "frog %s %d" % ["fish", 12]
const Array *arr=reinterpret_cast<const Array*>(p_b._data._mem);
_RETURN(str->sprintf(*arr));
} else {
// e.g. "frog %d" % 12
Array arr;
arr.push_back(p_b);
_RETURN(str->sprintf(arr));
}
}
r_valid=false;

View file

@ -1,33 +0,0 @@
::res://::1412302385
WWT-01.png::ImageTexture::1412126473::
WWT-02.png::ImageTexture::1412126474::
WWT-03.png::ImageTexture::1412126474::
WWT-04.png::ImageTexture::1412126474::
WWT-05.png::ImageTexture::1412126474::
WWT-06.png::ImageTexture::1412126474::
WWT-07.png::ImageTexture::1412126474::
WWT-08.png::ImageTexture::1412126474::
WWT-09.png::ImageTexture::1412126474::
WWT-10.png::ImageTexture::1412126474::
WWT-11.png::ImageTexture::1412126475::
WWT-12.png::ImageTexture::1412126475::
WWT-13.png::ImageTexture::1412126475::
WWT-14.png::ImageTexture::1412126475::
WWT-15.png::ImageTexture::1412126475::
WWT-16.png::ImageTexture::1412126475::
WWT-17.png::ImageTexture::1412126475::
WWT-18.png::ImageTexture::1412126475::
WWT-19.png::ImageTexture::1412126476::
WWT-20.png::ImageTexture::1412126476::
WWT-21.png::ImageTexture::1412126476::
WWT-22.png::ImageTexture::1412126476::
WWT-23.png::ImageTexture::1412126476::
WWT-24.png::ImageTexture::1412126476::
WWT-25.png::ImageTexture::1412126476::
WWT-26.png::ImageTexture::1412126476::
map.scn::PackedScene::1412127344::
tiles.scn::PackedScene::1412126994::
tileset.res::TileSet::1412127001::
troll.gd::GDScript::1412302377::
troll.png::ImageTexture::1412302385::
troll.scn::PackedScene::1412302380::

View file

@ -1,4 +0,0 @@
::res://::1421669411
icon.png::ImageTexture::1421499066::
new_scene_poly_with_holes.scn::PackedScene::1421499066::
polygonpathfinder.gd::GDScript::1421669411::

File diff suppressed because one or more lines are too long

View file

@ -4038,8 +4038,16 @@ void RasterizerGLES2::render_target_set_size(RID p_render_target,int p_width,int
glGenTextures(1, &rt->color);
glBindTexture(GL_TEXTURE_2D, rt->color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
if (rt->texture_ptr->flags&VS::TEXTURE_FLAG_FILTER) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
@ -5494,13 +5502,15 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
base = surf->array_local;
glBindBuffer(GL_ARRAY_BUFFER, 0);
bool can_copy_to_local=surf->local_stride * surf->array_len <= skinned_buffer_size;
if (p_morphs && surf->stride * surf->array_len > skinned_buffer_size)
can_copy_to_local=false;
if (!can_copy_to_local)
skeleton_valid=false;
/* compute morphs */
if (p_morphs && surf->morph_target_count && can_copy_to_local) {
@ -9584,9 +9594,6 @@ void RasterizerGLES2::init() {
//glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
skinned_buffer_size = GLOBAL_DEF("rasterizer/skinned_buffer_size",DEFAULT_SKINNED_BUFFER_SIZE);
skinned_buffer = memnew_arr( uint8_t, skinned_buffer_size );
glGenTextures(1, &white_tex);
unsigned char whitetexdata[8*8*3];
for(int i=0;i<8*8*3;i++) {
@ -9762,7 +9769,6 @@ void RasterizerGLES2::init() {
void RasterizerGLES2::finish() {
memdelete_arr(skinned_buffer);
}
int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) {
@ -10042,10 +10048,29 @@ RasterizerGLES2* RasterizerGLES2::get_singleton() {
return _singleton;
};
int RasterizerGLES2::RenderList::max_elements=RenderList::DEFAULT_MAX_ELEMENTS;
RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,bool p_default_fragment_lighting,bool p_use_reload_hooks) {
_singleton = this;
RenderList::max_elements=GLOBAL_DEF("rasterizer/max_render_elements",(int)RenderList::DEFAULT_MAX_ELEMENTS);
if (RenderList::max_elements>64000)
RenderList::max_elements=64000;
if (RenderList::max_elements<1024)
RenderList::max_elements=1024;
opaque_render_list.init();
alpha_render_list.init();
skinned_buffer_size = GLOBAL_DEF("rasterizer/skeleton_buffer_size_kb",DEFAULT_SKINNED_BUFFER_SIZE);
if (skinned_buffer_size<256)
skinned_buffer_size=256;
if (skinned_buffer_size>16384)
skinned_buffer_size=16384;
skinned_buffer_size*=1024;
skinned_buffer = memnew_arr( uint8_t, skinned_buffer_size );
keep_copies=p_keep_ram_copy;
use_reload_hooks=p_use_reload_hooks;
pack_arrays=p_compress_arrays;
@ -10089,6 +10114,7 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo
RasterizerGLES2::~RasterizerGLES2() {
memdelete_arr(skinned_buffer);
};

View file

@ -65,7 +65,7 @@ class RasterizerGLES2 : public Rasterizer {
MAX_SCENE_LIGHTS=2048,
LIGHT_SPOT_BIT=0x80,
DEFAULT_SKINNED_BUFFER_SIZE = 2048 * 1024, // 10k vertices
DEFAULT_SKINNED_BUFFER_SIZE = 2048, // 10k vertices
MAX_HW_LIGHTS = 1,
};
@ -827,15 +827,18 @@ class RasterizerGLES2 : public Rasterizer {
GLuint gui_quad_buffer;
struct RenderList {
enum {
MAX_ELEMENTS=4096,
DEFAULT_MAX_ELEMENTS=4096,
MAX_LIGHTS=4,
SORT_FLAG_SKELETON=1,
SORT_FLAG_INSTANCING=2,
};
static int max_elements;
struct Element {
@ -868,8 +871,8 @@ class RasterizerGLES2 : public Rasterizer {
};
Element _elements[MAX_ELEMENTS];
Element *elements[MAX_ELEMENTS];
Element *_elements;
Element **elements;
int element_count;
void clear() {
@ -1004,17 +1007,28 @@ class RasterizerGLES2 : public Rasterizer {
}
_FORCE_INLINE_ Element* add_element() {
if (element_count>MAX_ELEMENTS)
if (element_count>=max_elements)
return NULL;
elements[element_count]=&_elements[element_count];
return elements[element_count++];
}
RenderList() {
void init() {
element_count = 0;
for (int i=0;i<MAX_ELEMENTS;i++)
elements=memnew_arr(Element*,max_elements);
_elements=memnew_arr(Element,max_elements);
for (int i=0;i<max_elements;i++)
elements[i]=&_elements[i]; // assign elements
}
RenderList() {
}
~RenderList() {
memdelete_arr(elements);
memdelete_arr(_elements);
}
};

View file

@ -50,11 +50,16 @@
#ifdef ANDROID_ENABLED
#include "platform/android/ifaddrs_android.h"
#else
#ifdef __FreeBSD__
#include <sys/types.h>
#endif
#include <ifaddrs.h>
#endif
#include <arpa/inet.h>
#include <sys/socket.h>
#ifdef __FreeBSD__
#include <netinet/in.h>
#endif
#endif
IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) {

View file

@ -44,7 +44,9 @@
#include "stream_peer_tcp_posix.h"
#include "packet_peer_udp_posix.h"
#ifdef __FreeBSD__
#include <sys/param.h>
#endif
#include <stdarg.h>
#include <sys/time.h>
#include <sys/wait.h>
@ -305,7 +307,17 @@ Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,boo
args.push_back((char*)cs[i].get_data());// shitty C cast
args.push_back(0);
#ifdef __FreeBSD__
if(p_path.find("/")) {
// exec name contains path so use it
execv(p_path.utf8().get_data(),&args[0]);
}else{
// use program name and search through PATH to find it
execvp(getprogname(),&args[0]);
}
#else
execv(p_path.utf8().get_data(),&args[0]);
#endif
// still alive? something failed..
fprintf(stderr,"**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n",p_path.utf8().get_data());
abort();
@ -421,6 +433,12 @@ String OS_Unix::get_executable_path() const {
return OS::get_executable_path();
}
return b;
#elif defined(__FreeBSD__)
char resolved_path[MAXPATHLEN];
realpath(OS::get_executable_path().utf8().get_data(), resolved_path);
return String(resolved_path);
#else
ERR_PRINT("Warning, don't know how to obtain executable path on this OS! Please override this function properly.");
return OS::get_executable_path();

View file

@ -51,7 +51,7 @@ String GDScriptLanguage::get_template(const String& p_class_name, const String&
"# var a=2\n"+
"# var b=\"textvar\"\n\n"+
"func _ready():\n"+
"\t# Initalization here\n"+
"\t# Initialization here\n"+
"\tpass\n"+
"\n"+
"\n";

View file

@ -84,13 +84,11 @@ static int frame_count = 0;
switch (frame_count) {
case 0: {
int backingWidth;
int backingHeight;
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
iphone_main(backingWidth, backingHeight, gargc, gargv);
int backingWidth;
int backingHeight;
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
OS::VideoMode vm;
vm.fullscreen = true;
@ -198,6 +196,13 @@ static int frame_count = 0;
//glView.autoresizesSubviews = YES;
//[glView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth];
int backingWidth;
int backingHeight;
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
iphone_main(backingWidth, backingHeight, gargc, gargv);
view_controller = [[ViewController alloc] init];
view_controller.view = glView;
window.rootViewController = view_controller;

View file

@ -22,7 +22,7 @@ def get_opts():
return [
('ISIMPLATFORM', 'name of the iphone platform', 'iPhoneSimulator'),
('ISIMPATH', 'the path to iphone toolchain', '/Applications/Xcode.app/Contents/Developer/Platforms/${ISIMPLATFORM}.platform'),
('ISIMSDK', 'path to the iphone SDK', '$ISIMPATH/Developer/SDKs/${ISIMPLATFORM}7.1.sdk'),
('ISIMSDK', 'path to the iphone SDK', '$ISIMPATH/Developer/SDKs/${ISIMPLATFORM}.sdk'),
('game_center', 'Support for game center', 'yes'),
('store_kit', 'Support for in-app store', 'yes'),
('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'),

View file

@ -593,10 +593,11 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE);
// Make sure we don't include modifiers for the modifier key itself.
KeyEvent ke;
ke.mod_state.shift=shift_mem;
ke.mod_state.alt=alt_mem;
ke.mod_state.control=control_mem;
ke.mod_state.shift= (wParam != VK_SHIFT) ? shift_mem : false;
ke.mod_state.alt= (! (wParam == VK_MENU && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN))) ? alt_mem : false;
ke.mod_state.control= (wParam != VK_CONTROL) ? control_mem : false;
ke.mod_state.meta=meta_mem;
ke.uMsg=uMsg;

View file

@ -70,24 +70,23 @@ def configure(env):
else:
env["bits"]="32"
env.Append(CPPPATH=['#platform/x11'])
if (env["use_llvm"]=="yes"):
env["CC"]="clang"
env["CXX"]="clang++"
env["LD"]="clang++"
if (env["use_sanitizer"]=="yes"):
env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer'])
env.Append(LINKFLAGS=['-fsanitize=address'])
env.extra_suffix=".llvms"
else:
env.extra_suffix=".llvm"
if 'clang++' not in env['CXX']:
env["CC"]="clang"
env["CXX"]="clang++"
env["LD"]="clang++"
env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
env.extra_suffix=".llvm"
if (env["colored"]=="yes"):
if sys.stdout.isatty():
env.Append(CXXFLAGS=["-fcolor-diagnostics"])
if (env["use_sanitizer"]=="yes"):
env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer'])
env.Append(LINKFLAGS=['-fsanitize=address'])
env.extra_suffix+="s"
#if (env["tools"]=="no"):
# #no tools suffix
@ -141,11 +140,6 @@ def configure(env):
env.Append(LINKFLAGS=['-m64','-L/usr/lib/i686-linux-gnu'])
if (env["CXX"]=="clang++"):
env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
env["CC"]="clang"
env["LD"]="clang++"
import methods
env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )

View file

@ -810,6 +810,23 @@ void CanvasItem::_shader_changed() {
}
#endif
void CanvasItem::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
if (p_idx==0 && shader.is_valid() && (p_function.operator String()=="get_shader_param" || p_function.operator String()=="set_shader_param")) {
List<PropertyInfo> pl;
shader->get_param_list(&pl);
for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\"");
}
return;
}
Node::get_argument_options(p_function,p_idx,r_options);
}
void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_sort_children"),&CanvasItem::_sort_children);
@ -845,7 +862,7 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_self_opacity","self_opacity"),&CanvasItem::set_self_opacity);
ObjectTypeDB::bind_method(_MD("get_self_opacity"),&CanvasItem::get_self_opacity);
ObjectTypeDB::bind_method(_MD("set_draw_behind_parent","enabe"),&CanvasItem::set_draw_behind_parent);
ObjectTypeDB::bind_method(_MD("set_draw_behind_parent","enable"),&CanvasItem::set_draw_behind_parent);
ObjectTypeDB::bind_method(_MD("is_draw_behind_parent_enabled"),&CanvasItem::is_draw_behind_parent_enabled);
ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top);
@ -882,6 +899,10 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_use_parent_shader","enable"),&CanvasItem::set_use_parent_shader);
ObjectTypeDB::bind_method(_MD("get_use_parent_shader"),&CanvasItem::get_use_parent_shader);
ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItem::set_shader_param);
ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItem::get_shader_param);
BIND_VMETHOD(MethodInfo("_draw"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"),_SCS("_is_visible_") );

View file

@ -221,6 +221,8 @@ public:
void set_shader_param(const StringName& p_param,const Variant& p_value);
Variant get_shader_param(const StringName& p_param) const;
void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
CanvasItem();
~CanvasItem();
};

View file

@ -604,7 +604,7 @@ Vector3 Camera::project_position(const Point2& p_point) const {
Vector2 point;
point.x = (p_point.x/viewport_size.x) * 2.0 - 1.0;
point.y = (p_point.y/viewport_size.y) * 2.0 - 1.0;
point.y = (1.0-(p_point.y/viewport_size.y)) * 2.0 - 1.0;
point*=vp_size;
Vector3 p(point.x,point.y,-near);

View file

@ -582,7 +582,7 @@ void ShaderMaterial::get_argument_options(const StringName& p_function,int p_idx
List<PropertyInfo> pl;
shader->get_param_list(&pl);
for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
r_options->push_back("\""+E->get().name.replace("shader_param/","")+"\"");
r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\"");
}
}
}

View file

@ -525,24 +525,32 @@ bool PolygonPathFinder::is_point_inside(const Vector2& p_point) const {
Vector2 PolygonPathFinder::get_closest_point(const Vector2& p_point) const {
int closest_idx=-1;
float closest_dist=1e20;
for(int i=0;i<points.size()-2;i++) {
Vector2 closest_point;
for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
const Edge& e=E->get();
Vector2 seg[2]={
points[e.points[0]].pos,
points[e.points[1]].pos
};
Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point,seg);
float d = p_point.distance_squared_to(closest);
float d = p_point.distance_squared_to(points[i].pos);
if (d<closest_dist) {
closest_dist=d;
closest_idx=i;
closest_point=closest;
}
}
ERR_FAIL_COND_V(closest_dist==1e20,Vector2());
ERR_FAIL_COND_V(closest_idx==-1,Vector2());
return points[closest_idx].pos;
return closest_point;
}
Vector<Vector2> PolygonPathFinder::get_intersections(const Vector2& p_from, const Vector2& p_to) const {
Vector<Vector2> inters;

View file

@ -85,6 +85,12 @@ void StyleBox::_bind_methods() {
ObjectTypeDB::bind_method(_MD("draw"),&StyleBox::draw);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/left", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_LEFT );
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/right", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_RIGHT );
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/top", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_TOP);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/bottom", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_BOTTOM );
}
StyleBox::StyleBox() {

View file

@ -936,21 +936,21 @@ float CubeMap::get_lossy_storage_quality() const {
bool CubeMap::_set(const StringName& p_name, const Variant& p_value) {
if (p_name=="side/left")
if (p_name=="side/left") {
set_side(SIDE_LEFT,p_value);
if (p_name=="side/right")
} else if (p_name=="side/right") {
set_side(SIDE_RIGHT,p_value);
if (p_name=="side/bottom")
} else if (p_name=="side/bottom") {
set_side(SIDE_BOTTOM,p_value);
if (p_name=="side/top")
} else if (p_name=="side/top") {
set_side(SIDE_TOP,p_value);
if (p_name=="side/front")
} else if (p_name=="side/front") {
set_side(SIDE_FRONT,p_value);
if (p_name=="side/back")
} else if (p_name=="side/back") {
set_side(SIDE_BACK,p_value);
else if (p_name=="flags")
} else if (p_name=="flags") {
set_flags(p_value);
else if (p_name=="storage") {
} else if (p_name=="storage") {
storage=Storage(p_value.operator int());
} else if (p_name=="lossy_quality") {
lossy_storage_quality=p_value;
@ -963,25 +963,25 @@ bool CubeMap::_set(const StringName& p_name, const Variant& p_value) {
bool CubeMap::_get(const StringName& p_name,Variant &r_ret) const {
if (p_name=="side/left")
if (p_name=="side/left") {
r_ret=get_side(SIDE_LEFT);
if (p_name=="side/right")
} else if (p_name=="side/right") {
r_ret=get_side(SIDE_RIGHT);
if (p_name=="side/bottom")
} else if (p_name=="side/bottom") {
r_ret=get_side(SIDE_BOTTOM);
if (p_name=="side/top")
} else if (p_name=="side/top") {
r_ret=get_side(SIDE_TOP);
if (p_name=="side/front")
} else if (p_name=="side/front") {
r_ret=get_side(SIDE_FRONT);
if (p_name=="side/back")
} else if (p_name=="side/back") {
r_ret=get_side(SIDE_BACK);
else if (p_name=="flags")
} else if (p_name=="flags") {
r_ret= flags;
else if (p_name=="storage")
} else if (p_name=="storage") {
r_ret= storage;
else if (p_name=="lossy_quality")
} else if (p_name=="lossy_quality") {
r_ret= lossy_storage_quality;
else
} else
return false;
return true;

View file

@ -1141,10 +1141,36 @@ EditorImportExport* EditorImportExport::singleton=NULL;
void EditorImportExport::add_import_plugin(const Ref<EditorImportPlugin>& p_plugin) {
// Need to make sure the name is unique if we are going to lookup by it
ERR_FAIL_COND(by_idx.has(p_plugin->get_name()));
by_idx[ p_plugin->get_name() ]=plugins.size();
plugins.push_back(p_plugin);
}
void EditorImportExport::remove_import_plugin(const Ref<EditorImportPlugin>& p_plugin) {
String plugin_name = p_plugin->get_name();
// Keep the indices the same
// Find the index of the target plugin
ERR_FAIL_COND(!by_idx.has(plugin_name));
int idx = by_idx[plugin_name];
int last_idx = plugins.size() - 1;
// Swap the last plugin and the target one
SWAP(plugins[idx], plugins[last_idx]);
// Update the index of the old last one
by_idx[plugins[idx]->get_name()] = idx;
// Remove the target plugin's by_idx entry
by_idx.erase(plugin_name);
// Erase the plugin
plugins.remove(last_idx);
}
int EditorImportExport::get_import_plugin_count() const{
return plugins.size();

View file

@ -270,6 +270,7 @@ public:
static EditorImportExport* get_singleton() { return singleton; }
void add_import_plugin(const Ref<EditorImportPlugin>& p_plugin);
void remove_import_plugin(const Ref<EditorImportPlugin>& p_plugin);
int get_import_plugin_count() const;
Ref<EditorImportPlugin> get_import_plugin(int p_idx) const;
Ref<EditorImportPlugin> get_import_plugin_by_name(const String& p_string) const;

View file

@ -336,6 +336,19 @@ void EditorNode::_vp_resized() {
}
void EditorNode::_rebuild_import_menu()
{
PopupMenu* p = import_menu->get_popup();
p->clear();
p->add_item("Sub-Scene", FILE_IMPORT_SUBSCENE);
p->add_separator();
for (int i = 0; i < editor_import_export->get_import_plugin_count(); i++) {
p->add_item(editor_import_export->get_import_plugin(i)->get_visible_name(), IMPORT_PLUGIN_BASE + i);
}
p->add_separator();
p->add_item("Re-Import..", SETTINGS_IMPORT);
}
void EditorNode::_node_renamed() {
if (property_editor)
@ -1967,6 +1980,25 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
log->add_message("REDO: "+action);
} break;
case EDIT_REVERT: {
Node *scene = get_edited_scene();
if (!scene)
break;
if (unsaved_cache && !p_confirmed) {
confirmation->get_ok()->set_text("Revert");
confirmation->set_text("This action cannot be undone. Revert anyway?");
confirmation->popup_centered(Size2(300,70));
break;
}
Error err = load_scene(scene->get_filename());
} break;
#if 0
case NODE_EXTERNAL_INSTANCE: {
@ -2388,6 +2420,19 @@ void EditorNode::remove_editor_plugin(EditorPlugin *p_editor) {
}
void EditorNode::add_editor_import_plugin(const Ref<EditorImportPlugin>& p_editor_import) {
editor_import_export->add_import_plugin(p_editor_import);
_rebuild_import_menu();
}
void EditorNode::remove_editor_import_plugin(const Ref<EditorImportPlugin>& p_editor_import) {
editor_import_export->remove_import_plugin(p_editor_import);
_rebuild_import_menu();
}
void EditorNode::set_edited_scene(Node *p_scene) {
if (edited_scene) {
@ -3152,6 +3197,9 @@ void EditorNode::_bind_methods() {
ObjectTypeDB::bind_method("_sources_changed",&EditorNode::_sources_changed);
ObjectTypeDB::bind_method("_fs_changed",&EditorNode::_fs_changed);
ObjectTypeDB::bind_method(_MD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin);
ObjectTypeDB::bind_method(_MD("remove_editor_import_plugin", "plugin"), &EditorNode::remove_editor_import_plugin);
ObjectTypeDB::bind_method(_MD("get_gui_base"), &EditorNode::get_gui_base);
ADD_SIGNAL( MethodInfo("play_pressed") );
ADD_SIGNAL( MethodInfo("pause_pressed") );
@ -3469,6 +3517,8 @@ EditorNode::EditorNode() {
p->add_separator();
p->add_item("Project Settings",RUN_SETTINGS);
p->add_separator();
p->add_item("Revert Scene",EDIT_REVERT);
p->add_separator();
p->add_item("Quit to Project List",RUN_PROJECT_MANAGER,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_Q);
p->add_item("Quit",FILE_QUIT,KEY_MASK_CMD+KEY_Q);
@ -3513,8 +3563,6 @@ EditorNode::EditorNode() {
left_menu_hb->add_child( import_menu );
p=import_menu->get_popup();
p->add_item("Sub-Scene",FILE_IMPORT_SUBSCENE);
p->add_separator();
p->connect("item_pressed",this,"_menu_option");
export_button = memnew( ToolButton );
@ -3552,7 +3600,7 @@ EditorNode::EditorNode() {
play_button->set_icon(gui_base->get_icon("MainPlay","EditorIcons"));
play_button->set_focus_mode(Control::FOCUS_NONE);
play_button->connect("pressed", this,"_menu_option",make_binds(RUN_PLAY));
play_button->set_tooltip("Start the scene (F5).");
play_button->set_tooltip("Play the project (F5).");
@ -4023,11 +4071,6 @@ EditorNode::EditorNode() {
editor_import_export->add_import_plugin( Ref<EditorSampleImportPlugin>( memnew(EditorSampleImportPlugin(this))));
editor_import_export->add_import_plugin( Ref<EditorTranslationImportPlugin>( memnew(EditorTranslationImportPlugin(this))));
for(int i=0;i<editor_import_export->get_import_plugin_count();i++) {
import_menu->get_popup()->add_item(editor_import_export->get_import_plugin(i)->get_visible_name(),IMPORT_PLUGIN_BASE+i);
}
editor_import_export->add_export_plugin( Ref<EditorTextureExportPlugin>( memnew(EditorTextureExportPlugin)));
add_editor_plugin( memnew( CanvasItemEditorPlugin(this) ) );
@ -4072,9 +4115,7 @@ EditorNode::EditorNode() {
circle_step_frame=OS::get_singleton()->get_frames_drawn();;
circle_step=0;
import_menu->get_popup()->add_separator();
import_menu->get_popup()->add_item("Re-Import..",SETTINGS_IMPORT);
_rebuild_import_menu();
editor_plugin_screen=NULL;
editor_plugin_over=NULL;

View file

@ -127,6 +127,7 @@ class EditorNode : public Node {
FILE_EXTERNAL_OPEN_SCENE,
EDIT_UNDO,
EDIT_REDO,
EDIT_REVERT,
RESOURCE_NEW,
RESOURCE_LOAD,
RESOURCE_SAVE,
@ -339,6 +340,8 @@ class EditorNode : public Node {
void _show_messages();
void _vp_resized();
void _rebuild_import_menu();
void _save_scene(String p_file);
@ -420,6 +423,9 @@ public:
static void add_editor_plugin(EditorPlugin *p_editor);
static void remove_editor_plugin(EditorPlugin *p_editor);
void add_editor_import_plugin(const Ref<EditorImportPlugin>& p_editor_import);
void remove_editor_import_plugin(const Ref<EditorImportPlugin>& p_editor_import);
void edit_node(Node *p_node);
void edit_resource(const Ref<Resource>& p_resource);

View file

@ -631,7 +631,10 @@ bool ScriptEditor::_test_script_times_on_disk() {
if (!all_ok)
disk_changed->call_deferred("popup_centered_ratio",0.5);
if (bool(EDITOR_DEF("text_editor/auto_reload_changed_scripts",false)))
script_editor->_reload_scripts();
else
disk_changed->call_deferred("popup_centered_ratio",0.5);
return all_ok;
}
@ -1806,6 +1809,7 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
script_editor->hide();
EDITOR_DEF("text_editor/auto_reload_changed_scripts",false);
EDITOR_DEF("external_editor/use_external_editor",false);
EDITOR_DEF("external_editor/exec_path","");
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"external_editor/exec_path",PROPERTY_HINT_GLOBAL_FILE));

View file

@ -79,10 +79,22 @@ Node* SceneTreeDock::instance(const String& p_file) {
//accept->get_cancel()->hide();
accept->get_ok()->set_text("Ugh");
accept->set_text(String("Error loading scene from ")+p_file);
accept->popup_centered(Size2(300,70));;
accept->popup_centered(Size2(300,70));
return NULL;
}
// If the scene hasn't been saved yet a cyclical dependency cannot exist.
if (edited_scene->get_filename()!="") {
if (_cyclical_dependency_exists(edited_scene->get_filename(), instanced_scene)) {
accept->get_ok()->set_text("Ok");
accept->set_text(String("Cannot instance the scene '")+p_file+String("' because the current scene exists within one of its' nodes."));
accept->popup_centered(Size2(300,90));
return NULL;
}
}
instanced_scene->generate_instance_state();
instanced_scene->set_filename( Globals::get_singleton()->localize_path(p_file) );
@ -100,6 +112,25 @@ Node* SceneTreeDock::instance(const String& p_file) {
}
bool SceneTreeDock::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) {
int childCount = p_desired_node->get_child_count();
if (p_desired_node->get_filename()==p_target_scene_path) {
return true;
}
for (int i=0;i<childCount;i++) {
Node* child=p_desired_node->get_child(i);
if(_cyclical_dependency_exists(p_target_scene_path,child)) {
return true;
}
}
return false;
}
static String _get_name_num_separator() {
switch(EditorSettings::get_singleton()->get("scenetree_editor/duplicate_node_name_num_separator").operator int()) {
case 0: return "";

View file

@ -102,6 +102,7 @@ class SceneTreeDock : public VBoxContainer {
void _load_request(const String& p_path);
void _script_open_request(const Ref<Script>& p_script);
bool _cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node);
void _node_selected();
void _node_renamed();

View file

@ -212,8 +212,8 @@ class DaeExporter:
imgid = self.new_id("image")
if (not os.path.isfile(imgpath)):
if img_tmp_path.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")):
imgpath="images/"+os.path.basename(img_tmp_path)
if imgpath.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")):
imgpath="images/"+os.path.basename(imgpath)
else:
imgpath="images/"+image.name+".png"