diff --git a/SConstruct b/SConstruct index 9cd1da7f458..9cce6edd812 100644 --- a/SConstruct +++ b/SConstruct @@ -220,14 +220,14 @@ if selected_platform in platform_list: env.Append(LINKFLAGS=string.split(str(LINKFLAGS))) - detect.configure(env) - - flag_list = platform_flags[selected_platform] for f in flag_list: if not (f[0] in ARGUMENTS): # allow command line to override platform flags env[f[0]] = f[1] + #must happen after the flags, so when flags are used by configure, stuff happens (ie, ssl on x11) + detect.configure(env) + #env['platform_libsuffix'] = env['LIBSUFFIX'] suffix="."+selected_platform diff --git a/core/error_list.h b/core/error_list.h index 124027172e2..92c417154ce 100644 --- a/core/error_list.h +++ b/core/error_list.h @@ -54,6 +54,7 @@ enum Error { ERR_FILE_CANT_READ, ERR_FILE_UNRECOGNIZED, // (15) ERR_FILE_CORRUPT, + ERR_FILE_MISSING_DEPENDENCIES, ERR_FILE_EOF, ERR_CANT_OPEN, ///< Can't open a resource/socket/file ERR_CANT_CREATE, diff --git a/core/error_macros.h b/core/error_macros.h index 18b08d8e0ee..76da88287bb 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -104,7 +104,7 @@ extern bool _err_error_exists; #define ERR_FAIL_INDEX(m_index,m_size) \ do {if ((m_index)<0 || (m_index)>=(m_size)) { \ - _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index "_STR(m_index)" out of size ("_STR(m_size)")."); \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index " _STR(m_index)" out of size (" _STR(m_size)")."); \ return; \ } else _err_error_exists=false; } while(0); \ @@ -115,7 +115,7 @@ extern bool _err_error_exists; #define ERR_FAIL_INDEX_V(m_index,m_size,m_retval) \ do {if ((m_index)<0 || (m_index)>=(m_size)) { \ - _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index "_STR(m_index)" out of size ("_STR(m_size)")."); \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index " _STR(m_index)" out of size (" _STR(m_size)")."); \ return m_retval; \ } else _err_error_exists=false;} while (0); @@ -125,14 +125,14 @@ extern bool _err_error_exists; #define ERR_FAIL_NULL(m_param) \ { if ( !m_param ) { \ - _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' "_STR(m_param)" ' is null."); \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' " _STR(m_param)" ' is null."); \ return; \ }else _err_error_exists=false; } \ #define ERR_FAIL_NULL_V(m_param,m_retval) \ { if ( !m_param ) { \ - _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' "_STR(m_param)" ' is null."); \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' " _STR(m_param)" ' is null."); \ return m_retval; \ }else _err_error_exists=false; } \ @@ -142,7 +142,7 @@ extern bool _err_error_exists; #define ERR_FAIL_COND(m_cond) \ { if ( m_cond ) { \ - _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true."); \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true."); \ return; \ }else _err_error_exists=false; } \ @@ -154,7 +154,7 @@ extern bool _err_error_exists; #define ERR_FAIL_COND_V(m_cond,m_retval) \ { if ( m_cond ) { \ - _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true. returned: "_STR(m_retval)); \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. returned: " _STR(m_retval)); \ return m_retval; \ }else _err_error_exists=false; } \ @@ -164,7 +164,7 @@ extern bool _err_error_exists; #define ERR_CONTINUE(m_cond) \ { if ( m_cond ) { \ - _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true. Continuing..:"); \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. Continuing..:"); \ continue;\ } else _err_error_exists=false;} \ @@ -174,7 +174,7 @@ extern bool _err_error_exists; #define ERR_BREAK(m_cond) \ { if ( m_cond ) { \ - _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true. Breaking..:"); \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. Breaking..:"); \ break;\ } else _err_error_exists=false;} \ @@ -193,7 +193,7 @@ extern bool _err_error_exists; #define ERR_FAIL_V(m_value) \ { \ - _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed, returning: "__STR(m_value)); \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed, returning: " __STR(m_value)); \ _err_error_exists=false; \ return m_value;\ } \ diff --git a/core/global_constants.cpp b/core/global_constants.cpp index b8d113f67c7..9fb45c672a8 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -422,6 +422,7 @@ static _GlobalConstant _global_constants[]={ BIND_GLOBAL_CONSTANT( ERR_FILE_CANT_READ ), BIND_GLOBAL_CONSTANT( ERR_FILE_UNRECOGNIZED ), BIND_GLOBAL_CONSTANT( ERR_FILE_CORRUPT ), + BIND_GLOBAL_CONSTANT( ERR_FILE_MISSING_DEPENDENCIES), BIND_GLOBAL_CONSTANT( ERR_FILE_EOF ), BIND_GLOBAL_CONSTANT( ERR_CANT_OPEN ), ///< Can't open a resource/socket/file BIND_GLOBAL_CONSTANT( ERR_CANT_CREATE ), diff --git a/core/globals.cpp b/core/globals.cpp index 731c5b7dff1..ffd4cf5d5e7 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -54,7 +54,7 @@ String Globals::localize_path(const String& p_path) const { if (resource_path=="") return p_path; //not initialied yet - if (p_path.begins_with("res://")) + if (p_path.find(":/") != -1) return p_path.simplify_path(); @@ -1477,7 +1477,6 @@ Globals::Globals() { custom_prop_info["render/mipmap_policy"]=PropertyInfo(Variant::INT,"render/mipmap_policy",PROPERTY_HINT_ENUM,"Allow,Allow For Po2,Disallow"); custom_prop_info["render/thread_model"]=PropertyInfo(Variant::INT,"render/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded"); custom_prop_info["physics_2d/thread_model"]=PropertyInfo(Variant::INT,"physics_2d/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded"); - set("display/emulate_touchscreen",false); using_datapack=false; } diff --git a/core/io/compression.cpp b/core/io/compression.cpp index 0bc006b41e9..729b7bec52c 100644 --- a/core/io/compression.cpp +++ b/core/io/compression.cpp @@ -26,12 +26,12 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "zlib.h" +#include "os/copymem.h" #include "compression.h" #include "fastlz.h" -#include "zlib.h" #include "zip_io.h" -#include "os/copymem.h" int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode) { diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index d3390ae1999..2db6e00f0a6 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -50,8 +50,10 @@ Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom if (!f) { Error err; f=FileAccess::open(p_file,FileAccess::READ,&err); - if (!f) + if (!f) { + print_line("ERROR OPENING FILE: "+p_file); return err; + } } String extension = p_file.extension(); @@ -62,15 +64,20 @@ Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom if (!loader[i]->recognize(extension)) continue; Error err = loader[i]->load_image(p_image,f); + if (err!=ERR_FILE_UNRECOGNIZED) { + + if (!p_custom) memdelete(f); + return err; } } - + print_line("NO LOADER?"); + if (!p_custom) memdelete(f); diff --git a/core/io/ioapi.h b/core/io/ioapi.h index a13d7ba621b..24bf6126176 100644 --- a/core/io/ioapi.h +++ b/core/io/ioapi.h @@ -40,7 +40,6 @@ #endif #include -#include #include "zlib.h" #if defined(USE_FILE32API) diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index c6cf631de61..60bb8b658eb 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -31,6 +31,7 @@ #include "globals.h" #include "io/file_access_compressed.h" #include "io/marshalls.h" +#include "os/dir_access.h" //#define print_bl(m_what) print_line(m_what) #define print_bl(m_what) @@ -99,7 +100,9 @@ enum { OBJECT_EMPTY=0, OBJECT_EXTERNAL_RESOURCE=1, OBJECT_INTERNAL_RESOURCE=2, - FORMAT_VERSION=0 + OBJECT_EXTERNAL_RESOURCE_INDEX=3, + FORMAT_VERSION=1, + FORMAT_VERSION_CAN_RENAME_DEPS=1 }; @@ -375,7 +378,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { } break; case OBJECT_INTERNAL_RESOURCE: { uint32_t index=f->get_32(); - String path = res_path+"::"+itos(index); + String path = res_path+"::"+itos(index); RES res = ResourceLoader::load(path); if (res.is_null()) { WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data()); @@ -384,6 +387,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { } break; case OBJECT_EXTERNAL_RESOURCE: { + //old file format, still around for compatibility String type = get_unicode_string(); String path = get_unicode_string(); @@ -394,6 +398,10 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { } + if (remaps.find(path)) { + path=remaps[path]; + } + RES res=ResourceLoader::load(path,type); if (res.is_null()) { @@ -401,6 +409,34 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { } r_v=res; + } break; + case OBJECT_EXTERNAL_RESOURCE_INDEX: { + //new file format, just refers to an index in the external list + uint32_t erindex = f->get_32(); + + if (erindex>=external_resources.size()) { + WARN_PRINT("Broken external resource! (index out of size"); + r_v=Variant(); + } else { + + String type = external_resources[erindex].type; + String path = external_resources[erindex].path; + + if (path.find("://")==-1 && path.is_rel_path()) { + // path is relative to file being loaded, so convert to a resource path + path=Globals::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); + + } + + RES res=ResourceLoader::load(path,type); + + if (res.is_null()) { + WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data()); + } + r_v=res; + } + + } break; default: { @@ -628,17 +664,20 @@ Error ResourceInteractiveLoaderBinary::poll(){ if (sstore_32(utf8.length()+1); + f->store_buffer((const uint8_t*)utf8.get_data(),utf8.length()+1); +} + + +static String get_ustring(FileAccess *f) { + + int len = f->get_32(); + Vector str_buf; + str_buf.resize(len); + f->get_buffer((uint8_t*)&str_buf[0],len); + String s; + s.parse_utf8(&str_buf[0]); + return s; +} + String ResourceInteractiveLoaderBinary::get_unicode_string() { int len = f->get_32(); @@ -801,7 +861,7 @@ String ResourceInteractiveLoaderBinary::get_unicode_string() { -void ResourceInteractiveLoaderBinary::get_dependencies(FileAccess *p_f,List *p_dependencies) { +void ResourceInteractiveLoaderBinary::get_dependencies(FileAccess *p_f,List *p_dependencies,bool p_add_types) { open(p_f); if (error) @@ -814,6 +874,10 @@ void ResourceInteractiveLoaderBinary::get_dependencies(FileAccess *p_f,Listpush_back(dep); } @@ -866,7 +930,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) { print_bl("minor: "+itos(ver_minor)); print_bl("format: "+itos(ver_format)); - if (ver_formatVERSION_MAJOR) { + if (ver_format>FORMAT_VERSION || ver_major>VERSION_MAJOR) { f->close(); ERR_EXPLAIN("File Format '"+itos(FORMAT_VERSION)+"."+itos(ver_major)+"."+itos(ver_minor)+"' is too new! Please upgrade to a a new engine version: "+local_path); @@ -903,6 +967,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) { } //see if the exporter has different set of external resources for more efficient loading + /* String preload_depts = "deps/"+res_path.md5_text(); if (Globals::get_singleton()->has(preload_depts)) { external_resources.clear(); @@ -913,7 +978,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) { external_resources[i].path=depts.get_name(i); } print_line(res_path+" - EXTERNAL RESOURCES: "+itos(external_resources.size())); - } + }*/ print_bl("ext resources: "+itos(ext_resources_size)); uint32_t int_resources_size=f->get_32(); @@ -973,7 +1038,7 @@ String ResourceInteractiveLoaderBinary::recognize(FileAccess *p_f) { uint32_t ver_minor=f->get_32(); uint32_t ver_format=f->get_32(); - if (ver_formatVERSION_MAJOR) { + if (ver_format>FORMAT_VERSION || ver_major>VERSION_MAJOR) { f->close(); return ""; @@ -1000,8 +1065,10 @@ ResourceInteractiveLoaderBinary::~ResourceInteractiveLoaderBinary() { } -Ref ResourceFormatLoaderBinary::load_interactive(const String &p_path) { +Ref ResourceFormatLoaderBinary::load_interactive(const String &p_path, Error *r_error) { + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; Error err; FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); @@ -1114,7 +1181,7 @@ Error ResourceFormatLoaderBinary::load_import_metadata(const String &p_path, Ref } -void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,List *p_dependencies) { +void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,List *p_dependencies,bool p_add_types) { FileAccess *f = FileAccess::open(p_path,FileAccess::READ); ERR_FAIL_COND(!f); @@ -1123,7 +1190,217 @@ void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,Listlocal_path=Globals::get_singleton()->localize_path(p_path); ria->res_path=ria->local_path; // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); - ria->get_dependencies(f,p_dependencies); + ria->get_dependencies(f,p_dependencies,p_add_types); +} + +Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path,const Map& p_map) { + + +// Error error=OK; + + + FileAccess *f=FileAccess::open(p_path,FileAccess::READ); + ERR_FAIL_COND_V(!f,ERR_CANT_OPEN); + + FileAccess* fw=NULL;//=FileAccess::open(p_path+".depren"); + + String local_path=p_path.get_base_dir(); + + uint8_t header[4]; + f->get_buffer(header,4); + if (header[0]=='R' && header[1]=='S' && header[2]=='C' && header[3]=='C') { + //compressed + FileAccessCompressed *fac = memnew( FileAccessCompressed ); + fac->open_after_magic(f); + f=fac; + + FileAccessCompressed *facw = memnew( FileAccessCompressed ); + facw->configure("RSCC"); + Error err = facw->_open(p_path+".depren",FileAccess::WRITE); + if (err) { + memdelete(fac); + memdelete(facw); + ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT); + } + + fw=facw; + + + } else if (header[0]!='R' || header[1]!='S' || header[2]!='R' || header[3]!='C') { + //not normal + + //error=ERR_FILE_UNRECOGNIZED; + memdelete(f); + ERR_EXPLAIN("Unrecognized binary resource file: "+local_path); + ERR_FAIL_V(ERR_FILE_UNRECOGNIZED); + } else { + fw = FileAccess::open(p_path+".depren",FileAccess::WRITE); + if (!fw) { + memdelete(f); + } + ERR_FAIL_COND_V(!fw,ERR_CANT_CREATE); + } + + bool big_endian = f->get_32(); +#ifdef BIG_ENDIAN_ENABLED + endian_swap = !big_endian; +#else + bool endian_swap = big_endian; +#endif + + bool use_real64 = f->get_32(); + + f->set_endian_swap(big_endian!=0); //read big endian if saved as big endian + fw->store_32(endian_swap); + fw->set_endian_swap(big_endian!=0); + fw->store_32(use_real64); //use real64 + + uint32_t ver_major=f->get_32(); + uint32_t ver_minor=f->get_32(); + uint32_t ver_format=f->get_32(); + + if (ver_formatremove(p_path+".depren"); + memdelete(da); + //fuck it, use the old approach; + + WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: "+p_path).utf8().get_data()); + + Error err; + f = FileAccess::open(p_path,FileAccess::READ,&err); + if (err!=OK) { + ERR_FAIL_COND_V(err!=OK,ERR_FILE_CANT_OPEN); + } + + Ref ria = memnew( ResourceInteractiveLoaderBinary ); + ria->local_path=Globals::get_singleton()->localize_path(p_path); + ria->res_path=ria->local_path; + ria->remaps=p_map; + // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); + ria->open(f); + + err = ria->poll(); + + while(err==OK) { + err=ria->poll(); + } + + ERR_FAIL_COND_V(err!=ERR_FILE_EOF,ERR_FILE_CORRUPT); + RES res = ria->get_resource(); + ERR_FAIL_COND_V(!res.is_valid(),ERR_FILE_CORRUPT); + + return ResourceFormatSaverBinary::singleton->save(p_path,res); + } + + if (ver_format>FORMAT_VERSION || ver_major>VERSION_MAJOR) { + + memdelete(f); + memdelete(fw); + ERR_EXPLAIN("File Format '"+itos(FORMAT_VERSION)+"."+itos(ver_major)+"."+itos(ver_minor)+"' is too new! Please upgrade to a a new engine version: "+local_path); + ERR_FAIL_V(ERR_FILE_UNRECOGNIZED); + + } + + fw->store_32( VERSION_MAJOR ); //current version + fw->store_32( VERSION_MINOR ); + fw->store_32( FORMAT_VERSION ); + + save_ustring(fw,get_ustring(f)); //type + + + size_t md_ofs = f->get_pos(); + size_t importmd_ofs = f->get_64(); + fw->store_64(0); //metadata offset + + for(int i=0;i<14;i++) { + fw->store_32(0); + f->get_32(); + } + + //string table + uint32_t string_table_size=f->get_32(); + + fw->store_32(string_table_size); + + for(uint32_t i=0;iget_32(); + fw->store_32(ext_resources_size); + for(uint32_t i=0;iget_pos() - (int64_t)f->get_pos(); + + //internal resources + uint32_t int_resources_size=f->get_32(); + fw->store_32(int_resources_size); + + for(uint32_t i=0;iget_64(); + save_ustring(fw,path); + fw->store_64(offset+size_diff); + } + + //rest of file + uint8_t b = f->get_8(); + while(!f->eof_reached()) { + fw->store_8(b); + b = f->get_8(); + } + + bool all_ok = fw->get_error()==OK; + + fw->seek(md_ofs); + fw->store_64(importmd_ofs+size_diff); + + + memdelete(f); + memdelete(fw); + + if (!all_ok) { + return ERR_CANT_CREATE; + } + + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + da->remove(p_path); + da->rename(p_path+".depren",p_path); + memdelete(da); + return OK; } @@ -1433,10 +1710,8 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant& p_property, } if (res->get_path().length() && res->get_path().find("::")==-1) { - f->store_32(OBJECT_EXTERNAL_RESOURCE); - save_unicode_string(res->get_save_type()); - String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path(); - save_unicode_string(path); + f->store_32(OBJECT_EXTERNAL_RESOURCE_INDEX); + f->store_32(external_resources[res]); } else { if (!resource_set.has(res)) { @@ -1594,11 +1869,12 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant& p_variant RES res = p_variant.operator RefPtr(); - if (res.is_null()) + if (res.is_null() || external_resources.has(res)) return; if (!p_main && (!bundle_resources ) && res->get_path().length() && res->get_path().find("::") == -1 ) { - external_resources.insert(res); + int idx = external_resources.size(); + external_resources[res]=idx; return; } @@ -1842,10 +2118,18 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_ // save external resource table f->store_32(external_resources.size()); //amount of external resources - for(Set::Element *E=external_resources.front();E;E=E->next()) { + Vector save_order; + save_order.resize(external_resources.size()); - save_unicode_string(E->get()->get_save_type()); - String path = E->get()->get_path(); + for(Map::Element *E=external_resources.front();E;E=E->next()) { + save_order[E->get()]=E->key(); + } + + for(int i=0;iget_save_type()); + String path = save_order[i]->get_path(); + path=relative_paths?local_path.path_to_file(path):path; save_unicode_string(path); } // save internal resource table @@ -1995,3 +2279,9 @@ void ResourceFormatSaverBinary::get_recognized_extensions(const RES& p_resource, } +ResourceFormatSaverBinary* ResourceFormatSaverBinary::singleton=NULL; + +ResourceFormatSaverBinary::ResourceFormatSaverBinary() { + + singleton=this; +} diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index da415d97a52..8bf20bc5749 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -71,6 +71,7 @@ class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader { String get_unicode_string(); void _advance_padding(uint32_t p_len); + Map remaps; Error error; int stage; @@ -88,9 +89,10 @@ public: virtual int get_stage() const; virtual int get_stage_count() const; + void set_remaps(const Map& p_remaps) { remaps=p_remaps; } void open(FileAccess *p_f); String recognize(FileAccess *p_f); - void get_dependencies(FileAccess *p_f,List *p_dependencies); + void get_dependencies(FileAccess *p_f, List *p_dependencies, bool p_add_types); ResourceInteractiveLoaderBinary(); @@ -101,13 +103,14 @@ public: class ResourceFormatLoaderBinary : public ResourceFormatLoader { public: - virtual Ref load_interactive(const String &p_path); + virtual Ref load_interactive(const String &p_path,Error *r_error=NULL); virtual void get_recognized_extensions_for_type(const String& p_type,List *p_extensions) const; virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; - virtual void get_dependencies(const String& p_path,List *p_dependencies); + virtual void get_dependencies(const String& p_path, List *p_dependencies, bool p_add_types=false); virtual Error load_import_metadata(const String &p_path, Ref& r_var) const; + virtual Error rename_dependencies(const String &p_path,const Map& p_map); @@ -134,7 +137,7 @@ class ResourceFormatSaverBinaryInstance { Vector strings; - Set external_resources; + Map external_resources; List saved_resources; @@ -174,11 +177,12 @@ class ResourceFormatSaverBinary : public ResourceFormatSaver { public: + static ResourceFormatSaverBinary* singleton; virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0); virtual bool recognize(const RES& p_resource) const; virtual void get_recognized_extensions(const RES& p_resource,List *p_extensions) const; - + ResourceFormatSaverBinary(); }; diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp index b744cbf9678..9019b4e3c0d 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -29,10 +29,10 @@ #include "resource_format_xml.h" #include "globals.h" #include "version.h" +#include "os/dir_access.h" - -ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool *r_exit,bool p_printerr) { +ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool *r_exit, bool p_printerr, List *r_order) { while(get_char()!='<' && !f->eof_reached()) {} @@ -107,7 +107,11 @@ ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool if (r_value.size()) { r_value.push_back(0); - tag.args[name].parse_utf8(r_value.get_data()); + String str; + str.parse_utf8(r_value.get_data()); + tag.args[name]=str; + if (r_order) + r_order->push_back(name); } break; @@ -119,7 +123,11 @@ ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool } else if (reading_value && r_value.size()) { r_value.push_back(0); - tag.args[name].parse_utf8(r_value.get_data()); + String str; + str.parse_utf8(r_value.get_data()); + tag.args[name]=str; + if (r_order) + r_order->push_back(name); name=""; r_value.clear(); reading_value=false; @@ -463,6 +471,10 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) } + if (remaps.has(path)) { + path=remaps[path]; + } + //take advantage of the resource loader cache. The resource is cached on it, even if RES res=ResourceLoader::load(path,hint); @@ -473,10 +485,31 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) } r_v=res.get_ref_ptr(); + } else if (tag->args.has("external")) { + + int index = tag->args["external"].to_int(); + if (ext_resources.has(index)) { + String path=ext_resources[index].path; + String type=ext_resources[index].type; + + //take advantage of the resource loader cache. The resource is cached on it, even if + RES res=ResourceLoader::load(path,type); + + if (res.is_null()) { + + WARN_PRINT(String("Couldn't load externalresource: "+path).ascii().get_data()); + } + + r_v=res.get_ref_ptr(); + } else { + WARN_PRINT(String("Invalid external resource index: "+itos(index)).ascii().get_data()); + + } } + Error err=goto_end_of_tag(); if (err) { ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error closing tag."); @@ -1364,32 +1397,6 @@ Error ResourceInteractiveLoaderXML::poll() { if (error!=OK) return error; - if (ext_resources.size()) { - - error=ERR_FILE_CORRUPT; - String path=ext_resources.front()->get(); - - RES res = ResourceLoader::load(path); - - if (res.is_null()) { - - if (ResourceLoader::get_abort_on_missing_resources()) { - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": editor exported nonexistent resource at: "+path); - ERR_FAIL_V(error); - } else { - ResourceLoader::notify_load_error("Resource Not Found: "+path); - } - } else { - - resource_cache.push_back(res); - } - - error=OK; - ext_resources.pop_front(); - resource_current++; - return error; - } - bool exit; Tag *tag = parse_tag(&exit); @@ -1413,12 +1420,13 @@ Error ResourceInteractiveLoaderXML::poll() { ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": missing 'path' field."); ERR_FAIL_COND_V(!tag->args.has("path"),ERR_FILE_CORRUPT); - String type; + String type="Resource"; if (tag->args.has("type")) type=tag->args["type"]; String path = tag->args["path"]; + ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": can't use a local path, this is a bug?."); ERR_FAIL_COND_V(path.begins_with("local://"),ERR_FILE_CORRUPT); @@ -1427,6 +1435,9 @@ Error ResourceInteractiveLoaderXML::poll() { path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path)); } + if (remaps.has(path)) { + path=remaps[path]; + } RES res = ResourceLoader::load(path,type); @@ -1436,13 +1447,21 @@ Error ResourceInteractiveLoaderXML::poll() { ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": referenced nonexistent resource at: "+path); ERR_FAIL_V(error); } else { - ResourceLoader::notify_load_error("Resource Not Found: "+path); + ResourceLoader::notify_dependency_error(local_path,path,type); } } else { resource_cache.push_back(res); } + if (tag->args.has("index")) { + ExtResource er; + er.path=path; + er.type=type; + ext_resources[tag->args["index"].to_int()]=er; + } + + Error err = close_tag("ext_resource"); if (err) return error; @@ -1566,7 +1585,7 @@ int ResourceInteractiveLoaderXML::get_stage() const { } int ResourceInteractiveLoaderXML::get_stage_count() const { - return resources_total+ext_resources.size(); + return resources_total;//+ext_resources; } ResourceInteractiveLoaderXML::~ResourceInteractiveLoaderXML() { @@ -1574,7 +1593,7 @@ ResourceInteractiveLoaderXML::~ResourceInteractiveLoaderXML() { memdelete(f); } -void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List *p_dependencies) { +void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List *p_dependencies,bool p_add_types) { open(f); @@ -1617,6 +1636,10 @@ void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List * path = ResourceLoader::guess_full_filename(path,type); } + if (p_add_types && tag->args.has("type")) { + path+="::"+tag->args["type"]; + } + p_dependencies->push_back(path); Error err = close_tag("ext_resource"); @@ -1628,6 +1651,167 @@ void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List * } +Error ResourceInteractiveLoaderXML::rename_dependencies(FileAccess *p_f, const String &p_path,const Map& p_map) { + + open(p_f); + ERR_FAIL_COND_V(error!=OK,error); + + //FileAccess + + bool old_format=false; + + FileAccess *fw = NULL; + + String base_path=local_path.get_base_dir(); + + while(true) { + bool exit; + List order; + + Tag *tag = parse_tag(&exit,true,&order); + + bool done=false; + + if (!tag) { + if (fw) { + memdelete(fw); + } + error=ERR_FILE_CORRUPT; + ERR_FAIL_COND_V(!exit,error); + error=ERR_FILE_EOF; + + return error; + } + + if (tag->name=="ext_resource") { + + if (!tag->args.has("index") || !tag->args.has("path") || !tag->args.has("type")) { + old_format=true; + break; + } + + if (!fw) { + + fw=FileAccess::open(p_path+".depren",FileAccess::WRITE); + fw->store_line(""); //no escape + fw->store_line(""); + + } + + String path = tag->args["path"]; + String index = tag->args["index"]; + String type = tag->args["type"]; + + + bool relative=false; + if (!path.begins_with("res://")) { + path=base_path.plus_file(path).simplify_path(); + relative=true; + } + + + if (p_map.has(path)) { + String np=p_map[path]; + path=np; + } + + if (relative) { + //restore relative + path=base_path.path_to_file(path); + } + + tag->args["path"]=path; + tag->args["index"]=index; + tag->args["type"]=type; + + } else { + + done=true; + } + + String tagt="\t<"; + if (exit) + tagt+="/"; + tagt+=tag->name; + + for(List::Element *E=order.front();E;E=E->next()) { + tagt+=" "+E->get()+"=\""+tag->args[E->get()]+"\""; + } + tagt+=">"; + fw->store_line(tagt); + if (done) + break; + close_tag("ext_resource"); + fw->store_line("\t"); + + } + + + if (old_format) { + if (fw) + memdelete(fw); + + DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + da->remove(p_path+".depren"); + memdelete(da); + //fuck it, use the old approach; + + WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: "+p_path).utf8().get_data()); + + Error err; + FileAccess *f2 = FileAccess::open(p_path,FileAccess::READ,&err); + if (err!=OK) { + ERR_FAIL_COND_V(err!=OK,ERR_FILE_CANT_OPEN); + } + + Ref ria = memnew( ResourceInteractiveLoaderXML ); + ria->local_path=Globals::get_singleton()->localize_path(p_path); + ria->res_path=ria->local_path; + ria->remaps=p_map; + // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); + ria->open(f2); + + err = ria->poll(); + + while(err==OK) { + err=ria->poll(); + } + + ERR_FAIL_COND_V(err!=ERR_FILE_EOF,ERR_FILE_CORRUPT); + RES res = ria->get_resource(); + ERR_FAIL_COND_V(!res.is_valid(),ERR_FILE_CORRUPT); + + return ResourceFormatSaverXML::singleton->save(p_path,res); + } + + if (!fw) { + + return OK; //nothing to rename, do nothing + } + + uint8_t c=f->get_8(); + while(!f->eof_reached()) { + fw->store_8(c); + c=f->get_8(); + } + + bool all_ok = fw->get_error()==OK; + + memdelete(fw); + + if (!all_ok) { + return ERR_CANT_CREATE; + } + + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + da->remove(p_path); + da->rename(p_path+".depren",p_path); + memdelete(da); + + return OK; + +} + void ResourceInteractiveLoaderXML::open(FileAccess *p_f) { @@ -1686,6 +1870,7 @@ void ResourceInteractiveLoaderXML::open(FileAccess *p_f) { } + /* String preload_depts = "deps/"+local_path.md5_text(); if (Globals::get_singleton()->has(preload_depts)) { ext_resources.clear(); @@ -1697,7 +1882,7 @@ void ResourceInteractiveLoaderXML::open(FileAccess *p_f) { } print_line(local_path+" - EXTERNAL RESOURCES: "+itos(ext_resources.size())); } - +*/ } @@ -1730,7 +1915,10 @@ String ResourceInteractiveLoaderXML::recognize(FileAccess *p_f) { ///////////////////// -Ref ResourceFormatLoaderXML::load_interactive(const String &p_path) { +Ref ResourceFormatLoaderXML::load_interactive(const String &p_path, Error *r_error) { + + if (r_error) + *r_error=ERR_CANT_OPEN; Error err; FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); @@ -1816,7 +2004,7 @@ String ResourceFormatLoaderXML::get_resource_type(const String &p_path) const{ } -void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List *p_dependencies) { +void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List *p_dependencies,bool p_add_types) { FileAccess *f = FileAccess::open(p_path,FileAccess::READ); if (!f) { @@ -1828,11 +2016,27 @@ void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List ria->local_path=Globals::get_singleton()->localize_path(p_path); ria->res_path=ria->local_path; // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); - ria->get_dependencies(f,p_dependencies); + ria->get_dependencies(f,p_dependencies,p_add_types); } +Error ResourceFormatLoaderXML::rename_dependencies(const String &p_path,const Map& p_map) { + + FileAccess *f = FileAccess::open(p_path,FileAccess::READ); + if (!f) { + + ERR_FAIL_V(ERR_CANT_OPEN); + } + + Ref ria = memnew( ResourceInteractiveLoaderXML ); + ria->local_path=Globals::get_singleton()->localize_path(p_path); + ria->res_path=ria->local_path; +// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); + return ria->rename_dependencies(f,p_path,p_map); +} + + /****************************************************************************************/ /****************************************************************************************/ /****************************************************************************************/ @@ -2024,20 +2228,26 @@ void ResourceFormatSaverXMLInstance::write_property(const String& p_name,const V return; // don't save it } - params="resource_type=\""+res->get_save_type()+"\""; + if (external_resources.has(res)) { - if (res->get_path().length() && res->get_path().find("::")==-1) { - //external resource - String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path(); - escape(path); - params+=" path=\""+path+"\""; + params="external=\""+itos(external_resources[res])+"\""; } else { + params="resource_type=\""+res->get_save_type()+"\""; - //internal resource - ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?"); - ERR_FAIL_COND(!resource_set.has(res)); - params+=" path=\"local://"+itos(res->get_subindex())+"\""; + if (res->get_path().length() && res->get_path().find("::")==-1) { + //external resource + String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path(); + escape(path); + params+=" path=\""+path+"\""; + } else { + + //internal resource + ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?"); + ERR_FAIL_COND(!resource_set.has(res)); + + params+=" path=\"local://"+itos(res->get_subindex())+"\""; + } } } break; @@ -2441,11 +2651,12 @@ void ResourceFormatSaverXMLInstance::_find_resources(const Variant& p_variant,bo RES res = p_variant.operator RefPtr(); - if (res.is_null()) + if (res.is_null() || external_resources.has(res)) return; if (!p_main && (!bundle_resources ) && res->get_path().length() && res->get_path().find("::") == -1 ) { - external_resources.push_back(res); + int index = external_resources.size(); + external_resources[res]=index; return; } @@ -2533,12 +2744,12 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res enter_tag("resource_file","type=\""+p_resource->get_type()+"\" subresource_count=\""+itos(saved_resources.size()+external_resources.size())+"\" version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\""); write_string("\n",false); - for(List::Element *E=external_resources.front();E;E=E->next()) { + for(Map::Element *E=external_resources.front();E;E=E->next()) { write_tabs(); - String p = E->get()->get_path(); + String p = E->key()->get_path(); - enter_tag("ext_resource","path=\""+p+"\" type=\""+E->get()->get_save_type()+"\""); //bundled + enter_tag("ext_resource","path=\""+p+"\" type=\""+E->key()->get_save_type()+"\" index=\""+itos(E->get())+"\""); //bundled exit_tag("ext_resource"); //bundled write_string("\n",false); } @@ -2667,3 +2878,8 @@ void ResourceFormatSaverXML::get_recognized_extensions(const RES& p_resource,Lis } } + +ResourceFormatSaverXML* ResourceFormatSaverXML::singleton=NULL; +ResourceFormatSaverXML::ResourceFormatSaverXML() { + singleton=this; +} diff --git a/core/io/resource_format_xml.h b/core/io/resource_format_xml.h index d5ba9eb8001..77987c6a5b6 100644 --- a/core/io/resource_format_xml.h +++ b/core/io/resource_format_xml.h @@ -46,13 +46,21 @@ class ResourceInteractiveLoaderXML : public ResourceInteractiveLoader { String name; HashMap args; + }; _FORCE_INLINE_ Error _parse_array_element(Vector &buff,bool p_number_only,FileAccess *f,bool *end); + struct ExtResource { + String path; + String type; + }; - List ext_resources; + + Map remaps; + + Map ext_resources; int resources_total; int resource_current; @@ -66,7 +74,7 @@ friend class ResourceFormatLoaderXML; List tag_stack; List resource_cache; - Tag* parse_tag(bool* r_exit=NULL,bool p_printerr=true); + Tag* parse_tag(bool* r_exit=NULL,bool p_printerr=true,List *r_order=NULL); Error close_tag(const String& p_name); _FORCE_INLINE_ void unquote(String& p_str); Error goto_end_of_tag(); @@ -87,7 +95,8 @@ public: void open(FileAccess *p_f); String recognize(FileAccess *p_f); - void get_dependencies(FileAccess *p_f,List *p_dependencies); + void get_dependencies(FileAccess *p_f, List *p_dependencies, bool p_add_types); + Error rename_dependencies(FileAccess *p_f, const String &p_path,const Map& p_map); ~ResourceInteractiveLoaderXML(); @@ -97,12 +106,13 @@ public: class ResourceFormatLoaderXML : public ResourceFormatLoader { public: - virtual Ref load_interactive(const String &p_path); + virtual Ref load_interactive(const String &p_path,Error *r_error=NULL); virtual void get_recognized_extensions_for_type(const String& p_type,List *p_extensions) const; virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; - virtual void get_dependencies(const String& p_path,List *p_dependencies); + virtual void get_dependencies(const String& p_path, List *p_dependencies, bool p_add_types=false); + virtual Error rename_dependencies(const String &p_path,const Map& p_map); }; @@ -125,7 +135,7 @@ class ResourceFormatSaverXMLInstance { int depth; Set resource_set; List saved_resources; - List external_resources; + Map external_resources; void enter_tag(const char* p_tag,const String& p_args=String()); void exit_tag(const char* p_tag); @@ -148,11 +158,12 @@ public: class ResourceFormatSaverXML : public ResourceFormatSaver { public: + static ResourceFormatSaverXML* singleton; virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0); virtual bool recognize(const RES& p_resource) const; virtual void get_recognized_extensions(const RES& p_resource,List *p_extensions) const; - + ResourceFormatSaverXML(); }; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 22d89840ae5..1e014480f4d 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -103,10 +103,10 @@ public: -Ref ResourceFormatLoader::load_interactive(const String &p_path) { +Ref ResourceFormatLoader::load_interactive(const String &p_path, Error *r_error) { //either this - Ref res = load(p_path); + Ref res = load(p_path,p_path,r_error); if (res.is_null()) return Ref(); @@ -115,12 +115,13 @@ Ref ResourceFormatLoader::load_interactive(const Stri return ril; } -RES ResourceFormatLoader::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoader::load(const String &p_path, const String& p_original_path, Error *r_error) { + String path=p_path; //or this must be implemented - Ref ril = load_interactive(p_path); + Ref ril = load_interactive(p_path,r_error); if (!ril.is_valid()) return RES(); ril->set_local_path(p_original_path); @@ -130,9 +131,14 @@ RES ResourceFormatLoader::load(const String &p_path,const String& p_original_pat Error err = ril->poll(); if (err==ERR_FILE_EOF) { + if (r_error) + *r_error=OK; return ril->get_resource(); } + if (r_error) + *r_error=err; + ERR_FAIL_COND_V(err!=OK,RES()); } @@ -140,7 +146,7 @@ RES ResourceFormatLoader::load(const String &p_path,const String& p_original_pat } -void ResourceFormatLoader::get_dependencies(const String& p_path,List *p_dependencies) { +void ResourceFormatLoader::get_dependencies(const String& p_path, List *p_dependencies, bool p_add_types) { //do nothing by default } @@ -149,7 +155,10 @@ void ResourceFormatLoader::get_dependencies(const String& p_path,List *p /////////////////////////////////// -RES ResourceLoader::load(const String &p_path,const String& p_type_hint,bool p_no_cache) { +RES ResourceLoader::load(const String &p_path, const String& p_type_hint, bool p_no_cache, Error *r_error) { + + if (r_error) + *r_error=ERR_CANT_OPEN; String local_path; if (p_path.is_rel_path()) @@ -183,7 +192,7 @@ RES ResourceLoader::load(const String &p_path,const String& p_type_hint,bool p_n if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; found=true; - RES res = loader[i]->load(remapped_path,local_path); + RES res = loader[i]->load(remapped_path,local_path,r_error); if (res.is_null()) continue; if (!p_no_cache) @@ -289,9 +298,11 @@ String ResourceLoader::find_complete_path(const String& p_path,const String& p_t return local_path; } -Ref ResourceLoader::load_interactive(const String &p_path,const String& p_type_hint,bool p_no_cache) { +Ref ResourceLoader::load_interactive(const String &p_path,const String& p_type_hint,bool p_no_cache,Error *r_error) { + if (r_error) + *r_error=ERR_CANT_OPEN; String local_path; if (p_path.is_rel_path()) @@ -327,7 +338,7 @@ Ref ResourceLoader::load_interactive(const String &p_ if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; found=true; - Ref ril = loader[i]->load_interactive(remapped_path); + Ref ril = loader[i]->load_interactive(remapped_path,r_error); if (ril.is_null()) continue; if (!p_no_cache) @@ -352,7 +363,7 @@ void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_l loader[loader_count++]=p_format_loader; } -void ResourceLoader::get_dependencies(const String& p_path,List *p_dependencies) { +void ResourceLoader::get_dependencies(const String& p_path, List *p_dependencies, bool p_add_types) { String local_path; @@ -372,11 +383,40 @@ void ResourceLoader::get_dependencies(const String& p_path,List *p_depen //if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) // continue; - loader[i]->get_dependencies(remapped_path,p_dependencies); + loader[i]->get_dependencies(remapped_path,p_dependencies,p_add_types); } } +Error ResourceLoader::rename_dependencies(const String &p_path,const Map& p_map) { + + + String local_path; + if (p_path.is_rel_path()) + local_path="res://"+p_path; + else + local_path = Globals::get_singleton()->localize_path(p_path); + + String remapped_path = PathRemap::get_singleton()->get_remap(local_path); + + String extension=remapped_path.extension(); + + for (int i=0;irecognize(extension)) + continue; + //if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) + // continue; + + return loader[i]->rename_dependencies(p_path,p_map); + + } + + return OK; // ?? + +} + + String ResourceLoader::guess_full_filename(const String &p_path,const String& p_type) { String local_path; @@ -414,6 +454,9 @@ String ResourceLoader::get_resource_type(const String &p_path) { ResourceLoadErrorNotify ResourceLoader::err_notify=NULL; void *ResourceLoader::err_notify_ud=NULL; +DependencyErrorNotify ResourceLoader::dep_err_notify=NULL; +void *ResourceLoader::dep_err_notify_ud=NULL; + bool ResourceLoader::abort_on_missing_resource=true; bool ResourceLoader::timestamp_on_load=false; diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index d25727f19f9..00a05dcb430 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -57,21 +57,23 @@ public: class ResourceFormatLoader { public: - virtual Ref load_interactive(const String &p_path); - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual Ref load_interactive(const String &p_path,Error *r_error=NULL); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const=0; virtual void get_recognized_extensions_for_type(const String& p_type,List *p_extensions) const; bool recognize(const String& p_extension) const; virtual bool handles_type(const String& p_type) const=0; virtual String get_resource_type(const String &p_path) const=0; - virtual void get_dependencies(const String& p_path,List *p_dependencies); + virtual void get_dependencies(const String& p_path,List *p_dependencies,bool p_add_types=false); virtual Error load_import_metadata(const String &p_path, Ref& r_var) const { return ERR_UNAVAILABLE; } + virtual Error rename_dependencies(const String &p_path,const Map& p_map) { return OK; } virtual ~ResourceFormatLoader() {} }; typedef void (*ResourceLoadErrorNotify)(void *p_ud,const String& p_text); +typedef void (*DependencyErrorNotify)(void *p_ud,const String& p_loading,const String& p_which,const String& p_type); class ResourceLoader { @@ -86,6 +88,8 @@ class ResourceLoader { static void* err_notify_ud; static ResourceLoadErrorNotify err_notify; + static void* dep_err_notify_ud; + static DependencyErrorNotify dep_err_notify; static bool abort_on_missing_resource; static String find_complete_path(const String& p_path,const String& p_type); @@ -93,14 +97,15 @@ public: - static Ref load_interactive(const String &p_path,const String& p_type_hint="",bool p_no_cache=false); - static RES load(const String &p_path,const String& p_type_hint="",bool p_no_cache=false); + static Ref load_interactive(const String &p_path,const String& p_type_hint="",bool p_no_cache=false,Error *r_error=NULL); + static RES load(const String &p_path,const String& p_type_hint="",bool p_no_cache=false,Error *r_error=NULL); static Ref load_import_metadata(const String &p_path); static void get_recognized_extensions_for_type(const String& p_type,List *p_extensions); static void add_resource_format_loader(ResourceFormatLoader *p_format_loader); static String get_resource_type(const String &p_path); - static void get_dependencies(const String& p_path,List *p_dependencies); + static void get_dependencies(const String& p_path,List *p_dependencies,bool p_add_types=false); + static Error rename_dependencies(const String &p_path,const Map& p_map); static String guess_full_filename(const String &p_path,const String& p_type); @@ -108,6 +113,11 @@ public: static void notify_load_error(const String& p_err) { if (err_notify) err_notify(err_notify_ud,p_err); } static void set_error_notify_func(void* p_ud,ResourceLoadErrorNotify p_err_notify) { err_notify=p_err_notify; err_notify_ud=p_ud;} + + static void notify_dependency_error(const String& p_path,const String& p_dependency,const String& p_type) { if (dep_err_notify) dep_err_notify(dep_err_notify_ud,p_path,p_dependency,p_type); } + static void set_dependency_error_notify_func(void* p_ud,DependencyErrorNotify p_err_notify) { dep_err_notify=p_err_notify; dep_err_notify_ud=p_ud;} + + static void set_abort_on_missing_resources(bool p_abort) { abort_on_missing_resource=p_abort; } static bool get_abort_on_missing_resources() { return abort_on_missing_resource; } }; diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h index 05cbe7f98e7..8382b65290a 100644 --- a/core/io/resource_saver.h +++ b/core/io/resource_saver.h @@ -46,7 +46,7 @@ public: virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0)=0; virtual bool recognize(const RES& p_resource) const=0; virtual void get_recognized_extensions(const RES& p_resource,List *p_extensions) const=0; - + virtual ~ResourceFormatSaver() {} }; diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp index c32b25c4075..020d1682080 100644 --- a/core/io/translation_loader_po.cpp +++ b/core/io/translation_loader_po.cpp @@ -30,7 +30,10 @@ #include "os/file_access.h" #include "translation.h" -RES TranslationLoaderPO::load(const String &p_path,const String& p_original_path) { +RES TranslationLoaderPO::load(const String &p_path, const String& p_original_path, Error *r_error) { + + if (r_error) + *r_error=ERR_CANT_OPEN; FileAccess *f=FileAccess::open(p_path,FileAccess::READ); ERR_FAIL_COND_V(!f,RES()); @@ -49,6 +52,8 @@ RES TranslationLoaderPO::load(const String &p_path,const String& p_original_path String msg_id; String msg_str; String config; + if (r_error) + *r_error=ERR_FILE_CORRUPT; Ref translation = Ref( memnew( Translation )); int line = 1; @@ -174,6 +179,8 @@ RES TranslationLoaderPO::load(const String &p_path,const String& p_original_path } } + if (r_error) + *r_error=OK; return translation; diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h index 9d8ad97a29b..e07ae15e288 100644 --- a/core/io/translation_loader_po.h +++ b/core/io/translation_loader_po.h @@ -34,7 +34,7 @@ class TranslationLoaderPO : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/core/io/zip.h b/core/io/zip.h index cca06c2ee80..85f93568c99 100644 --- a/core/io/zip.h +++ b/core/io/zip.h @@ -39,6 +39,8 @@ #ifndef _zip12_H #define _zip12_H +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/core/io/zip_io.h b/core/io/zip_io.h index c4b4d6b34d6..dd3c371a4aa 100644 --- a/core/io/zip_io.h +++ b/core/io/zip_io.h @@ -34,6 +34,7 @@ #include "os/file_access.h" #include "os/copymem.h" + static void* zipio_open(void* data, const char* p_fname, int mode) { FileAccess *&f = *(FileAccess**)data; diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index c2917145737..a64b3d27151 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -746,6 +746,25 @@ bool ObjectTypeDB::has_method(StringName p_type,StringName p_method,bool p_no_in } +bool ObjectTypeDB::get_setter_and_type_for_property(const StringName& p_class, const StringName& p_prop, StringName& r_class, StringName& r_setter) { + + TypeInfo *type=types.getptr(p_class); + TypeInfo *check=type; + while(check) { + + if (check->property_setget.has(p_prop)) { + r_class=check->name; + r_setter=check->property_setget[p_prop].setter; + return true; + } + + check=check->inherits_ptr; + } + + return false; + +} + #ifdef DEBUG_METHODS_ENABLED MethodBind* ObjectTypeDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind , const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) { StringName mdname=method_name.name; diff --git a/core/object_type_db.h b/core/object_type_db.h index caa5baddd5a..bfa0f921e50 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -475,7 +475,9 @@ public: static void get_integer_constant_list(const StringName& p_type, List *p_constants, bool p_no_inheritance=false); static int get_integer_constant(const StringName& p_type, const StringName &p_name, bool *p_success=NULL); static StringName get_category(const StringName& p_node); - + + static bool get_setter_and_type_for_property(const StringName& p_class, const StringName& p_prop, StringName& r_class, StringName& r_setter); + static void set_type_enabled(StringName p_type,bool p_enable); static bool is_type_enabled(StringName p_type); diff --git a/core/os/input.cpp b/core/os/input.cpp index 2b939ede464..cf2938f5cd1 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -271,6 +271,38 @@ void InputDefault::parse_input_event(const InputEvent& p_event) { mouse_button_mask|=(1<input_event(ev); + } + } break; + case InputEvent::MOUSE_MOTION: { + + if (main_loop && emulate_touch && p_event.mouse_motion.button_mask&1) { + InputEventScreenDrag drag_event; + drag_event.index=0; + drag_event.x=p_event.mouse_motion.x; + drag_event.y=p_event.mouse_motion.y; + drag_event.relative_x=p_event.mouse_motion.relative_x; + drag_event.relative_y=p_event.mouse_motion.relative_y; + drag_event.speed_x=p_event.mouse_motion.speed_x; + drag_event.speed_y=p_event.mouse_motion.speed_y; + + InputEvent ev; + ev.type=InputEvent::SCREEN_DRAG; + ev.screen_drag=drag_event; + + main_loop->input_event(ev); + } + } break; case InputEvent::JOYSTICK_BUTTON: { @@ -362,8 +394,19 @@ void InputDefault::action_release(const StringName& p_action){ } } +void InputDefault::set_emulate_touch(bool p_emulate) { + + emulate_touch=p_emulate; +} + +bool InputDefault::is_emulating_touchscreen() const { + + return emulate_touch; +} + InputDefault::InputDefault() { mouse_button_mask=0; + emulate_touch=false; main_loop=NULL; } diff --git a/core/os/input.h b/core/os/input.h index ce14c2166ed..5c69ced825f 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -78,6 +78,8 @@ public: void get_argument_options(const StringName& p_function,int p_idx,List*r_options) const; + virtual bool is_emulating_touchscreen() const=0; + Input(); }; @@ -99,6 +101,8 @@ class InputDefault : public Input { Vector2 mouse_pos; MainLoop *main_loop; + bool emulate_touch; + struct SpeedTrack { uint64_t last_tick; @@ -147,6 +151,9 @@ public: void iteration(float p_step); + void set_emulate_touch(bool p_emulate); + virtual bool is_emulating_touchscreen() const; + InputDefault(); }; diff --git a/core/os/os.cpp b/core/os/os.cpp index efcd492230f..2db926e5565 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -31,7 +31,7 @@ #include #include "dir_access.h" #include "globals.h" - +#include "input.h" OS* OS::singleton=NULL; @@ -363,7 +363,7 @@ Error OS::set_cwd(const String& p_cwd) { bool OS::has_touchscreen_ui_hint() const { //return false; - return GLOBAL_DEF("display/emulate_touchscreen",false); + return Input::get_singleton() && Input::get_singleton()->is_emulating_touchscreen(); } int OS::get_free_static_memory() const { diff --git a/core/os/os.h b/core/os/os.h index e8ecfa10548..d89734d7d38 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -155,7 +155,7 @@ public: virtual int get_screen_count() const{ return 1; } virtual int get_current_screen() const { return 0; } virtual void set_current_screen(int p_screen) { } - virtual Point2 get_screen_position(int p_screen=0) { return Point2(); } + virtual Point2 get_screen_position(int p_screen=0) const { return Point2(); } virtual Size2 get_screen_size(int p_screen=0) const { return get_window_size(); } virtual Point2 get_window_position() const { return Vector2(); } virtual void set_window_position(const Point2& p_position) {} diff --git a/core/typedefs.h b/core/typedefs.h index ae1eb1f5e77..6ca31fd1374 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -41,8 +41,8 @@ #define _MKSTR(m_x) _STR(m_x) #endif // have to include version.h for this to work, include it in the .cpp not the .h -#define VERSION_MKSTRING _MKSTR(VERSION_MAJOR)"."_MKSTR(VERSION_MINOR)"."_MKSTR(VERSION_STATUS)"."_MKSTR(VERSION_REVISION) -#define VERSION_FULL_NAME _MKSTR(VERSION_NAME)" v"VERSION_MKSTRING +#define VERSION_MKSTRING _MKSTR(VERSION_MAJOR)"." _MKSTR(VERSION_MINOR)"." _MKSTR(VERSION_STATUS)"." _MKSTR(VERSION_REVISION) +#define VERSION_FULL_NAME _MKSTR(VERSION_NAME)" v" VERSION_MKSTRING #ifndef _ALWAYS_INLINE_ diff --git a/core/ustring.cpp b/core/ustring.cpp index 3cfc1e4a3c0..ff7c8984fad 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -3048,6 +3048,37 @@ bool String::is_valid_identifier() const { //kind of poor should be rewritten properly +String String::world_wrap(int p_chars_per_line) const { + + int from=0; + int last_space=0; + String ret; + for(int i=0;i=p_chars_per_line) { + if (last_space==-1) { + ret+=substr(from,i-from+1)+"\n"; + } else { + ret+=substr(from,last_space-from)+"\n"; + i=last_space; //rewind + } + from=i+1; + last_space=-1; + } else if (operator[](i)==' ' || operator[](i)=='\t') { + last_space=i; + } else if (operator[](i)=='\n') { + ret+=substr(from,i-from); + from=i+1; + last_space=-1; + } + } + + if (fromget_type()+":"+itos(_get_obj().obj->get_instance_ID())+"]"; - else + } else return "[Object:null]"; } break; diff --git a/demos/2d/platformer/engine.cfg b/demos/2d/platformer/engine.cfg index 50b6b862e97..cf679cedea4 100644 --- a/demos/2d/platformer/engine.cfg +++ b/demos/2d/platformer/engine.cfg @@ -4,14 +4,17 @@ name="Platformer" main_scene="res://stage.xml" icon="res://icon.png" name_es="Plataformero" +target_fps="60" [display] width=800 height=480 -stretch_2d=false -stretch_mode="viewport" -stretch_aspect="keep" +#stretch_2d=false +#stretch_mode="viewport" +#stretch_aspect="keep" +stretch_mode="2d" +stretch_aspect="keep_height" [image_loader] diff --git a/drivers/chibi/event_stream_chibi.cpp b/drivers/chibi/event_stream_chibi.cpp index e87e0a9aaae..ecb5c3f22bf 100644 --- a/drivers/chibi/event_stream_chibi.cpp +++ b/drivers/chibi/event_stream_chibi.cpp @@ -779,8 +779,10 @@ EventStreamChibi::EventStreamChibi() { -RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderChibi::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; String el = p_path.extension().to_lower(); CPFileAccessWrapperImpl f; @@ -791,6 +793,8 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina CPLoader_IT loader(&f); CPLoader::Error err = loader.load_song(p_path.utf8().get_data(),&esc->song,false); ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); + if (r_error) + *r_error=OK; return esc; @@ -800,6 +804,8 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina CPLoader_XM loader(&f); CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); + if (r_error) + *r_error=OK; return esc; } else if (el=="s3m") { @@ -808,6 +814,9 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina CPLoader_S3M loader(&f); CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); + if (r_error) + *r_error=OK; + return esc; } else if (el=="mod") { @@ -816,6 +825,8 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina CPLoader_MOD loader(&f); CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); + if (r_error) + *r_error=OK; return esc; } diff --git a/drivers/chibi/event_stream_chibi.h b/drivers/chibi/event_stream_chibi.h index 7b2ee4b4713..b564c160184 100644 --- a/drivers/chibi/event_stream_chibi.h +++ b/drivers/chibi/event_stream_chibi.h @@ -301,7 +301,7 @@ public: class ResourceFormatLoaderChibi : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/drivers/dds/texture_loader_dds.cpp b/drivers/dds/texture_loader_dds.cpp index 8e6c3b62e6f..9b2e401fd94 100644 --- a/drivers/dds/texture_loader_dds.cpp +++ b/drivers/dds/texture_loader_dds.cpp @@ -64,8 +64,10 @@ static const DDSFormatInfo dds_format_info[DDS_MAX]={ }; -RES ResourceFormatDDS::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatDDS::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=ERR_CANT_OPEN; Error err; FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); @@ -73,6 +75,8 @@ RES ResourceFormatDDS::load(const String &p_path,const String& p_original_path) return RES(); FileAccessRef fref(f); + if (r_error) + *r_error=ERR_FILE_CORRUPT; ERR_EXPLAIN("Unable to open DDS texture file: "+p_path); ERR_FAIL_COND_V(err!=OK,RES()); @@ -427,6 +431,10 @@ RES ResourceFormatDDS::load(const String &p_path,const String& p_original_path) Ref texture = memnew( ImageTexture ); texture->create_from_image(img); + if (r_error) + *r_error=OK; + + return texture; } diff --git a/drivers/dds/texture_loader_dds.h b/drivers/dds/texture_loader_dds.h index 18a14850737..c8b3610063b 100644 --- a/drivers/dds/texture_loader_dds.h +++ b/drivers/dds/texture_loader_dds.h @@ -7,7 +7,7 @@ class ResourceFormatDDS : public ResourceFormatLoader{ public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 157f2e398b5..d57512c9363 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -132,18 +132,18 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a SL::BlockNode *bnode=(SL::BlockNode*)p_node; //variables - code+="{"ENDL; + code+="{" ENDL; for(Map::Element *E=bnode->variables.front();E;E=E->next()) { - code+=_mktab(p_level)+_typestr(E->value())+" "+replace_string(E->key())+";"ENDL; + code+=_mktab(p_level)+_typestr(E->value())+" "+replace_string(E->key())+";" ENDL; } for(int i=0;istatements.size();i++) { - code+=_mktab(p_level)+dump_node_code(bnode->statements[i],p_level)+";"ENDL; + code+=_mktab(p_level)+dump_node_code(bnode->statements[i],p_level)+";" ENDL; } - code+="}"ENDL; + code+="}" ENDL; } break; case SL::Node::TYPE_VARIABLE: { @@ -489,15 +489,15 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a SL::ControlFlowNode *cfnode=(SL::ControlFlowNode*)p_node; if (cfnode->flow_op==SL::FLOW_OP_IF) { - code+="if ("+dump_node_code(cfnode->statements[0],p_level)+") {"ENDL; + code+="if ("+dump_node_code(cfnode->statements[0],p_level)+") {" ENDL; code+=dump_node_code(cfnode->statements[1],p_level+1); if (cfnode->statements.size()==3) { - code+="} else {"ENDL; + code+="} else {" ENDL; code+=dump_node_code(cfnode->statements[2],p_level+1); } - code+="}"ENDL; + code+="}" ENDL; } else if (cfnode->flow_op==SL::FLOW_OP_RETURN) { @@ -560,7 +560,7 @@ Error ShaderCompilerGLES2::compile_node(SL::ProgramNode *p_program) { ubase=uniforms->size(); for(Map::Element *E=p_program->uniforms.front();E;E=E->next()) { - String uline="uniform "+_typestr(E->get().type)+" _"+E->key().operator String()+";"ENDL; + String uline="uniform "+_typestr(E->get().type)+" _"+E->key().operator String()+";" ENDL; global_code+=uline; if (uniforms) { @@ -593,10 +593,10 @@ Error ShaderCompilerGLES2::compile_node(SL::ProgramNode *p_program) { header+=_typestr(fnode->arguments[i].type)+" "+replace_string(fnode->arguments[i].name); } - header+=") {"ENDL; + header+=") {" ENDL; String fcode=header; fcode+=dump_node_code(fnode->body,1); - fcode+="}"ENDL; + fcode+="}" ENDL; global_code+=fcode; } @@ -605,7 +605,7 @@ Error ShaderCompilerGLES2::compile_node(SL::ProgramNode *p_program) { StringName varname=E->key(); String newvarname=replace_string(varname); - global_code+="uniform "+_typestr(E->get())+" "+newvarname+";"ENDL; + global_code+="uniform "+_typestr(E->get())+" "+newvarname+";" ENDL; }*/ code=dump_node_code(p_program,0); diff --git a/drivers/mpc/audio_stream_mpc.cpp b/drivers/mpc/audio_stream_mpc.cpp index cd8125c9af9..67f21f922c0 100644 --- a/drivers/mpc/audio_stream_mpc.cpp +++ b/drivers/mpc/audio_stream_mpc.cpp @@ -366,8 +366,9 @@ AudioStreamMPC::~AudioStreamMPC() { -RES ResourceFormatLoaderAudioStreamMPC::load(const String &p_path,const String& p_original_path) { - +RES ResourceFormatLoaderAudioStreamMPC::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=OK; //streamed so it will always work.. AudioStreamMPC *mpc_stream = memnew(AudioStreamMPC); mpc_stream->set_file(p_path); return Ref(mpc_stream); diff --git a/drivers/mpc/audio_stream_mpc.h b/drivers/mpc/audio_stream_mpc.h index fa949acd008..8fb0ed13de4 100644 --- a/drivers/mpc/audio_stream_mpc.h +++ b/drivers/mpc/audio_stream_mpc.h @@ -88,7 +88,7 @@ public: class ResourceFormatLoaderAudioStreamMPC : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/drivers/pvr/texture_loader_pvr.cpp b/drivers/pvr/texture_loader_pvr.cpp index 5268b953f4d..eb67dad8cf0 100644 --- a/drivers/pvr/texture_loader_pvr.cpp +++ b/drivers/pvr/texture_loader_pvr.cpp @@ -22,8 +22,10 @@ enum PVRFLags { -RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path,Error *r_error) { + if (r_error) + *r_error=ERR_CANT_OPEN; Error err; FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); @@ -34,6 +36,8 @@ RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path) ERR_FAIL_COND_V(err,RES()); + if (r_error) + *r_error=ERR_FILE_CORRUPT; uint32_t hsize = f->get_32(); @@ -135,6 +139,9 @@ RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path) Ref texture = memnew( ImageTexture ); texture->create_from_image(image,tex_flags); + if (r_error) + *r_error=OK; + return texture; } diff --git a/drivers/pvr/texture_loader_pvr.h b/drivers/pvr/texture_loader_pvr.h index ad86660aa16..735cb2b48bd 100644 --- a/drivers/pvr/texture_loader_pvr.h +++ b/drivers/pvr/texture_loader_pvr.h @@ -9,7 +9,7 @@ class ResourceFormatPVR : public ResourceFormatLoader{ public: - virtual RES load(const String &p_path,const String& p_original_path); + virtual RES load(const String &p_path,const String& p_original_path,Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/drivers/speex/audio_stream_speex.cpp b/drivers/speex/audio_stream_speex.cpp index bcf4c515f80..2cffb170494 100644 --- a/drivers/speex/audio_stream_speex.cpp +++ b/drivers/speex/audio_stream_speex.cpp @@ -530,7 +530,10 @@ AudioStreamSpeex::~AudioStreamSpeex() { unload(); } -RES ResourceFormatLoaderAudioStreamSpeex::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderAudioStreamSpeex::load(const String &p_path, const String& p_original_path, Error *r_error) { + + if (r_error) + *r_error=OK; AudioStreamSpeex *stream = memnew(AudioStreamSpeex); stream->set_file(p_path); diff --git a/drivers/speex/audio_stream_speex.h b/drivers/speex/audio_stream_speex.h index 9557ebe0b81..f9e0fce6660 100644 --- a/drivers/speex/audio_stream_speex.h +++ b/drivers/speex/audio_stream_speex.h @@ -91,7 +91,7 @@ public: class ResourceFormatLoaderAudioStreamSpeex : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/drivers/theora/video_stream_theora.h b/drivers/theora/video_stream_theora.h index b408f9db136..12aac731fc6 100644 --- a/drivers/theora/video_stream_theora.h +++ b/drivers/theora/video_stream_theora.h @@ -102,7 +102,7 @@ public: class ResourceFormatLoaderVideoStreamTheora : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/drivers/theoraplayer/src/YUV/libyuv/src/cpu_id.cc b/drivers/theoraplayer/src/YUV/libyuv/src/cpu_id.cc index f52bd955518..aac7390b32c 100755 --- a/drivers/theoraplayer/src/YUV/libyuv/src/cpu_id.cc +++ b/drivers/theoraplayer/src/YUV/libyuv/src/cpu_id.cc @@ -174,7 +174,7 @@ int cpu_info_ = kCpuInit; // cpu_info is not initialized yet. #if !defined(__native_client__) && !defined(_M_ARM) static LIBYUV_BOOL TestEnv(const char* name) { -#ifndef _WINRT +#if !defined(_WINRT) && !defined(ORBIS_ENABLED) const char* var = getenv(name); if (var) { if (var[0] != '0') { diff --git a/drivers/theoraplayer/video_stream_theoraplayer.cpp b/drivers/theoraplayer/video_stream_theoraplayer.cpp index ef1f5651ab3..876cac3425c 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.cpp +++ b/drivers/theoraplayer/video_stream_theoraplayer.cpp @@ -525,7 +525,9 @@ VideoStreamTheoraplayer::VideoStreamTheoraplayer() { }; -RES ResourceFormatLoaderVideoStreamTheoraplayer::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderVideoStreamTheoraplayer::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=OK; VideoStreamTheoraplayer *stream = memnew(VideoStreamTheoraplayer); stream->set_file(p_path); diff --git a/drivers/theoraplayer/video_stream_theoraplayer.h b/drivers/theoraplayer/video_stream_theoraplayer.h index d43c12609fe..69cae7c4a26 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.h +++ b/drivers/theoraplayer/video_stream_theoraplayer.h @@ -54,7 +54,7 @@ public: class ResourceFormatLoaderVideoStreamTheoraplayer : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/drivers/vorbis/audio_stream_ogg_vorbis.cpp index 249059e2c1f..ee9ba8da4d5 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp +++ b/drivers/vorbis/audio_stream_ogg_vorbis.cpp @@ -385,7 +385,9 @@ AudioStreamOGGVorbis::~AudioStreamOGGVorbis() { -RES ResourceFormatLoaderAudioStreamOGGVorbis::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderAudioStreamOGGVorbis::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=OK; AudioStreamOGGVorbis *ogg_stream = memnew(AudioStreamOGGVorbis); ogg_stream->set_file(p_path); diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.h b/drivers/vorbis/audio_stream_ogg_vorbis.h index 8a35fc09cbf..5e3649d9803 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.h +++ b/drivers/vorbis/audio_stream_ogg_vorbis.h @@ -111,7 +111,7 @@ public: class ResourceFormatLoaderAudioStreamOGGVorbis : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/main/main.cpp b/main/main.cpp index 19ee1c115fc..452e95660fb 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -75,7 +75,7 @@ #include "core/io/file_access_zip.h" #include "translation.h" #include "version.h" - +#include "os/input.h" #include "performance.h" static Globals *globals=NULL; @@ -94,11 +94,15 @@ static FileAccessNetworkClient *file_access_network_client=NULL; static TranslationServer *translation_server = NULL; static OS::VideoMode video_mode; +static bool init_maximized=false; +static bool init_fullscreen=false; +static bool init_use_custom_pos=false; +static Vector2 init_custom_pos; static int video_driver_idx=-1; static int audio_driver_idx=-1; static String locale; -static bool init_maximized=false; + static int init_screen=-1; static String unescape_cmdline(const String& p_str) { @@ -136,8 +140,10 @@ void Main::print_help(const char* p_binary) { } OS::get_singleton()->print(")\n"); - OS::get_singleton()->print("\t-r WIDTHxHEIGHT\t : Request Screen Resolution\n"); + OS::get_singleton()->print("\t-r WIDTHxHEIGHT\t : Request Window Resolution\n"); + OS::get_singleton()->print("\t-p XxY\t : Request Window Position\n"); OS::get_singleton()->print("\t-f\t\t : Request Fullscreen\n"); + OS::get_singleton()->print("\t-mx\t\t Request Maximized\n"); OS::get_singleton()->print("\t-vd DRIVER\t : Video Driver ("); for (int i=0;iget_video_driver_count();i++) { @@ -311,7 +317,37 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas } - + } else if (I->get()=="-p") { // position + + if (I->next()) { + + String vm=I->next()->get(); + + if (vm.find("x")==-1) { // invalid parameter format + + goto error; + + + } + + int x=vm.get_slice("x",0).to_int(); + int y=vm.get_slice("x",1).to_int(); + + init_custom_pos=Point2(x,y); + init_use_custom_pos=true; + force_res=true; + + N=I->next()->next(); + } else { + goto error; + + + } + + + } else if (I->get()=="-mx") { // video driver + + init_maximized=true; } else if (I->get()=="-vd") { // video driver if (I->next()) { @@ -383,7 +419,8 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas } else if (I->get()=="-f") { // fullscreen - video_mode.fullscreen=true; + //video_mode.fullscreen=false; + init_fullscreen=true; } else if (I->get()=="-e" || I->get()=="-editor") { // fonud editor editor=true; @@ -785,6 +822,14 @@ Error Main::setup2() { OS::get_singleton()->initialize(video_mode,video_driver_idx,audio_driver_idx); + if (init_use_custom_pos) { + OS::get_singleton()->set_window_position(init_custom_pos); + } + if (init_maximized) { + OS::get_singleton()->set_window_maximized(true); + } else if (init_fullscreen) { + OS::get_singleton()->set_window_fullscreen(true); + } register_core_singletons(); @@ -801,17 +846,29 @@ Error Main::setup2() { if (init_maximized) { OS::get_singleton()->set_window_maximized(true); } + MAIN_PRINT("Main: Load Remaps"); + + path_remap->load_remaps(); if (show_logo) { //boot logo! String boot_logo_path=GLOBAL_DEF("application/boot_splash",String()); bool boot_logo_scale=GLOBAL_DEF("application/boot_splash_fullsize",true); Globals::get_singleton()->set_custom_property_info("application/boot_splash",PropertyInfo(Variant::STRING,"application/boot_splash",PROPERTY_HINT_FILE,"*.png")); - + print_line("BOOT SPLASH: "+boot_logo_path); Image boot_logo; - if (boot_logo_path.strip_edges()!="" && FileAccess::exists(boot_logo_path)) { - boot_logo.load(boot_logo_path); + boot_logo_path = boot_logo_path.strip_edges(); + print_line("BOOT SPLASH IS : "+boot_logo_path); + + if (boot_logo_path!=String() /*&& FileAccess::exists(boot_logo_path)*/) { + Error err = boot_logo.load(boot_logo_path); + if (err!=OK) { + print_line("ËRROR LOADING BOOT LOGO SPLASH :"+boot_logo_path); + } else { + print_line("BOOT SPLASH OK!"); + + } } if (!boot_logo.empty()) { @@ -822,7 +879,7 @@ Error Main::setup2() { VisualServer::get_singleton()->set_boot_image(boot_logo, boot_bg,boot_logo_scale); #ifndef TOOLS_ENABLED //no tools, so free the boot logo (no longer needed) - Globals::get_singleton()->set("application/boot_logo",Image()); + // Globals::get_singleton()->set("application/boot_logo",Image()); #endif } else { @@ -847,10 +904,16 @@ Error Main::setup2() { GLOBAL_DEF("application/icon",String()); Globals::get_singleton()->set_custom_property_info("application/icon",PropertyInfo(Variant::STRING,"application/icon",PROPERTY_HINT_FILE,"*.png,*.webp")); + if (bool(GLOBAL_DEF("display/emulate_touchscreen",false))) { + if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) { + //only if no touchscreen ui hint, set emulation + InputDefault *id = Input::get_singleton()->cast_to(); + if (id) + id->set_emulate_touch(true); + } + } MAIN_PRINT("Main: Load Remaps"); - path_remap->load_remaps(); - MAIN_PRINT("Main: Load Scene Types"); register_scene_types(); diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 7cb9882f3ac..0d986e92a25 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -998,6 +998,44 @@ static bool _guess_identifier_type_in_block(GDCompletionContext& context,int p_l return false; } + +static bool _guess_identifier_from_assignment_in_function(GDCompletionContext& context,const StringName& p_identifier, const StringName& p_function,GDCompletionIdentifier &r_type) { + + const GDParser::FunctionNode* func=NULL; + for(int i=0;ifunctions.size();i++) { + if (context._class->functions[i]->name==p_function) { + func=context._class->functions[i]; + break; + } + } + + if (!func) + return false; + + for(int i=0;ibody->statements.size();i++) { + + + + if (func->body->statements[i]->type==GDParser::BlockNode::TYPE_OPERATOR) { + const GDParser::OperatorNode *op = static_cast(func->body->statements[i]); + if (op->op==GDParser::OperatorNode::OP_ASSIGN) { + + if (op->arguments.size() && op->arguments[0]->type==GDParser::Node::TYPE_IDENTIFIER) { + + const GDParser::IdentifierNode *id = static_cast(op->arguments[0]); + + if (id->name==p_identifier) { + + return _guess_expression_type(context,op->arguments[1],func->body->statements[i]->line,r_type); + } + } + } + } + } + + return false; +} + static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) { //go to block first @@ -1089,8 +1127,22 @@ static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const r_type=_get_type_from_pinfo(context._class->variables[i]._export); return true; } else if (context._class->variables[i].expression) { - return _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type); + + bool rtype = _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type); + if (rtype && r_type.type!=Variant::NIL) + return true; + //return _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type); } + + //try to guess from assignment in construtor or _ready + if (_guess_identifier_from_assignment_in_function(context,p_identifier,"_ready",r_type)) + return true; + if (_guess_identifier_from_assignment_in_function(context,p_identifier,"_enter_tree",r_type)) + return true; + if (_guess_identifier_from_assignment_in_function(context,p_identifier,"_init",r_type)) + return true; + + return false; } } } diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index f7aaaf7ee5c..9c39051b7f9 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -170,6 +170,7 @@ void GDParser::_make_completable_call(int p_arg) { completion_line=tokenizer->get_token_line(); completion_argument=p_arg; completion_block=current_block; + completion_found=true; tokenizer->advance(); } @@ -190,6 +191,7 @@ bool GDParser::_get_completable_identifier(CompletionType p_type,StringName& ide completion_function=current_function; completion_line=tokenizer->get_token_line(); completion_block=current_block; + completion_found=true; tokenizer->advance(); if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) { @@ -1414,6 +1416,24 @@ GDParser::Node* GDParser::_parse_and_reduce_expression(Node *p_parent,bool p_sta return expr; } +bool GDParser::_recover_from_completion() { + + if (!completion_found) { + return false; //can't recover if no completion + } + //skip stuff until newline + while(tokenizer->get_token()!=GDTokenizer::TK_NEWLINE && tokenizer->get_token()!=GDTokenizer::TK_EOF && tokenizer->get_token()!=GDTokenizer::TK_ERROR) { + tokenizer->advance(); + } + completion_found=false; + error_set=false; + if(tokenizer->get_token() == GDTokenizer::TK_ERROR){ + error_set = true; + } + + return true; +} + void GDParser::_parse_block(BlockNode *p_block,bool p_static) { int indent_level = tab_level.back()->get(); @@ -1511,8 +1531,14 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { Node *subexpr=NULL; subexpr = _parse_and_reduce_expression(p_block,p_static); - if (!subexpr) + if (!subexpr) { + if (_recover_from_completion()) { + break; + } return; + } + + lv->assign=subexpr; assigned=subexpr; @@ -1543,8 +1569,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { tokenizer->advance(); Node *condition = _parse_and_reduce_expression(p_block,p_static); - if (!condition) + if (!condition) { + if (_recover_from_completion()) { + break; + } return; + } ControlFlowNode *cf_if = alloc_node(); @@ -1598,8 +1628,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { //condition Node *condition = _parse_and_reduce_expression(p_block,p_static); - if (!condition) + if (!condition) { + if (_recover_from_completion()) { + break; + } return; + } cf_else->arguments.push_back(condition); cf_else->cf_type=ControlFlowNode::CF_IF; @@ -1660,8 +1694,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { tokenizer->advance(); Node *condition = _parse_and_reduce_expression(p_block,p_static); - if (!condition) + if (!condition) { + if (_recover_from_completion()) { + break; + } return; + } ControlFlowNode *cf_while = alloc_node(); @@ -1706,8 +1744,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { tokenizer->advance(); Node *container = _parse_and_reduce_expression(p_block,p_static); - if (!container) + if (!container) { + if (_recover_from_completion()) { + break; + } return; + } ControlFlowNode *cf_for = alloc_node(); @@ -1771,8 +1813,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { } else { //expect expression Node *retexpr = _parse_and_reduce_expression(p_block,p_static); - if (!retexpr) + if (!retexpr) { + if (_recover_from_completion()) { + break; + } return; + } cf_return->arguments.push_back(retexpr); p_block->statements.push_back(cf_return); if (!_end_statement()) { @@ -1787,8 +1833,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { tokenizer->advance(); Node *condition = _parse_and_reduce_expression(p_block,p_static); - if (!condition) + if (!condition) { + if (_recover_from_completion()) { + break; + } return; + } AssertNode *an = alloc_node(); an->condition=condition; p_block->statements.push_back(an); @@ -1801,8 +1851,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { default: { Node *expression = _parse_and_reduce_expression(p_block,p_static,false,true); - if (!expression) + if (!expression) { + if (_recover_from_completion()) { + break; + } return; + } p_block->statements.push_back(expression); if (!_end_statement()) { _set_error("Expected end of statement after expression."); @@ -2625,14 +2679,18 @@ void GDParser::_parse_class(ClassNode *p_class) { Node *subexpr=NULL; - subexpr = _parse_and_reduce_expression(p_class,false); - if (!subexpr) + subexpr = _parse_and_reduce_expression(p_class,false,autoexport); + if (!subexpr) { + if (_recover_from_completion()) { + break; + } return; + } member.expression=subexpr; if (autoexport) { - if (subexpr->type==Node::TYPE_ARRAY) { + if (1)/*(subexpr->type==Node::TYPE_ARRAY) { member._export.type=Variant::ARRAY; @@ -2640,7 +2698,7 @@ void GDParser::_parse_class(ClassNode *p_class) { member._export.type=Variant::DICTIONARY; - } else { + } else*/ { if (subexpr->type!=Node::TYPE_CONSTANT) { @@ -2756,8 +2814,12 @@ void GDParser::_parse_class(ClassNode *p_class) { Node *subexpr=NULL; subexpr = _parse_and_reduce_expression(p_class,true,true); - if (!subexpr) + if (!subexpr) { + if (_recover_from_completion()) { + break; + } return; + } if (subexpr->type!=Node::TYPE_CONSTANT) { _set_error("Expected constant expression"); @@ -2852,6 +2914,7 @@ Error GDParser::parse_bytecode(const Vector &p_bytecode,const String& p completion_class=NULL; completion_function=NULL; completion_block=NULL; + completion_found=false; current_block=NULL; current_class=NULL; current_function=NULL; @@ -2874,6 +2937,7 @@ Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_ju completion_class=NULL; completion_function=NULL; completion_block=NULL; + completion_found=false; current_block=NULL; current_class=NULL; @@ -2917,6 +2981,8 @@ void GDParser::clear() { current_block=NULL; current_class=NULL; + completion_found=false; + current_function=NULL; validating=false; diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h index fd8a2576fa3..134279b6d82 100644 --- a/modules/gdscript/gd_parser.h +++ b/modules/gdscript/gd_parser.h @@ -419,10 +419,12 @@ private: BlockNode *completion_block; int completion_line; int completion_argument; + bool completion_found; PropertyInfo current_export; void _set_error(const String& p_error, int p_line=-1, int p_column=-1); + bool _recover_from_completion(); bool _parse_arguments(Node* p_parent, Vector& p_args, bool p_static, bool p_can_codecomplete=false); diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index 53ae0c87021..99ddc74bb4b 100644 --- a/modules/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -2710,7 +2710,10 @@ GDScriptLanguage::~GDScriptLanguage() { /*************** RESOURCE ***************/ -RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderGDScript::load(const String &p_path, const String& p_original_path, Error *r_error) { + + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; GDScript *script = memnew( GDScript ); @@ -2742,6 +2745,8 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_orig script->reload(); } + if (r_error) + *r_error=OK; return scriptres; } diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index fe325ff71e1..37ef47af6c0 100644 --- a/modules/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -557,7 +557,7 @@ public: class ResourceFormatLoaderGDScript : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/platform/android/detect.py b/platform/android/detect.py index 76575a1ec6b..fce1fe3ed6c 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -173,8 +173,7 @@ def configure(env): env.Append(LDPATH=[ld_path]) env.Append(LIBS=['OpenSLES']) # env.Append(LIBS=['c','m','stdc++','log','EGL','GLESv1_CM','GLESv2','OpenSLES','supc++','android']) - if (env["ndk_platform"]!="2.2"): - env.Append(LIBS=['EGL','OpenSLES','android']) + env.Append(LIBS=['EGL','OpenSLES','android']) env.Append(LIBS=['c','m','stdc++','log','GLESv1_CM','GLESv2', 'z']) env["LINKFLAGS"]= string.split(" -g --sysroot="+ld_sysroot+" -Wl,--no-undefined -Wl,-z,noexecstack ") diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp index da3a37fb42f..ff70d5ae764 100644 --- a/platform/android/file_access_android.cpp +++ b/platform/android/file_access_android.cpp @@ -29,16 +29,16 @@ #include "file_access_android.h" #include "print_string.h" -#ifdef ANDROID_NATIVE_ACTIVITY + AAssetManager *FileAccessAndroid::asset_manager=NULL; -void FileAccessAndroid::make_default() { +/*void FileAccessAndroid::make_default() { create_func=create_android; -} +}*/ FileAccess* FileAccessAndroid::create_android() { @@ -46,7 +46,7 @@ FileAccess* FileAccessAndroid::create_android() { } -Error FileAccessAndroid::open(const String& p_path, int p_mode_flags) { +Error FileAccessAndroid::_open(const String& p_path, int p_mode_flags) { String path=fix_path(p_path).simplify_path(); if (path.begins_with("/")) @@ -55,7 +55,6 @@ Error FileAccessAndroid::open(const String& p_path, int p_mode_flags) { path=path.substr(6,path.length()); - ERR_FAIL_COND_V(p_mode_flags&FileAccess::WRITE,ERR_UNAVAILABLE); //can't write on android.. a=AAssetManager_open(asset_manager,path.utf8().get_data(),AASSET_MODE_STREAMING); if (!a) @@ -184,4 +183,4 @@ FileAccessAndroid::~FileAccessAndroid() { close(); } -#endif + diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h index f477920ae99..506c2c023fc 100644 --- a/platform/android/file_access_android.h +++ b/platform/android/file_access_android.h @@ -29,14 +29,13 @@ #ifndef FILE_ACCESS_ANDROID_H #define FILE_ACCESS_ANDROID_H -#ifdef ANDROID_NATIVE_ACTIVITY #include "os/file_access.h" #include #include #include -#include +//#include class FileAccessAndroid : public FileAccess { @@ -51,7 +50,7 @@ public: static AAssetManager *asset_manager; - virtual Error open(const String& p_path, int p_mode_flags); ///< open a file + virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open @@ -71,12 +70,13 @@ public: virtual bool file_exists(const String& p_path); ///< return true if a file exists + virtual uint64_t _get_modified_time(const String& p_file) { return 0; } - static void make_default(); + //static void make_default(); FileAccessAndroid(); ~FileAccessAndroid(); }; #endif // FILE_ACCESS_ANDROID_H -#endif + diff --git a/platform/android/file_access_jandroid.cpp b/platform/android/file_access_jandroid.cpp index 971d4f84ab2..be38d806b2f 100644 --- a/platform/android/file_access_jandroid.cpp +++ b/platform/android/file_access_jandroid.cpp @@ -62,13 +62,15 @@ Error FileAccessJAndroid::_open(const String& p_path, int p_mode_flags) { JNIEnv *env = ThreadAndroid::get_env(); - //OS::get_singleton()->print("env: %p, io %p, fo: %p\n",env,io,_file_open); jstring js = env->NewStringUTF(path.utf8().get_data()); int res = env->CallIntMethod(io,_file_open,js,p_mode_flags&WRITE?true:false); env->DeleteLocalRef(js); + OS::get_singleton()->print("fopen: '%s' ret %i\n",path.utf8().get_data(),res); + + if (res<=0) return ERR_FILE_CANT_OPEN; id=res; diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java index 9b9b1ab2ada..4c5a3135764 100644 --- a/platform/android/java/src/com/android/godot/Godot.java +++ b/platform/android/java/src/com/android/godot/Godot.java @@ -357,7 +357,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC Log.d("GODOT"," " + command_line[w]); } }*/ - GodotLib.initialize(this,io.needsReloadHooks(),command_line); + GodotLib.initialize(this,io.needsReloadHooks(),command_line,getAssets()); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); diff --git a/platform/android/java/src/com/android/godot/GodotIO.java b/platform/android/java/src/com/android/godot/GodotIO.java index addceb15286..a7dc0c2f756 100644 --- a/platform/android/java/src/com/android/godot/GodotIO.java +++ b/platform/android/java/src/com/android/godot/GodotIO.java @@ -94,6 +94,7 @@ public class GodotIO { //System.out.printf("file_open: Attempt to Open %s\n",path); + //Log.v("MyApp", "TRYING TO OPEN FILE: " + path); if (write) return -1; @@ -105,7 +106,7 @@ public class GodotIO { } catch (Exception e) { - //System.out.printf("Exception on file_open: %s\n",e); + //System.out.printf("Exception on file_open: %s\n",path); return -1; } @@ -113,7 +114,7 @@ public class GodotIO { ad.len=ad.is.available(); } catch (Exception e) { - System.out.printf("Exception availabling on file_open: %s\n",e); + System.out.printf("Exception availabling on file_open: %s\n",path); return -1; } diff --git a/platform/android/java/src/com/android/godot/GodotLib.java b/platform/android/java/src/com/android/godot/GodotLib.java index 71c31e9f836..f099e0feffd 100644 --- a/platform/android/java/src/com/android/godot/GodotLib.java +++ b/platform/android/java/src/com/android/godot/GodotLib.java @@ -44,7 +44,7 @@ public class GodotLib { * @param height the current view height */ - public static native void initialize(Godot p_instance,boolean need_reload_hook,String[] p_cmdline); + public static native void initialize(Godot p_instance,boolean need_reload_hook,String[] p_cmdline,Object p_asset_manager); public static native void resize(int width, int height,boolean reload); public static native void newcontext(); public static native void quit(); diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index 31582547811..d001cface2e 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -33,13 +33,14 @@ #include "main/main.h" #include #include "file_access_jandroid.h" +#include "file_access_android.h" #include "dir_access_jandroid.h" #include "audio_driver_jandroid.h" #include "globals.h" #include "thread_jandroid.h" #include "core/os/keyboard.h" #include "java_class_wrapper.h" - +#include "android/asset_manager_jni.h" static JavaClassWrapper *java_class_wrapper=NULL; static OS_Android *os_android=NULL; @@ -764,7 +765,7 @@ static void _stop_video() { env->CallVoidMethod(godot_io, _stopVideo); } -JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline) { +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline,jobject p_asset_manager) { __android_log_print(ANDROID_LOG_INFO,"godot","**INIT EVENT! - %p\n",env); @@ -820,7 +821,14 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, } ThreadAndroid::make_default(jvm); +#ifdef USE_JAVA_FILE_ACCESS FileAccessJAndroid::setup(gob); +#else + + jobject amgr = env->NewGlobalRef(p_asset_manager); + + FileAccessAndroid::asset_manager=AAssetManager_fromJava(env,amgr); +#endif DirAccessJAndroid::setup(gob); AudioDriverAndroid::setup(gob); } diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h index 57a4cc8651f..9410fe71324 100644 --- a/platform/android/java_glue.h +++ b/platform/android/java_glue.h @@ -36,7 +36,7 @@ extern "C" { - JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline,jobject p_asset_manager); JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_resize(JNIEnv * env, jobject obj, jint width, jint height, jboolean reload); JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_newcontext(JNIEnv * env, jobject obj); JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_step(JNIEnv * env, jobject obj); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 612148418b1..e2ff128f0d9 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -37,6 +37,8 @@ #include "servers/visual/visual_server_wrap_mt.h" #include "main/main.h" +#include "file_access_android.h" + #include "core/globals.h" #ifdef ANDROID_NATIVE_ACTIVITY @@ -89,8 +91,14 @@ void OS_Android::initialize_core() { if (use_apk_expansion) FileAccess::make_default(FileAccess::ACCESS_RESOURCES); - else + else { +#ifdef USE_JAVA_FILE_ACCESS FileAccess::make_default >(FileAccess::ACCESS_RESOURCES); +#else + //FileAccess::make_default >(FileAccess::ACCESS_RESOURCES); + FileAccess::make_default(FileAccess::ACCESS_RESOURCES); +#endif + } FileAccess::make_default(FileAccess::ACCESS_USERDATA); FileAccess::make_default(FileAccess::ACCESS_FILESYSTEM); //FileAccessBufferedFA::make_default(); diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 7a5a55653f1..e9b0d001965 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -41,6 +41,9 @@ #include "servers/visual/rasterizer.h" +//#ifdef USE_JAVA_FILE_ACCESS + + #ifdef ANDROID_NATIVE_ACTIVITY #include diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm index 3c79137171f..d5764b2b5cd 100644 --- a/platform/iphone/app_delegate.mm +++ b/platform/iphone/app_delegate.mm @@ -43,6 +43,11 @@ #import #endif +#ifdef MODULE_PARSE_ENABLED +#import +#import "FBSDKCoreKit/FBSDKCoreKit.h" +#endif + #define kFilteringFactor 0.1 #define kRenderingFrequency 60 #define kAccelerometerFrequency 100.0 // Hz @@ -139,8 +144,9 @@ static int frame_count = 0; ++frame_count; // this might be necessary before here - for (NSString* key in [[NSBundle mainBundle] infoDictionary]) { - NSObject* value = [[[NSBundle mainBundle] infoDictionary] objectForKey:key]; + NSDictionary* dict = [[NSBundle mainBundle] infoDictionary]; + for (NSString* key in dict) { + NSObject* value = [dict objectForKey:key]; String ukey = String::utf8([key UTF8String]); // we need a NSObject to Variant conversor @@ -341,6 +347,15 @@ static int frame_count = 0; // For 4.2+ support - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { +#ifdef MODULE_PARSE_ENABLED + NSLog(@"Handling application openURL"); + return [[FBSDKApplicationDelegate sharedInstance] application:application + openURL:url + sourceApplication:sourceApplication + annotation:annotation]; +#endif + + #ifdef MODULE_FACEBOOKSCORER_IOS_ENABLED return [[[FacebookScorer sharedInstance] facebook] handleOpenURL:url]; #else @@ -348,6 +363,32 @@ static int frame_count = 0; #endif } +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { +#ifdef MODULE_PARSE_ENABLED + // Store the deviceToken in the current installation and save it to Parse. + PFInstallation *currentInstallation = [PFInstallation currentInstallation]; + //NSString* token = [[NSString alloc] initWithData:deviceToken encoding:NSUTF8StringEncoding]; + NSLog(@"Device Token : %@ ", deviceToken); + [currentInstallation setDeviceTokenFromData:deviceToken]; + [currentInstallation saveInBackground]; +#endif +} + +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { +#ifdef MODULE_PARSE_ENABLED + [PFPush handlePush:userInfo]; + NSDictionary *aps = [userInfo objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + NSLog(@"Push Notification Payload (app active) %@", aps); + [defaults setObject:aps forKey:@"notificationInfo"]; + [defaults synchronize]; + if (application.applicationState == UIApplicationStateInactive) { + [PFAnalytics trackAppOpenedWithRemoteNotificationPayload:userInfo]; + } +#endif +} + - (void)dealloc { [window release]; diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index fb57876a838..6be3539b9d0 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -59,7 +59,7 @@ def configure(env): env.Append(CPPFLAGS=['-DNEED_LONG_INT']) env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON']) else: - env['CCFLAGS'] = string.split('-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -MMD -MT dependencies -isysroot $IPHONESDK') + env['CCFLAGS'] = string.split('-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=5.1.1 -MMD -MT dependencies -isysroot $IPHONESDK') if (env["bits"]=="64"): env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=5.1.1', @@ -80,7 +80,7 @@ def configure(env): '-framework', 'CoreMedia', ]) else: - env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=4.3', + env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=5.1.1', '-isysroot', '$IPHONESDK', '-framework', 'Foundation', '-framework', 'UIKit', diff --git a/platform/iphone/gl_view.h b/platform/iphone/gl_view.h index c58c8635107..cda75394dbb 100755 --- a/platform/iphone/gl_view.h +++ b/platform/iphone/gl_view.h @@ -34,7 +34,7 @@ #import #import -#define USE_CADISPLAYLINK 1 //iOS version 3.1+ is required +#define USE_CADISPLAYLINK 0 //iOS version 3.1+ is required @protocol GLViewDelegate; diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm index e3ba6bbd73c..f689123c812 100644 --- a/platform/iphone/in_app_store.mm +++ b/platform/iphone/in_app_store.mm @@ -28,6 +28,10 @@ /*************************************************************************/ #ifdef STOREKIT_ENABLED +#ifdef MODULE_FUSEBOXX_ENABLED +#import "modules/fuseboxx/ios/FuseSDK.h" +#endif + #include "in_app_store.h" extern "C" { @@ -222,6 +226,11 @@ Error InAppStore::request_product_info(Variant p_params) { else{ [pending_transactions setObject:transaction forKey:transaction.payment.productIdentifier]; } + + #ifdef MODULE_FUSEBOXX_ENABLED + printf("Registering transaction on Fuseboxx!\n"); + [FuseSDK registerInAppPurchase: transaction]; + #endif } break; case SKPaymentTransactionStateFailed: { printf("status transaction failed!\n"); diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 5703cbc5465..22cee0527e6 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -11,15 +11,17 @@ def get_name(): def can_build(): - if (sys.platform != "darwin"): - return False + if (sys.platform == "darwin" or os.environ.has_key("OSXCROSS_ROOT")): + return True - return True # osx enabled + + return False def get_opts(): return [ ('force_64_bits','Force 64 bits binary','no'), + ('osxcross_sdk','OSXCross SDK version','darwin14'), ] @@ -59,12 +61,31 @@ def configure(env): env.Append(CPPPATH=['#tools/freetype']) env.Append(CPPPATH=['#tools/freetype/freetype/include']) - if (env["bits"]=="64"): - env.Append(CCFLAGS=['-arch', 'x86_64']) - env.Append(LINKFLAGS=['-arch', 'x86_64']) + + + if (not os.environ.has_key("OSXCROSS_ROOT")): + #regular native build + if (env["bits"]=="64"): + env.Append(CCFLAGS=['-arch', 'x86_64']) + env.Append(LINKFLAGS=['-arch', 'x86_64']) + else: + env.Append(CCFLAGS=['-arch', 'i386']) + env.Append(LINKFLAGS=['-arch', 'i386']) else: - env.Append(CCFLAGS=['-arch', 'i386']) - env.Append(LINKFLAGS=['-arch', 'i386']) + #osxcross build + root=os.environ.get("OSXCROSS_ROOT",0) + if env["bits"]=="64": + basecmd=root+"/target/bin/x86_64-apple-"+env["osxcross_sdk"]+"-" + else: + basecmd=root+"/target/bin/i386-apple-"+env["osxcross_sdk"]+"-" + + + env['CC'] = basecmd+"cc" + env['CXX'] = basecmd+"c++" + env['AR'] = basecmd+"ar" + env['RANLIB'] = basecmd+"ranlib" + env['AS'] = basecmd+"as" + # env.Append(CPPPATH=['#platform/osx/include/freetype2', '#platform/osx/include']) # env.Append(LIBPATH=['#platform/osx/lib']) diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 144037b1cbe..869997f190d 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -170,7 +170,7 @@ public: virtual int get_screen_count() const; virtual int get_current_screen() const; virtual void set_current_screen(int p_screen); - virtual Point2 get_screen_position(int p_screen=0); + virtual Point2 get_screen_position(int p_screen=0) const; virtual Point2 get_window_position() const; virtual void set_window_position(const Point2& p_position); virtual void set_window_size(const Size2 p_size); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 72699366c4d..abfe42beda8 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1279,7 +1279,7 @@ void OS_OSX::set_current_screen(int p_screen) { current_screen = p_screen; }; -Point2 OS_OSX::get_screen_position(int p_screen) { +Point2 OS_OSX::get_screen_position(int p_screen) const { ERR_FAIL_INDEX_V(p_screen, screens.size(), Point2()); return screens[p_screen].pos; diff --git a/platform/x11/detect.py b/platform/x11/detect.py index ff85e286db3..b8890a3a2f8 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -126,7 +126,9 @@ def configure(env): env.ParseConfig('pkg-config x11 --cflags --libs') env.ParseConfig('pkg-config xinerama --cflags --libs') env.ParseConfig('pkg-config xcursor --cflags --libs') - env.ParseConfig('pkg-config openssl --cflags --libs') + + if (env["openssl"]=="yes"): + env.ParseConfig('pkg-config openssl --cflags --libs') env.ParseConfig('pkg-config freetype2 --cflags --libs') diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index b34d1ba7c8c..51f4392eb4f 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -441,6 +441,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi net_wm_icon = XInternAtom(x11_display, "_NET_WM_ICON", False); + //printf("got map notify\n"); } @@ -504,6 +505,23 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { mouse_mode=p_mode; if (mouse_mode==MOUSE_MODE_CAPTURED) { + + while(true) { + //flush pending motion events + + if (XPending(x11_display) > 0) { + XEvent event; + XPeekEvent(x11_display, &event); + if (event.type==MotionNotify) { + XNextEvent(x11_display,&event); + } else { + break; + } + } else { + break; + } + } + if (XGrabPointer(x11_display, x11_window, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, @@ -518,6 +536,8 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { 0,0,0,0, (int)center.x, (int)center.y); input->set_mouse_pos(center); + } else { + do_mouse_warp=false; } } @@ -652,17 +672,24 @@ void OS_X11::set_current_screen(int p_screen) { } Point2 OS_X11::get_screen_position(int p_screen) const { + // Using Xinerama Extension int event_base, error_base; const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); - if( !ext_okay ) return Point2i(0,0); + if( !ext_okay ) { + return Point2i(0,0); + } int count; XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count); - if( p_screen >= count ) return Point2i(0,0); + if( p_screen >= count ) { + return Point2i(0,0); + } Point2i position = Point2i(xsi[p_screen].x_org, xsi[p_screen].y_org); + XFree(xsi); + return position; } @@ -696,6 +723,7 @@ Point2 OS_X11::get_window_position() const { void OS_X11::set_window_position(const Point2& p_position) { // Using EWMH -- Extended Window Manager Hints // to get the size of the decoration +#if 0 Atom property = XInternAtom(x11_display,"_NET_FRAME_EXTENTS", True); Atom type; int format; @@ -738,6 +766,9 @@ void OS_X11::set_window_position(const Point2& p_position) { top -= screen_position.y; XMoveWindow(x11_display,x11_window,p_position.x - left,p_position.y - top); +#else + XMoveWindow(x11_display,x11_window,p_position.x,p_position.y); +#endif } Size2 OS_X11::get_window_size() const { @@ -1131,7 +1162,7 @@ void OS_X11::process_xevents() { //printf("checking events %i\n", XPending(x11_display)); - bool do_mouse_warp=false; + do_mouse_warp=false; while (XPending(x11_display) > 0) { XEvent event; @@ -1244,8 +1275,38 @@ void OS_X11::process_xevents() { } break; case MotionNotify: { - + + // FUCK YOU X11 API YOU SERIOUSLY GROSS ME OUT + // YOU ARE AS GROSS AS LOOKING AT A PUTRID PILE + // OF POOP STICKING OUT OF A CLOGGED TOILET + // HOW THE FUCK I AM SUPPOSED TO KNOW WHICH ONE + // OF THE MOTION NOTIFY EVENTS IS THE ONE GENERATED + // BY WARPING THE MOUSE POINTER? + // YOU ARE FORCING ME TO FILTER ONE BY ONE TO FIND IT + // PLEASE DO ME A FAVOR AND DIE DROWNED IN A FECAL + // MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG. + + while(true) { + if (mouse_mode==MOUSE_MODE_CAPTURED && event.xmotion.x==current_videomode.width/2 && event.xmotion.y==current_videomode.height/2) { + //this is likely the warp event since it was warped here + center=Vector2(event.xmotion.x,event.xmotion.y); + break; + } + + if (XPending(x11_display) > 0) { + XEvent tevent; + XPeekEvent(x11_display, &tevent); + if (tevent.type==MotionNotify) { + XNextEvent(x11_display,&event); + } else { + break; + } + } else { + break; + } + } + last_timestamp=event.xmotion.time; // Motion is also simple. diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 261a54dd254..12f0aec611a 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -114,6 +114,7 @@ class OS_X11 : public OS_Unix { bool minimized; int dpad_last[2]; + bool do_mouse_warp; const char *cursor_theme; int cursor_size; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index c521952f9b1..6705cebf379 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -322,8 +322,8 @@ void Sprite::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v")); - ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); - ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes")); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes")); ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 58cbbdba22a..ff35837bc0c 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -83,15 +83,25 @@ real_t Area::get_gravity() const{ return gravity; } +void Area::set_linear_damp(real_t p_linear_damp){ -void Area::set_density(real_t p_density){ - - density=p_density; - PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_DENSITY,p_density); + linear_damp=p_linear_damp; + PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_LINEAR_DAMP,p_linear_damp); } -real_t Area::get_density() const{ +real_t Area::get_linear_damp() const{ - return density; + return linear_damp; +} + +void Area::set_angular_damp(real_t p_angular_damp){ + + angular_damp=p_angular_damp; + PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_ANGULAR_DAMP,p_angular_damp); +} + +real_t Area::get_angular_damp() const{ + + return angular_damp; } void Area::set_priority(real_t p_priority){ @@ -533,8 +543,11 @@ void Area::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_gravity","gravity"),&Area::set_gravity); ObjectTypeDB::bind_method(_MD("get_gravity"),&Area::get_gravity); - ObjectTypeDB::bind_method(_MD("set_density","density"),&Area::set_density); - ObjectTypeDB::bind_method(_MD("get_density"),&Area::get_density); + ObjectTypeDB::bind_method(_MD("set_angular_damp","angular_damp"),&Area::set_angular_damp); + ObjectTypeDB::bind_method(_MD("get_angular_damp"),&Area::get_angular_damp); + + ObjectTypeDB::bind_method(_MD("set_linear_damp","linear_damp"),&Area::set_linear_damp); + ObjectTypeDB::bind_method(_MD("get_linear_damp"),&Area::get_linear_damp); ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area::set_priority); ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_priority); @@ -571,7 +584,8 @@ void Area::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_gravity"),_SCS("get_gravity")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_linear_damp"),_SCS("get_linear_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_angular_damp"),_SCS("get_angular_damp")); ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable")); @@ -586,7 +600,8 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru set_gravity_vector(Vector3(0,-1,0)); gravity_is_point=false; gravity_distance_scale=0; - density=0.1; + linear_damp=0.1; + angular_damp=1; priority=0; monitoring=false; set_ray_pickable(false); diff --git a/scene/3d/area.h b/scene/3d/area.h index fa7500c47c8..f03955d1e76 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -50,7 +50,8 @@ private: real_t gravity; bool gravity_is_point; real_t gravity_distance_scale; - real_t density; + real_t angular_damp; + real_t linear_damp; int priority; bool monitoring; bool monitorable; @@ -139,8 +140,11 @@ public: void set_gravity(real_t p_gravity); real_t get_gravity() const; - void set_density(real_t p_density); - real_t get_density() const; + void set_angular_damp(real_t p_angular_damp); + real_t get_angular_damp() const; + + void set_linear_damp(real_t p_linear_damp); + real_t get_linear_damp() const; void set_priority(real_t p_priority); real_t get_priority() const; diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 3d5091f6671..d61859a3d06 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -133,6 +133,8 @@ real_t StaticBody::get_bounce() const{ return bounce; } + + void StaticBody::set_constant_linear_velocity(const Vector3& p_vel) { constant_linear_velocity=p_vel; @@ -494,6 +496,42 @@ real_t RigidBody::get_bounce() const{ return bounce; } + +void RigidBody::set_gravity_scale(real_t p_gravity_scale){ + + gravity_scale=p_gravity_scale; + PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_GRAVITY_SCALE,gravity_scale); + +} +real_t RigidBody::get_gravity_scale() const{ + + return gravity_scale; +} + +void RigidBody::set_linear_damp(real_t p_linear_damp){ + + ERR_FAIL_COND(p_linear_damp<-1); + linear_damp=p_linear_damp; + PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_LINEAR_DAMP,linear_damp); + +} +real_t RigidBody::get_linear_damp() const{ + + return linear_damp; +} + +void RigidBody::set_angular_damp(real_t p_angular_damp){ + + ERR_FAIL_COND(p_angular_damp<-1); + angular_damp=p_angular_damp; + PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_ANGULAR_DAMP,angular_damp); + +} +real_t RigidBody::get_angular_damp() const{ + + return angular_damp; +} + void RigidBody::set_axis_velocity(const Vector3& p_axis) { Vector3 v = state? state->get_linear_velocity() : linear_velocity; @@ -685,6 +723,16 @@ void RigidBody::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_angular_velocity","angular_velocity"),&RigidBody::set_angular_velocity); ObjectTypeDB::bind_method(_MD("get_angular_velocity"),&RigidBody::get_angular_velocity); + ObjectTypeDB::bind_method(_MD("set_gravity_scale","gravity_scale"),&RigidBody::set_gravity_scale); + ObjectTypeDB::bind_method(_MD("get_gravity_scale"),&RigidBody::get_gravity_scale); + + ObjectTypeDB::bind_method(_MD("set_linear_damp","linear_damp"),&RigidBody::set_linear_damp); + ObjectTypeDB::bind_method(_MD("get_linear_damp"),&RigidBody::get_linear_damp); + + ObjectTypeDB::bind_method(_MD("set_angular_damp","angular_damp"),&RigidBody::set_angular_damp); + ObjectTypeDB::bind_method(_MD("get_angular_damp"),&RigidBody::get_angular_damp); + + ObjectTypeDB::bind_method(_MD("set_max_contacts_reported","amount"),&RigidBody::set_max_contacts_reported); ObjectTypeDB::bind_method(_MD("get_max_contacts_reported"),&RigidBody::get_max_contacts_reported); @@ -722,6 +770,7 @@ void RigidBody::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_scale",PROPERTY_HINT_RANGE,"-128,128,0.01"),_SCS("set_gravity_scale"),_SCS("get_gravity_scale")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),_SCS("set_use_custom_integrator"),_SCS("is_using_custom_integrator")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"continuous_cd"),_SCS("set_use_continuous_collision_detection"),_SCS("is_using_continuous_collision_detection")); ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),_SCS("set_max_contacts_reported"),_SCS("get_max_contacts_reported")); @@ -731,6 +780,8 @@ void RigidBody::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::INT,"axis_lock",PROPERTY_HINT_ENUM,"Disabled,Lock X,Lock Y,Lock Z"),_SCS("set_axis_lock"),_SCS("get_axis_lock")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"velocity/linear"),_SCS("set_linear_velocity"),_SCS("get_linear_velocity")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"velocity/angular"),_SCS("set_angular_velocity"),_SCS("get_angular_velocity")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"damp_override/linear",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_linear_damp"),_SCS("get_linear_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"damp_override/angular",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_angular_damp"),_SCS("get_angular_damp")); ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape"))); ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape"))); @@ -753,6 +804,10 @@ RigidBody::RigidBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) { max_contacts_reported=0; state=NULL; + gravity_scale=1; + linear_damp=-1; + angular_damp=-1; + //angular_velocity=0; sleeping=false; ccd=false; diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 0ff3b360af1..66490ba9258 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -129,6 +129,10 @@ private: Vector3 linear_velocity; Vector3 angular_velocity; + real_t gravity_scale; + real_t linear_damp; + real_t angular_damp; + bool sleeping; bool ccd; @@ -217,6 +221,16 @@ public: void set_angular_velocity(const Vector3&p_velocity); Vector3 get_angular_velocity() const; + void set_gravity_scale(real_t p_gravity_scale); + real_t get_gravity_scale() const; + + void set_linear_damp(real_t p_linear_damp); + real_t get_linear_damp() const; + + void set_angular_damp(real_t p_angular_damp); + real_t get_angular_damp() const; + + void set_use_custom_integrator(bool p_enable); bool is_using_custom_integrator(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index e9da95f3fb6..c7d1249a07c 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -578,8 +578,8 @@ void Sprite3D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_hframes"),&Sprite3D::get_hframes); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes")); ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 3ddf23fc4a7..0c0f924f522 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -274,7 +274,7 @@ Button* AcceptDialog::add_button(const String& p_text,bool p_right,const String& } if (p_action!="") { - button->connect("pressed",this,"_custom_action",make_binds(p_action)); + button->connect("pressed",this,"_custom_action",varray(p_action)); } return button; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index c29f6625d37..b7b2f061eaf 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -187,6 +187,7 @@ void ItemList::select(int p_idx,bool p_single){ } current=p_idx; + ensure_selected_visible=false; } else { if (items[p_idx].selectable) { @@ -195,6 +196,7 @@ void ItemList::select(int p_idx,bool p_single){ } update(); + } void ItemList::unselect(int p_idx){ @@ -246,12 +248,14 @@ void ItemList::remove_item(int p_idx){ update(); shape_changed=true; + } void ItemList::clear(){ items.clear(); current=-1; + ensure_selected_visible=false; update(); } @@ -602,18 +606,8 @@ void ItemList::_input_event(const InputEvent& p_event) { void ItemList::ensure_current_is_visible() { - if (current>=0 && current <=items.size()) { - - Rect2 r = items[current].rect_cache; - int from = scroll_bar->get_val(); - int to = from + scroll_bar->get_page(); - - if (r.pos.y < from) { - scroll_bar->set_val(r.pos.y); - } else if (r.pos.y+r.size.y > to) { - scroll_bar->set_val(r.pos.y+r.size.y - (to-from)); - } - } + ensure_selected_visible=true; + update(); } void ItemList::_notification(int p_what) { @@ -928,6 +922,24 @@ void ItemList::_notification(int p_what) { draw_line(Vector2(bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),Vector2(size.width-bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),guide_color); } + + if (ensure_selected_visible && current>=0 && current <=items.size()) { + + Rect2 r = items[current].rect_cache; + int from = scroll_bar->get_val(); + int to = from + scroll_bar->get_page(); + + if (r.pos.y < from) { + scroll_bar->set_val(r.pos.y); + } else if (r.pos.y+r.size.y > to) { + scroll_bar->set_val(r.pos.y+r.size.y - (to-from)); + } + + + } + + ensure_selected_visible=false; + } } @@ -1095,6 +1107,7 @@ ItemList::ItemList() { set_focus_mode(FOCUS_ALL); current_columns=1; search_time_msec=0; + ensure_selected_visible=false; } diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 237079c4288..7cf58a64268 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -41,6 +41,8 @@ private: bool shape_changed; + bool ensure_selected_visible; + Vector items; Vector separators; diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 68fcb4bda8c..13ff7074ea9 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -124,7 +124,7 @@ void MenuButton::_set_items(const Array& p_items) { void MenuButton::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_popup"),&MenuButton::get_popup); + ObjectTypeDB::bind_method(_MD("get_popup:PopupMenu"),&MenuButton::get_popup); ObjectTypeDB::bind_method(_MD("_unhandled_key_input"),&MenuButton::_unhandled_key_input); ObjectTypeDB::bind_method(_MD("_set_items"),&MenuButton::_set_items); ObjectTypeDB::bind_method(_MD("_get_items"),&MenuButton::_get_items); diff --git a/scene/gui/patch_9_frame.cpp b/scene/gui/patch_9_frame.cpp new file mode 100644 index 00000000000..b6e261714c3 --- /dev/null +++ b/scene/gui/patch_9_frame.cpp @@ -0,0 +1,132 @@ +#include "patch_9_frame.h" + +#include "servers/visual_server.h" + +void Patch9Frame::_notification(int p_what) { + + if (p_what==NOTIFICATION_DRAW) { + + if (texture.is_null()) + return; + + + Size2 s=get_size(); + RID ci = get_canvas_item(); + VS::get_singleton()->canvas_item_add_style_box(ci,Rect2(Point2(),s),texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate); +// draw_texture_rect(texture,Rect2(Point2(),s),false,modulate); + +/* + Vector points; + points.resize(4); + points[0]=Point2(0,0); + points[1]=Point2(s.x,0); + points[2]=Point2(s.x,s.y); + points[3]=Point2(0,s.y); + Vector uvs; + uvs.resize(4); + uvs[0]=Point2(0,0); + uvs[1]=Point2(1,0); + uvs[2]=Point2(1,1); + uvs[3]=Point2(0,1); + + VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector(),uvs,texture->get_rid()); +*/ + } +} + +Size2 Patch9Frame::get_minimum_size() const { + + return Size2(margin[MARGIN_LEFT]+margin[MARGIN_RIGHT],margin[MARGIN_TOP]+margin[MARGIN_BOTTOM]); +} +void Patch9Frame::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("set_texture","texture"), & Patch9Frame::set_texture ); + ObjectTypeDB::bind_method(_MD("get_texture"), & Patch9Frame::get_texture ); + ObjectTypeDB::bind_method(_MD("set_modulate","modulate"), & Patch9Frame::set_modulate ); + ObjectTypeDB::bind_method(_MD("get_modulate"), & Patch9Frame::get_modulate ); + ObjectTypeDB::bind_method(_MD("set_patch_margin","margin","value"), & Patch9Frame::set_patch_margin ); + ObjectTypeDB::bind_method(_MD("get_patch_margin","margin"), & Patch9Frame::get_patch_margin ); + ObjectTypeDB::bind_method(_MD("set_draw_center","draw_center"), & Patch9Frame::set_draw_center ); + ObjectTypeDB::bind_method(_MD("get_draw_center"), & Patch9Frame::get_draw_center ); + + ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") ); + ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") ); + ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), _SCS("set_draw_center"),_SCS("get_draw_center") ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/left",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_LEFT ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/top",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_TOP ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/right",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_RIGHT ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/bottom",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_BOTTOM ); + +} + + +void Patch9Frame::set_texture(const Ref& p_tex) { + + texture=p_tex; + update(); + //if (texture.is_valid()) + // texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites + minimum_size_changed(); +} + +Ref Patch9Frame::get_texture() const { + + return texture; +} + +void Patch9Frame::set_modulate(const Color& p_tex) { + + modulate=p_tex; + update(); +} + +Color Patch9Frame::get_modulate() const{ + + return modulate; +} + + +void Patch9Frame::set_patch_margin(Margin p_margin,int p_size) { + + ERR_FAIL_INDEX(p_margin,4); + margin[p_margin]=p_size; + update(); + minimum_size_changed(); +} + +int Patch9Frame::get_patch_margin(Margin p_margin) const{ + + ERR_FAIL_INDEX_V(p_margin,4,0); + return margin[p_margin]; +} + +void Patch9Frame::set_draw_center(bool p_draw) { + + draw_center=p_draw; + update(); +} + +bool Patch9Frame::get_draw_center() const{ + + return draw_center; +} + +Patch9Frame::Patch9Frame() { + + + margin[MARGIN_LEFT]=0; + margin[MARGIN_RIGHT]=0; + margin[MARGIN_BOTTOM]=0; + margin[MARGIN_TOP]=0; + modulate=Color(1,1,1,1); + set_ignore_mouse(true); + draw_center=true; +} + + +Patch9Frame::~Patch9Frame() +{ +} + + diff --git a/scene/gui/patch_9_frame.h b/scene/gui/patch_9_frame.h new file mode 100644 index 00000000000..562a5b1d771 --- /dev/null +++ b/scene/gui/patch_9_frame.h @@ -0,0 +1,40 @@ +#ifndef PATCH_9_FRAME_H +#define PATCH_9_FRAME_H + +#include "scene/gui/control.h" +/** + @author Juan Linietsky +*/ +class Patch9Frame : public Control { + + OBJ_TYPE(Patch9Frame,Control); + + bool draw_center; + int margin[4]; + Color modulate; + Ref texture; +protected: + + void _notification(int p_what); + virtual Size2 get_minimum_size() const; + static void _bind_methods(); + +public: + + void set_texture(const Ref& p_tex); + Ref get_texture() const; + + void set_modulate(const Color& p_tex); + Color get_modulate() const; + + void set_patch_margin(Margin p_margin,int p_size); + int get_patch_margin(Margin p_margin) const; + + void set_draw_center(bool p_enable); + bool get_draw_center() const; + + Patch9Frame(); + ~Patch9Frame(); + +}; +#endif // PATCH_9_FRAME_H diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 41e775bbff4..a48136f541e 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -27,7 +27,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "spin_box.h" - +#include "os/input.h" Size2 SpinBox::get_minimum_size() const { @@ -62,6 +62,13 @@ LineEdit *SpinBox::get_line_edit() { } +void SpinBox::_line_edit_input(const InputEvent& p_event) { + + + +} + + void SpinBox::_input_event(const InputEvent& p_event) { if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed) { @@ -94,6 +101,48 @@ void SpinBox::_input_event(const InputEvent& p_event) { } break; } } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) { + + //set_default_cursor_shape(CURSOR_VSIZE); + Vector2 cpos = Vector2(p_event.mouse_button.x,p_event.mouse_button.y); + drag.mouse_pos=cpos; + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) { + + //set_default_cursor_shape(CURSOR_ARROW); + if (drag.enabled) { + drag.enabled=false; + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + warp_mouse(drag.capture_pos); + } + } + + if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_button.button_mask&1) { + + Vector2 cpos = Vector2(p_event.mouse_motion.x,p_event.mouse_motion.y); + if (drag.enabled) { + + float diff_y = drag.mouse_pos.y - cpos.y; + diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y); + diff_y*=0.1; + + drag.mouse_pos=cpos; + drag.base_val=CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max()); + + set_val( drag.base_val); + + } else if (drag.mouse_pos.distance_to(cpos)>2) { + + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); + drag.enabled=true; + drag.base_val=get_val(); + drag.mouse_pos=cpos; + drag.capture_pos=cpos; + + } + } } @@ -177,6 +226,7 @@ void SpinBox::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_editable"),&SpinBox::is_editable); ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit); ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit); + ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable")); @@ -196,4 +246,6 @@ SpinBox::SpinBox() { //connect("value_changed",this,"_value_changed"); line_edit->connect("text_entered",this,"_text_entered",Vector(),CONNECT_DEFERRED); line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector(),CONNECT_DEFERRED); + line_edit->connect("input_event",this,"_line_edit_input"); + drag.enabled=false; } diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 6ebe14631e3..4c8cb8432a2 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -44,6 +44,18 @@ class SpinBox : public Range { String prefix; String suffix; + void _line_edit_input(const InputEvent& p_event); + + + struct Drag { + float base_val; + bool enabled; + Vector2 from; + Vector2 mouse_pos; + Vector2 capture_pos; + } drag; + + void _line_edit_focus_exit(); protected: diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6c15f1cae4f..e639b5cb051 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -31,7 +31,7 @@ #include "os/os.h" #include "os/keyboard.h" #include "globals.h" - +#include "os/input.h" @@ -70,6 +70,7 @@ Size2 TreeItem::Cell::get_icon_size() const { else return icon_region.size; } + void TreeItem::Cell::draw_icon(const RID& p_where, const Point2& p_pos, const Size2& p_size) const{ if (icon.is_null()) @@ -728,14 +729,20 @@ TreeItem::~TreeItem() { tree->root=0; } - if (tree && tree->popup_edited_item==this) + if (tree && tree->popup_edited_item==this) { tree->popup_edited_item=NULL; + tree->pressing_for_editor=false; + + } if (tree && tree->selected_item==this) tree->selected_item=NULL; - if (tree && tree->edited_item==this) + if (tree && tree->edited_item==this) { tree->edited_item=NULL; + tree->pressing_for_editor=false; + } + } @@ -1292,7 +1299,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col } else if (select_mode==SELECT_SINGLE || select_mode==SELECT_MULTI) { - if (&selected_cell==&c) { + if (!r_in_range && &selected_cell==&c) { if (!selected_cell.selected) { @@ -1301,6 +1308,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col selected_item=p_selected; selected_col=i; + emit_signal("cell_selected"); if (select_mode==SELECT_MULTI) emit_signal("multi_selected",p_current,i,true); @@ -1317,6 +1325,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col if (r_in_range && *r_in_range) { + if (!c.selected && c.selectable) { c.selected=true; emit_signal("multi_selected",p_current,i,true); @@ -1467,7 +1476,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ if (select_mode==SELECT_MULTI && p_mod.shift && selected_item && selected_item!=p_item) { bool inrange=false; - print_line("SELECT MULTI AND SHIFT AND ALL"); + select_single_item( p_item, root, col,selected_item,&inrange ); } else { select_single_item( p_item, root, col ); @@ -1490,7 +1499,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ /* editing */ - bool bring_up_editor=c.selected && already_selected; + bool bring_up_editor=c.selected;// && already_selected; bool bring_up_value_editor=false; String editor_text=c.text; @@ -1605,31 +1614,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ return -1; - click_handled=true; + + click_handled=true; popup_edited_item=p_item; popup_edited_item_col=col; - text_editor->set_pos(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset ); - text_editor->set_size( Size2(col_width,item_h)); - text_editor->clear(); - text_editor->set_text( editor_text ); - text_editor->select_all(); - if (bring_up_value_editor) { - - value_editor->set_pos(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset+Point2i(0,text_editor->get_size().height) ); - value_editor->set_size( Size2(col_width,1)); - value_editor->show_modal(); - updating_value_editor=true; - value_editor->set_min( c.min ); - value_editor->set_max( c.max ); - value_editor->set_step( c.step ); - value_editor->set_val( c.val ); - value_editor->set_exp_unit_value( c.expr ); - updating_value_editor=false; - } - - text_editor->show_modal(); - text_editor->grab_focus(); + pressing_item_rect=Rect2(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset,Size2(col_width,item_h)); + pressing_for_editor_text=editor_text; + pressing_for_editor=true; return -1; //select } else { @@ -2062,6 +2054,33 @@ void Tree::_input_event(InputEvent p_event) { update(); } + if (pressing_for_editor && popup_edited_item && popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE) { + //range drag + + if (!range_drag_enabled) { + + Vector2 cpos = Vector2(b.x,b.y); + if (cpos.distance_to(pressing_pos)>2) { + range_drag_enabled=true; + range_drag_capture_pos=cpos; + range_drag_base=popup_edited_item->get_range(popup_edited_item_col); + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); + } + } else { + + TreeItem::Cell &c=popup_edited_item->cells[popup_edited_item_col]; + float diff_y = -b.relative_y; + diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y); + diff_y*=0.1; + range_drag_base=CLAMP(range_drag_base + c.step * diff_y, c.min, c.max); + + popup_edited_item->set_range(popup_edited_item_col,range_drag_base); + item_edited(popup_edited_item_col,popup_edited_item); + + } + + } + if (drag_touching && ! drag_touching_deaccel) { @@ -2084,6 +2103,31 @@ void Tree::_input_event(InputEvent p_event) { if (b.button_index==BUTTON_LEFT) { + if (pressing_for_editor) { + + if (range_drag_enabled) { + + range_drag_enabled=false; + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + warp_mouse(range_drag_capture_pos); + } else { + text_editor->set_pos(pressing_item_rect.pos); + text_editor->set_size(pressing_item_rect.size); + + text_editor->clear(); + text_editor->set_text( pressing_for_editor_text ); + text_editor->select_all(); + + text_editor->show_modal(); + text_editor->grab_focus(); + + } + pressing_for_editor=false; + + } + + + if (cache.click_type==Cache::CLICK_BUTTON) { emit_signal("button_pressed",cache.click_item,cache.click_column,cache.click_id); @@ -2145,11 +2189,15 @@ void Tree::_input_event(InputEvent p_event) { break; click_handled=false; + pressing_for_editor=false; blocked++; bool handled = propagate_mouse_event(pos+cache.offset,0,0,b.doubleclick,root,b.button_index,b.mod); blocked--; + if (pressing_for_editor) { + pressing_pos=Point2(b.x,b.y); + } if (drag_touching) { @@ -2360,6 +2408,11 @@ void Tree::_notification(int p_what) { } } + if (p_what==NOTIFICATION_VISIBILITY_CHANGED) { + + drag_touching=false; + } + if (p_what==NOTIFICATION_ENTER_TREE) { update_cache();; @@ -2610,6 +2663,8 @@ void Tree::clear() { selected_item=NULL; edited_item=NULL; popup_edited_item=NULL; + selected_item=NULL; + pressing_for_editor=false; update(); }; @@ -3184,6 +3239,8 @@ Tree::Tree() { drag_speed=0; drag_touching=false; drag_touching_deaccel=false; + pressing_for_editor=false; + range_drag_enabled=false; } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 8ddddd0630e..3fbd7c95d9b 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -258,7 +258,18 @@ friend class TreeItem; TreeItem *popup_edited_item; TreeItem *selected_item; TreeItem *edited_item; + + int pressed_button; + bool pressing_for_editor; + String pressing_for_editor_text; + Vector2 pressing_pos; + Rect2 pressing_item_rect; + + float range_drag_base; + bool range_drag_enabled; + Vector2 range_drag_capture_pos; + //TreeItem *cursor_item; //int cursor_column; diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp index 8527498fc20..f67d50b56c3 100644 --- a/scene/io/resource_format_image.cpp +++ b/scene/io/resource_format_image.cpp @@ -31,9 +31,11 @@ #include "io/image_loader.h" #include "globals.h" #include "os/os.h" -RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_original_path) { - +RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=ERR_CANT_OPEN; + if (p_path.extension()=="cube") { // open as cubemap txture @@ -83,6 +85,8 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina memdelete(f); cubemap->set_name(p_path.get_file()); + if (r_error) + *r_error=OK; return cubemap; @@ -112,6 +116,8 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina ERR_EXPLAIN("Failed loading image: "+p_path); ERR_FAIL_COND_V(err, RES()); + if (r_error) + *r_error=ERR_FILE_CORRUPT; #ifdef DEBUG_ENABLED #ifdef TOOLS_ENABLED @@ -199,6 +205,9 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina print_line(" -make texture: "+rtos(total)); } + if (r_error) + *r_error=OK; + return RES( texture ); } diff --git a/scene/io/resource_format_image.h b/scene/io/resource_format_image.h index 1af65870f81..b5ec5a12007 100644 --- a/scene/io/resource_format_image.h +++ b/scene/io/resource_format_image.h @@ -40,7 +40,7 @@ class ResourceFormatLoaderImage : public ResourceFormatLoader { int max_texture_size; public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/io/resource_format_wav.cpp b/scene/io/resource_format_wav.cpp index 7c90a4b3cd0..090348c9338 100644 --- a/scene/io/resource_format_wav.cpp +++ b/scene/io/resource_format_wav.cpp @@ -31,13 +31,18 @@ #include "scene/resources/sample.h" -RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderWAV::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; Error err; FileAccess *file=FileAccess::open(p_path, FileAccess::READ,&err); ERR_FAIL_COND_V( err!=OK, RES() ); + if (r_error) + *r_error=ERR_FILE_CORRUPT; + /* CHECK RIFF */ char riff[5]; riff[4]=0; @@ -244,6 +249,9 @@ RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_ file->close(); memdelete(file); + if (r_error) + *r_error=OK; + return sample; } diff --git a/scene/io/resource_format_wav.h b/scene/io/resource_format_wav.h index 081a563d033..a74da041c16 100644 --- a/scene/io/resource_format_wav.h +++ b/scene/io/resource_format_wav.h @@ -33,7 +33,7 @@ class ResourceFormatLoaderWAV : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 717ed93b16a..a53c69815fd 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -52,6 +52,7 @@ #include "scene/gui/option_button.h" #include "scene/gui/color_picker.h" #include "scene/gui/texture_frame.h" +#include "scene/gui/patch_9_frame.h" #include "scene/gui/menu_button.h" #include "scene/gui/check_box.h" #include "scene/gui/check_button.h" @@ -302,6 +303,7 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_virtual_type(); diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp index ef056a6230d..9a6452797a2 100644 --- a/scene/resources/bit_mask.cpp +++ b/scene/resources/bit_mask.cpp @@ -205,7 +205,10 @@ BitMap::BitMap() { ////////////////////////////////////// -RES ResourceFormatLoaderBitMap::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderBitMap::load(const String &p_path, const String& p_original_path, Error *r_error) { + + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; BitMap* ptr = memnew(BitMap); Ref bitmap( ptr ); @@ -219,6 +222,8 @@ RES ResourceFormatLoaderBitMap::load(const String &p_path,const String& p_origin ERR_FAIL_COND_V(err, RES()); bitmap->create_from_image_alpha(image); + if (r_error) + *r_error=OK; return bitmap; diff --git a/scene/resources/bit_mask.h b/scene/resources/bit_mask.h index 29b7bc66f45..a6b29bb919d 100644 --- a/scene/resources/bit_mask.h +++ b/scene/resources/bit_mask.h @@ -66,7 +66,7 @@ class ResourceFormatLoaderBitMap : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index cd0e67f04d9..f1e97fd6267 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -297,7 +297,7 @@ void make_default_theme() { t->set_color("font_color_hover","MenuButton", control_font_color_hover ); t->set_color("font_color_disabled","MenuButton", Color(1,1,1,0.3) ); - t->set_constant("hseparation","MenuButton", 0 ); + t->set_constant("hseparation","MenuButton", 3 ); // CheckBox diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 90598ee789e..a9376faf62f 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -219,7 +219,10 @@ Shader::~Shader() { -RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderShader::load(const String &p_path, const String& p_original_path, Error *r_error) { + + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; String fragment_code; String vertex_code; @@ -235,6 +238,8 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin ERR_FAIL_COND_V(err,RES()); String base_path = p_path.get_base_dir(); + if (r_error) + *r_error=ERR_FILE_CORRUPT; Ref shader;//( memnew( Shader ) ); @@ -435,6 +440,8 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin f->close(); memdelete(f); + if (r_error) + *r_error=OK; return shader; } diff --git a/scene/resources/shader.h b/scene/resources/shader.h index b805cbec96f..61a369c4089 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -126,7 +126,7 @@ public: class ResourceFormatLoaderShader : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 3060fe41b41..651e234b49d 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -601,7 +601,9 @@ Theme::~Theme() -RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderTheme::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=ERR_CANT_OPEN; Error err; FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); @@ -611,6 +613,8 @@ RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_origina String base_path = p_path.get_base_dir(); Ref theme( memnew( Theme ) ); Map library; + if (r_error) + *r_error=ERR_FILE_CORRUPT; bool reading_library=false; int line=0; @@ -1003,6 +1007,9 @@ RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_origina f->close(); memdelete(f); + if (r_error) + *r_error=OK; + return theme; } diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 802dcb099ce..cfa07625952 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -124,7 +124,7 @@ public: class ResourceFormatLoaderTheme : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp index 83be80f8160..e78f0699cb5 100644 --- a/servers/physics/area_sw.cpp +++ b/servers/physics/area_sw.cpp @@ -83,6 +83,10 @@ void AreaSW::set_monitor_callback(ObjectID p_id, const StringName& p_method) { _shape_changed(); + if (!moved_list.in_list() && get_space()) + get_space()->area_add_to_moved_list(&moved_list); + + } void AreaSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method) { @@ -103,6 +107,10 @@ void AreaSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method _shape_changed(); + if (!moved_list.in_list() && get_space()) + get_space()->area_add_to_moved_list(&moved_list); + + } @@ -123,7 +131,8 @@ void AreaSW::set_param(PhysicsServer::AreaParameter p_param, const Variant& p_va case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break; case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break; case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break; - case PhysicsServer::AREA_PARAM_DENSITY: density=p_value; ; break; + case PhysicsServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; ; break; + case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; ; break; case PhysicsServer::AREA_PARAM_PRIORITY: priority=p_value; ; break; } @@ -139,7 +148,8 @@ Variant AreaSW::get_param(PhysicsServer::AreaParameter p_param) const { case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale; case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; - case PhysicsServer::AREA_PARAM_DENSITY: return density; + case PhysicsServer::AREA_PARAM_LINEAR_DAMP: return linear_damp; + case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: return angular_damp; case PhysicsServer::AREA_PARAM_PRIORITY: return priority; } @@ -248,7 +258,8 @@ AreaSW::AreaSW() : CollisionObjectSW(TYPE_AREA), monitor_query_list(this), move gravity_is_point=false; gravity_distance_scale=0; point_attenuation=1; - density=0.1; + angular_damp=1.0; + linear_damp=0.1; priority=0; set_ray_pickable(false); monitor_callback_id=0; diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h index 26d6a177db8..40ccdaf370e 100644 --- a/servers/physics/area_sw.h +++ b/servers/physics/area_sw.h @@ -47,7 +47,8 @@ class AreaSW : public CollisionObjectSW{ bool gravity_is_point; float gravity_distance_scale; float point_attenuation; - float density; + float linear_damp; + float angular_damp; int priority; bool monitorable; @@ -145,8 +146,11 @@ public: _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; } _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; } - _FORCE_INLINE_ void set_density(float p_density) { density=p_density; } - _FORCE_INLINE_ float get_density() const { return density; } + _FORCE_INLINE_ void set_linear_damp(float p_linear_damp) { linear_damp=p_linear_damp; } + _FORCE_INLINE_ float get_linear_damp() const { return linear_damp; } + + _FORCE_INLINE_ void set_angular_damp(float p_angular_damp) { angular_damp=p_angular_damp; } + _FORCE_INLINE_ float get_angular_damp() const { return angular_damp; } _FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; } _FORCE_INLINE_ int get_priority() const { return priority; } @@ -202,6 +206,7 @@ void AreaSW::remove_area_from_query(AreaSW *p_area, uint32_t p_area_shape,uint32 monitored_areas[bk].dec(); if (!monitor_query_list.in_list()) _queue_monitor_update(); + } diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 5a528ecf94d..8edbaf0b89b 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -159,6 +159,17 @@ void BodySW::set_param(PhysicsServer::BodyParameter p_param, float p_value) { _update_inertia(); } break; + case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: { + gravity_scale=p_value; + } break; + case PhysicsServer::BODY_PARAM_LINEAR_DAMP: { + + linear_damp=p_value; + } break; + case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: { + + angular_damp=p_value; + } break; default:{} } } @@ -177,6 +188,18 @@ float BodySW::get_param(PhysicsServer::BodyParameter p_param) const { case PhysicsServer::BODY_PARAM_MASS: { return mass; } break; + case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: { + return gravity_scale; + } break; + case PhysicsServer::BODY_PARAM_LINEAR_DAMP: { + + return linear_damp; + } break; + case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: { + + return angular_damp; + } break; + default:{} } @@ -380,6 +403,8 @@ void BodySW::integrate_forces(real_t p_step) { return; AreaSW *def_area = get_space()->get_default_area(); + AreaSW *damp_area = def_area; + ERR_FAIL_COND(!def_area); int ac = areas.size(); @@ -388,7 +413,7 @@ void BodySW::integrate_forces(real_t p_step) { if (ac) { areas.sort(); const AreaCMP *aa = &areas[0]; - density = aa[ac-1].area->get_density(); + damp_area = aa[ac-1].area; for(int i=ac-1;i>=0;i--) { _compute_area_gravity(aa[i].area); if (aa[i].area->get_space_override_mode() == PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE) { @@ -396,13 +421,25 @@ void BodySW::integrate_forces(real_t p_step) { break; } } - } else { - density=def_area->get_density(); } + if( !replace ) { _compute_area_gravity(def_area); } + gravity*=gravity_scale; + + if (angular_damp>=0) + area_angular_damp=angular_damp; + else + area_angular_damp=damp_area->get_angular_damp(); + + if (linear_damp>=0) + area_linear_damp=linear_damp; + else + area_linear_damp=damp_area->get_linear_damp(); + + Vector3 motion; bool do_motion=false; @@ -431,12 +468,12 @@ void BodySW::integrate_forces(real_t p_step) { force+=applied_force; Vector3 torque=applied_torque; - real_t damp = 1.0 - p_step * density; + real_t damp = 1.0 - p_step * area_linear_damp; if (damp<0) // reached zero in the given time damp=0; - real_t angular_damp = 1.0 - p_step * density * get_space()->get_body_angular_velocity_damp_ratio(); + real_t angular_damp = 1.0 - p_step * area_angular_damp; if (angular_damp<0) // reached zero in the given time angular_damp=0; @@ -695,8 +732,12 @@ BodySW::BodySW() : CollisionObjectSW(TYPE_BODY), active_list(this), inertia_upda island_list_next=NULL; first_time_kinematic=false; _set_static(false); - density=0; + contact_count=0; + gravity_scale=1.0; + + area_angular_damp=0; + area_linear_damp=0; still_time=0; continuous_cd=false; diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index 6491ba8f18c..66d814bfd16 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -50,6 +50,10 @@ class BodySW : public CollisionObjectSW { real_t bounce; real_t friction; + real_t linear_damp; + real_t angular_damp; + real_t gravity_scale; + PhysicsServer::BodyAxisLock axis_lock; real_t _inv_mass; @@ -57,13 +61,16 @@ class BodySW : public CollisionObjectSW { Matrix3 _inv_inertia_tensor; Vector3 gravity; - real_t density; real_t still_time; Vector3 applied_force; Vector3 applied_torque; + float area_angular_damp; + float area_linear_damp; + + SelfList active_list; SelfList inertia_update_list; SelfList direct_state_query_list; @@ -233,7 +240,6 @@ public: _FORCE_INLINE_ Matrix3 get_inv_inertia_tensor() const { return _inv_inertia_tensor; } _FORCE_INLINE_ real_t get_friction() const { return friction; } _FORCE_INLINE_ Vector3 get_gravity() const { return gravity; } - _FORCE_INLINE_ real_t get_density() const { return density; } _FORCE_INLINE_ real_t get_bounce() const { return bounce; } _FORCE_INLINE_ void set_axis_lock(PhysicsServer::BodyAxisLock p_lock) { axis_lock=p_lock; } @@ -335,8 +341,9 @@ public: BodySW *body; real_t step; - virtual Vector3 get_total_gravity() const { return body->get_gravity(); } // get gravity vector working on this body space/area - virtual float get_total_density() const { return body->get_density(); } // get density of this body space/area + virtual Vector3 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area + virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area + virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass virtual Vector3 get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp index 1a41cda4829..a5a132020a1 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/area_2d_sw.cpp @@ -82,6 +82,10 @@ void Area2DSW::set_monitor_callback(ObjectID p_id, const StringName& p_method) { _shape_changed(); + if (!moved_list.in_list() && get_space()) + get_space()->area_add_to_moved_list(&moved_list); + + } void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method) { @@ -102,6 +106,10 @@ void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_meth _shape_changed(); + if (!moved_list.in_list() && get_space()) + get_space()->area_add_to_moved_list(&moved_list); + + } diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index c86bb51f1d8..2fbfcaca600 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -337,9 +337,9 @@ public: Body2DSW *body; real_t step; - virtual Vector2 get_total_gravity() const { return body->get_gravity(); } // get gravity vector working on this body space/area - virtual float get_total_angular_damp() const { return body->get_angular_damp(); } // get density of this body space/area - virtual float get_total_linear_damp() const { return body->get_linear_damp(); } // get density of this body space/area + virtual Vector2 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area + virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area + virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass virtual real_t get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index e02601af416..53409acdfba 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -39,13 +39,18 @@ void PhysicsDirectBodyState::integrate_forces() { Vector3 av = get_angular_velocity(); - float damp = 1.0 - step * get_total_density(); + float linear_damp = 1.0 - step * get_total_linear_damp(); - if (damp<0) // reached zero in the given time - damp=0; + if (linear_damp<0) // reached zero in the given time + linear_damp=0; - lv*=damp; - av*=damp; + float angular_damp = 1.0 - step * get_total_angular_damp(); + + if (angular_damp<0) // reached zero in the given time + angular_damp=0; + + lv*=linear_damp; + av*=angular_damp; set_linear_velocity(lv); set_angular_velocity(av); @@ -70,7 +75,8 @@ PhysicsServer * PhysicsServer::get_singleton() { void PhysicsDirectBodyState::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_total_gravity"),&PhysicsDirectBodyState::get_total_gravity); - ObjectTypeDB::bind_method(_MD("get_total_density"),&PhysicsDirectBodyState::get_total_density); + ObjectTypeDB::bind_method(_MD("get_total_linear_damp"),&PhysicsDirectBodyState::get_total_linear_damp); + ObjectTypeDB::bind_method(_MD("get_total_angular_damp"),&PhysicsDirectBodyState::get_total_angular_damp); ObjectTypeDB::bind_method(_MD("get_inverse_mass"),&PhysicsDirectBodyState::get_inverse_mass); ObjectTypeDB::bind_method(_MD("get_inverse_inertia"),&PhysicsDirectBodyState::get_inverse_inertia); @@ -683,7 +689,8 @@ void PhysicsServer::_bind_methods() { BIND_CONSTANT( AREA_PARAM_GRAVITY_IS_POINT ); BIND_CONSTANT( AREA_PARAM_GRAVITY_DISTANCE_SCALE ); BIND_CONSTANT( AREA_PARAM_GRAVITY_POINT_ATTENUATION ); - BIND_CONSTANT( AREA_PARAM_DENSITY ); + BIND_CONSTANT( AREA_PARAM_LINEAR_DAMP ); + BIND_CONSTANT( AREA_PARAM_ANGULAR_DAMP ); BIND_CONSTANT( AREA_PARAM_PRIORITY ); BIND_CONSTANT( AREA_SPACE_OVERRIDE_COMBINE ); @@ -698,6 +705,9 @@ void PhysicsServer::_bind_methods() { BIND_CONSTANT( BODY_PARAM_BOUNCE ); BIND_CONSTANT( BODY_PARAM_FRICTION ); BIND_CONSTANT( BODY_PARAM_MASS ); + BIND_CONSTANT( BODY_PARAM_GRAVITY_SCALE ); + BIND_CONSTANT( BODY_PARAM_ANGULAR_DAMP ); + BIND_CONSTANT( BODY_PARAM_LINEAR_DAMP ); BIND_CONSTANT( BODY_PARAM_MAX ); BIND_CONSTANT( BODY_STATE_TRANSFORM ); diff --git a/servers/physics_server.h b/servers/physics_server.h index f66ea590b82..b82d4cf5da3 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -41,8 +41,9 @@ protected: static void _bind_methods(); public: - virtual Vector3 get_total_gravity() const=0; // get gravity vector working on this body space/area - virtual float get_total_density() const=0; // get density of this body space/area + virtual Vector3 get_total_gravity() const=0; + virtual float get_total_angular_damp() const=0; + virtual float get_total_linear_damp() const=0; virtual float get_inverse_mass() const=0; // get the mass virtual Vector3 get_inverse_inertia() const=0; // get density of this body space @@ -300,7 +301,8 @@ public: AREA_PARAM_GRAVITY_IS_POINT, AREA_PARAM_GRAVITY_DISTANCE_SCALE, AREA_PARAM_GRAVITY_POINT_ATTENUATION, - AREA_PARAM_DENSITY, + AREA_PARAM_LINEAR_DAMP, + AREA_PARAM_ANGULAR_DAMP, AREA_PARAM_PRIORITY }; @@ -398,6 +400,9 @@ public: BODY_PARAM_BOUNCE, BODY_PARAM_FRICTION, BODY_PARAM_MASS, ///< unused for static, always infinite + BODY_PARAM_GRAVITY_SCALE, + BODY_PARAM_LINEAR_DAMP, + BODY_PARAM_ANGULAR_DAMP, BODY_PARAM_MAX, }; @@ -411,7 +416,7 @@ public: BODY_STATE_LINEAR_VELOCITY, BODY_STATE_ANGULAR_VELOCITY, BODY_STATE_SLEEPING, - BODY_STATE_CAN_SLEEP + BODY_STATE_CAN_SLEEP }; virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant)=0; diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index b51f59050d2..8b47596d7e6 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -7351,6 +7351,8 @@ void VisualServerRaster::_draw_cursors_and_margins() { rasterizer->canvas_draw_rect(Rect2(cursors[i].pos, size), 0, Rect2(), tex, Color(1, 1, 1, 1)); }; + + if (black_image[MARGIN_LEFT].is_valid()) { Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_LEFT]),rasterizer->texture_get_height(black_image[MARGIN_LEFT])); rasterizer->canvas_draw_rect(Rect2(0,0,black_margin[MARGIN_LEFT],window_h),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_LEFT],Color(1,1,1)); @@ -7362,10 +7364,22 @@ void VisualServerRaster::_draw_cursors_and_margins() { rasterizer->canvas_draw_rect(Rect2(window_w-black_margin[MARGIN_RIGHT],0,black_margin[MARGIN_RIGHT],window_h),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_RIGHT],Color(1,1,1)); } else if (black_margin[MARGIN_RIGHT]) rasterizer->canvas_draw_rect(Rect2(window_w-black_margin[MARGIN_RIGHT],0,black_margin[MARGIN_RIGHT],window_h),0,Rect2(0,0,1,1),RID(),Color(0,0,0)); - if (black_margin[MARGIN_TOP]) + + if (black_image[MARGIN_TOP].is_valid()) { + Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_TOP]),rasterizer->texture_get_height(black_image[MARGIN_TOP])); + rasterizer->canvas_draw_rect(Rect2(0,0,window_w,black_margin[MARGIN_TOP]),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_TOP],Color(1,1,1)); + + } else if (black_margin[MARGIN_TOP]) { rasterizer->canvas_draw_rect(Rect2(0,0,window_w,black_margin[MARGIN_TOP]),0,Rect2(0,0,1,1),RID(),Color(0,0,0)); - if (black_margin[MARGIN_BOTTOM]) + } + + if (black_image[MARGIN_BOTTOM].is_valid()) { + + Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_BOTTOM]),rasterizer->texture_get_height(black_image[MARGIN_BOTTOM])); + rasterizer->canvas_draw_rect(Rect2(0,window_h-black_margin[MARGIN_BOTTOM],window_w,black_margin[MARGIN_BOTTOM]),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_BOTTOM],Color(1,1,1)); + } else if (black_margin[MARGIN_BOTTOM]) { rasterizer->canvas_draw_rect(Rect2(0,window_h-black_margin[MARGIN_BOTTOM],window_w,black_margin[MARGIN_BOTTOM]),0,Rect2(0,0,1,1),RID(),Color(0,0,0)); + } rasterizer->canvas_end_rect(); }; diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index d431af6c8d1..96bd1ed27d1 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -33,6 +33,7 @@ #include "io/resource_saver.h" #include "pair.h" #include "scene/gui/separator.h" +#include "editor_node.h" /* Missing to fix: *Set @@ -634,9 +635,14 @@ void AnimationKeyEditor::_menu_track(int p_type) { last_menu_track_opt=p_type; switch(p_type) { - case TRACK_MENU_ADD_VALUE_TRACK: - case TRACK_MENU_ADD_TRANSFORM_TRACK: case TRACK_MENU_ADD_CALL_TRACK: { + if (root) { + call_select->popup_centered_ratio(); + break; + } + } break; + case TRACK_MENU_ADD_VALUE_TRACK: + case TRACK_MENU_ADD_TRANSFORM_TRACK: { undo_redo->create_action("Anim Add Track"); undo_redo->add_do_method(animation.ptr(),"add_track",p_type); @@ -2735,6 +2741,7 @@ void AnimationKeyEditor::_notification(int p_what) { } + call_select->connect("selected",this,"_add_call_track"); // rename_anim->set_icon( get_icon("Rename","EditorIcons") ); /* edit_anim->set_icon( get_icon("Edit","EditorIcons") ); @@ -3456,6 +3463,26 @@ void AnimationKeyEditor::_scale() { } +void AnimationKeyEditor::_add_call_track(const NodePath& p_base) { + + print_line("BASE IS "+String(p_base)); + Node* base = EditorNode::get_singleton()->get_edited_scene(); + if (!base) + return; + Node* from=base->get_node(p_base); + if (!from || !root) + return; + + NodePath path = root->get_path_to(from); + + undo_redo->create_action("Anim Add Call Track"); + undo_redo->add_do_method(animation.ptr(),"add_track",Animation::TYPE_METHOD); + undo_redo->add_do_method(animation.ptr(),"track_set_path",animation->get_track_count(),path); + undo_redo->add_undo_method(animation.ptr(),"remove_track",animation->get_track_count()); + undo_redo->commit_action(); + +} + void AnimationKeyEditor::cleanup() { set_animation(Ref()); @@ -3503,6 +3530,7 @@ void AnimationKeyEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_animation_optimize"),&AnimationKeyEditor::_animation_optimize); ObjectTypeDB::bind_method(_MD("_curve_transition_changed"),&AnimationKeyEditor::_curve_transition_changed); ObjectTypeDB::bind_method(_MD("_toggle_edit_curves"),&AnimationKeyEditor::_toggle_edit_curves); + ObjectTypeDB::bind_method(_MD("_add_call_track"),&AnimationKeyEditor::_add_call_track); ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) ); @@ -3815,7 +3843,9 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h scale_dialog->connect("confirmed",this,"_scale"); add_child(scale_dialog); - + call_select = memnew( SceneTreeDialog ); + add_child(call_select); + call_select->set_title("Call Functions in Which Node?"); } diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h index 35053fb6a34..4a1cc211543 100644 --- a/tools/editor/animation_editor.h +++ b/tools/editor/animation_editor.h @@ -44,7 +44,7 @@ #include "scene_tree_editor.h" #include "editor_data.h" #include "property_editor.h" - +#include "scene_tree_editor.h" class AnimationKeyEdit; class AnimationCurveEdit; @@ -206,6 +206,8 @@ class AnimationKeyEditor : public VBoxContainer { PropertyEditor *key_editor; + SceneTreeDialog *call_select; + Ref animation; void _update_paths(); @@ -299,6 +301,8 @@ class AnimationKeyEditor : public VBoxContainer { void _toggle_edit_curves(); void _animation_len_update(); + void _add_call_track(const NodePath& p_base); + void _root_removed(); protected: diff --git a/tools/editor/array_property_edit.cpp b/tools/editor/array_property_edit.cpp new file mode 100644 index 00000000000..9cd443270b8 --- /dev/null +++ b/tools/editor/array_property_edit.cpp @@ -0,0 +1,231 @@ +#include "array_property_edit.h" + +#include "editor_node.h" + +#define ITEMS_PER_PAGE 100 + +Variant ArrayPropertyEdit::get_array() const{ + + Object*o = ObjectDB::get_instance(obj); + if (!o) + return Array(); + Variant arr=o->get(property); + if (!arr.is_array()) { + Variant::CallError ce; + arr=Variant::construct(default_type,NULL,0,ce); + } + return arr; +} + +void ArrayPropertyEdit::_notif_change() { + _change_notify(); +} +void ArrayPropertyEdit::_notif_changev(const String& p_v) { + + _change_notify(p_v.utf8().get_data()); +} + +void ArrayPropertyEdit::_set_size(int p_size) { + + Variant arr = get_array(); + arr.call("resize",p_size); + Object*o = ObjectDB::get_instance(obj); + if (!o) + return; + + o->set(property,arr); + +} + +void ArrayPropertyEdit::_set_value(int p_idx,const Variant& p_value) { + + Variant arr = get_array(); + arr.set(p_idx,p_value); + Object*o = ObjectDB::get_instance(obj); + if (!o) + return; + + o->set(property,arr); +} + +bool ArrayPropertyEdit::_set(const StringName& p_name, const Variant& p_value){ + + String pn=p_name; + + if (pn.begins_with("array/")) { + + if (pn=="array/size") { + + Variant arr = get_array(); + int size = arr.call("size"); + + int newsize=p_value; + if (newsize==size) + return true; + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Resize Array"); + ur->add_do_method(this,"_set_size",newsize); + ur->add_undo_method(this,"_set_size",size); + if (newsizeadd_undo_method(this,"_set_value",i,arr.get(i)); + + } + } + ur->add_do_method(this,"_notif_change"); + ur->add_undo_method(this,"_notif_change"); + ur->commit_action(); + return true; + } + if (pn=="array/page") { + page=p_value; + _change_notify(); + return true; + } + } else if (pn.begins_with("indices")) { + + if (pn.find("_")!=-1) { + //type + int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int(); + + int type = p_value; + + Variant arr = get_array(); + + Variant value = arr.get(idx); + if (value.get_type()!=type && type>=0 && typeget_undo_redo(); + + ur->create_action("Change Array Value Type"); + ur->add_do_method(this,"_set_value",idx,new_value); + ur->add_undo_method(this,"_set_value",idx,value); + ur->add_do_method(this,"_notif_change"); + ur->add_undo_method(this,"_notif_change"); + ur->commit_action(); + + } + return true; + + } else { + int idx=pn.get_slicec('/',1).to_int(); + Variant arr = get_array(); + + Variant value = arr.get(idx); + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + + ur->create_action("Change Array Value"); + ur->add_do_method(this,"_set_value",idx,p_value); + ur->add_undo_method(this,"_set_value",idx,value); + ur->add_do_method(this,"_notif_changev",p_name); + ur->add_undo_method(this,"_notif_changev",p_name); + ur->commit_action(); + return true; + } + } + + return false; +} + +bool ArrayPropertyEdit::_get(const StringName& p_name,Variant &r_ret) const { + + Variant arr = get_array(); + //int size = arr.call("size"); + + String pn=p_name; + if (pn.begins_with("array/")) { + + if (pn=="array/size") { + r_ret=arr.call("size"); + return true; + } + if (pn=="array/page") { + r_ret=page; + return true; + } + } else if (pn.begins_with("indices")) { + + if (pn.find("_")!=-1) { + //type + int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int(); + bool valid; + r_ret=arr.get(idx,&valid); + if (valid) + r_ret=r_ret.get_type(); + return valid; + + } else { + int idx=pn.get_slicec('/',1).to_int(); + bool valid; + r_ret=arr.get(idx,&valid); + return valid; + } + } + + return false; +} + +void ArrayPropertyEdit::_get_property_list( List *p_list) const{ + + Variant arr = get_array(); + int size = arr.call("size"); + + p_list->push_back( PropertyInfo(Variant::INT,"array/size",PROPERTY_HINT_RANGE,"0,100000,1") ); + int pages = size/ITEMS_PER_PAGE; + if (pages>0) + p_list->push_back( PropertyInfo(Variant::INT,"array/page",PROPERTY_HINT_RANGE,"0,"+itos(pages)+",1") ); + + int offset=page*ITEMS_PER_PAGE; + + int items=MIN(size-offset,ITEMS_PER_PAGE); + + + for(int i=0;ipush_back(PropertyInfo(Variant::INT,"indices/"+itos(i+offset)+"_type",PROPERTY_HINT_ENUM,vtypes)); + } + if (arr.get_type()!=Variant::ARRAY || v.get_type()!=Variant::NIL) { + PropertyInfo pi(v.get_type(),"indices/"+itos(i+offset)); + if (v.get_type()==Variant::OBJECT) { + pi.hint=PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string="Resource"; + } + p_list->push_back(pi); + } + } + +} + +void ArrayPropertyEdit::edit(Object* p_obj,const StringName& p_prop,Variant::Type p_deftype) { + + page=0; + property=p_prop; + obj=p_obj->get_instance_ID(); + default_type=p_deftype; + +} + +void ArrayPropertyEdit::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_set_size"),&ArrayPropertyEdit::_set_size); + ObjectTypeDB::bind_method(_MD("_set_value"),&ArrayPropertyEdit::_set_value); + ObjectTypeDB::bind_method(_MD("_notif_change"),&ArrayPropertyEdit::_notif_change); + ObjectTypeDB::bind_method(_MD("_notif_changev"),&ArrayPropertyEdit::_notif_changev); +} + +ArrayPropertyEdit::ArrayPropertyEdit() +{ + page=0; + for(int i=0;i0) + vtypes+=","; + vtypes+=Variant::get_type_name( Variant::Type(i) ); + } + default_type=Variant::NIL; + +} diff --git a/tools/editor/array_property_edit.h b/tools/editor/array_property_edit.h new file mode 100644 index 00000000000..acfb8e68ede --- /dev/null +++ b/tools/editor/array_property_edit.h @@ -0,0 +1,36 @@ +#ifndef ARRAY_PROPERTY_EDIT_H +#define ARRAY_PROPERTY_EDIT_H + +#include "scene/main/node.h" + +class ArrayPropertyEdit : public Reference { + + OBJ_TYPE(ArrayPropertyEdit,Reference); + + int page; + ObjectID obj; + StringName property; + String vtypes; + Variant get_array() const; + Variant::Type default_type; + + void _notif_change(); + void _notif_changev(const String& p_v); + void _set_size(int p_size); + void _set_value(int p_idx,const Variant& p_value); + +protected: + + static void _bind_methods(); + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List *p_list) const; + +public: + + void edit(Object* p_obj, const StringName& p_prop, Variant::Type p_deftype); + + ArrayPropertyEdit(); +}; + +#endif // ARRAY_PROPERTY_EDIT_H diff --git a/tools/editor/dependency_editor.cpp b/tools/editor/dependency_editor.cpp new file mode 100644 index 00000000000..c04e82a08a3 --- /dev/null +++ b/tools/editor/dependency_editor.cpp @@ -0,0 +1,512 @@ +#include "dependency_editor.h" +#include "os/file_access.h" +#include "scene/gui/margin_container.h" +#include "io/resource_loader.h" +#include "editor_node.h" + +void DependencyEditor::_notification(int p_what){ + + +} + +void DependencyEditor::_searched(const String& p_path) { + + Map dep_rename; + dep_rename[replacing]=p_path; + + + ResourceLoader::rename_dependencies(editing,dep_rename); + + _update_list(); + _update_file(); +} + +void DependencyEditor::_load_pressed(Object* p_item,int p_cell,int p_button){ + + TreeItem *ti=p_item->cast_to(); + String fname = ti->get_text(0); + replacing = ti->get_text(1); + + search->set_title("Search Replacement For: "+replacing.get_file()); + + search->clear_filters(); + List ext; + ResourceLoader::get_recognized_extensions_for_type(ti->get_metadata(0),&ext); + for (List::Element *E=ext.front();E;E=E->next()) { + search->add_filter("*"+E->get()); + } + search->popup_centered_ratio(); + +} + +void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, Map >& candidates){ + + for(int i=0;iget_subdir_count();i++) { + _fix_and_find(efsd->get_subdir(i),candidates); + } + + for(int i=0;iget_file_count();i++) { + + String file = efsd->get_file(i); + if (!candidates.has(file)) + continue; + + String path = efsd->get_file_path(i); + Map &ss = candidates[file]; + + + for(Map::Element *E=candidates[file].front();E;E=E->next()) { + + if (E->get()==String()) { + E->get()=path; + continue; + } + + //must match the best, using subdirs + String existing=E->get().replace_first("res://",""); + String current=path.replace_first("res://",""); + String lost=E->key().replace_first("res://",""); + + Vector existingv=existing.split("/"); + existingv.invert(); + Vector currentv=current.split("/"); + currentv.invert(); + Vector lostv=lost.split("/"); + lostv.invert(); + + int existing_score=0; + int current_score=0; + + for(int j=0;j existing_score) { + + //if it was the same, could track distance to new path but.. + + E->get()=path; //replace by more accurate + } + + } + + } + +} + + +void DependencyEditor::_fix_all(){ + + if (!EditorFileSystem::get_singleton()->get_filesystem()) + return; + + Map > candidates; + + for (List::Element *E=missing.front();E;E=E->next()) { + + String base = E->get().get_file(); + if (!candidates.has(base)) { + candidates[base]=Map(); + } + + candidates[base][E->get()]=""; + } + + _fix_and_find(EditorFileSystem::get_singleton()->get_filesystem(),candidates); + + Map remaps; + + for (Map >::Element *E=candidates.front();E;E=E->next()) { + + for (Map::Element *F=E->get().front();F;F=F->next()) { + + if (F->get()!=String()) { + remaps[F->key()]=F->get(); + } + } + + } + + if (remaps.size()) { + + ResourceLoader::rename_dependencies(editing,remaps); + + _update_list(); + _update_file(); + } +} + +void DependencyEditor::_update_file() { + + EditorFileSystem::get_singleton()->update_file(editing); + +} + +void DependencyEditor::_update_list() { + + List deps; + ResourceLoader::get_dependencies(editing,&deps,true); + + tree->clear(); + missing.clear(); + + TreeItem *root = tree->create_item(); + + Ref folder = get_icon("folder","FileDialog"); + + bool broken=false; + + for(List::Element *E=deps.front();E;E=E->next()) { + + TreeItem *item = tree->create_item(root); + + String n = E->get(); + String path; + String type; + + if (n.find("::")!=-1) { + path = n.get_slice("::",0); + type = n.get_slice("::",1); + } else { + path=n; + type="Resource"; + } + String name = path.get_file(); + + Ref icon; + if (has_icon(type,"EditorIcons")) { + icon=get_icon(type,"EditorIcons"); + } else { + icon=get_icon("Object","EditorIcons"); + } + item->set_text(0,name); + item->set_icon(0,icon); + item->set_metadata(0,type); + item->set_text(1,path); + + if (!FileAccess::exists(path)) { + item->set_custom_color(1,Color(1,0.4,0.3)); + missing.push_back(path); + broken=true; + } + + item->add_button(1,folder,0); + } + + fixdeps->set_disabled(!broken); + +} + + + +void DependencyEditor::edit(const String& p_path) { + + + editing=p_path; + set_title("Dependencies For: "+p_path.get_file()); + + _update_list(); + popup_centered_ratio(); + + if (EditorNode::get_singleton()->is_scene_open(p_path)) { + EditorNode::get_singleton()->show_warning("Scene '"+p_path.get_file()+"' is currently being edited.\nChanges will not take effect unless reloaded."); + } else if (ResourceCache::has(p_path)) { + EditorNode::get_singleton()->show_warning("Resource '"+p_path.get_file()+"' is in use.\nChanges will take effect when reloaded."); + } +} + + +void DependencyEditor::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_searched"),&DependencyEditor::_searched); + ObjectTypeDB::bind_method(_MD("_load_pressed"),&DependencyEditor::_load_pressed); + ObjectTypeDB::bind_method(_MD("_fix_all"),&DependencyEditor::_fix_all); + +} + +DependencyEditor::DependencyEditor() { + + VBoxContainer *vb = memnew( VBoxContainer ); + vb->set_name("Dependencies"); + add_child(vb); + set_child_rect(vb); + + tree = memnew( Tree ); + tree->set_columns(2); + tree->set_column_titles_visible(true); + tree->set_column_title(0,"Resource"); + tree->set_column_title(1,"Path"); + tree->set_hide_root(true); + tree->connect("button_pressed",this,"_load_pressed"); + + HBoxContainer *hbc = memnew( HBoxContainer ); + Label *label = memnew( Label("Dependencies:")); + hbc->add_child(label); + hbc->add_spacer(); + fixdeps = memnew( Button("Fix Broken")); + hbc->add_child(fixdeps); + fixdeps->connect("pressed",this,"_fix_all"); + + vb->add_child(hbc); + + MarginContainer *mc = memnew( MarginContainer ); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + + mc->add_child(tree); + vb->add_child(mc); + + set_title("Dependency Editor"); + search = memnew( EditorFileDialog ); + search->connect("file_selected",this,"_searched"); + search->set_mode(EditorFileDialog::MODE_OPEN_FILE); + search->set_title("Search Replacement Resource:"); + add_child(search); + +} + +///////////////////////////////////// + + + +void DependencyEditorOwners::_fill_owners(EditorFileSystemDirectory *efsd) { + + if (!efsd) + return; + + for(int i=0;iget_subdir_count();i++) { + _fill_owners(efsd->get_subdir(i)); + } + + for(int i=0;iget_file_count();i++) { + + Vector deps = efsd->get_file_deps(i); + //print_line(":::"+efsd->get_file_path(i)); + bool found=false; + for(int j=0;j icon; + String type=efsd->get_file_type(i); + if (!has_icon(type,"EditorIcons")) { + icon=get_icon("Object","EditorIcons"); + } else { + icon=get_icon(type,"EditorIcons"); + } + + owners->add_item(efsd->get_file_path(i),icon); + } + +} + +void DependencyEditorOwners::show(const String& p_path) { + + editing=p_path; + owners->clear(); + _fill_owners(EditorFileSystem::get_singleton()->get_filesystem()); + popup_centered_ratio(); + + set_title("Owners Of: "+p_path.get_file()); + +} + +DependencyEditorOwners::DependencyEditorOwners() { + + + owners = memnew( ItemList ); + add_child(owners); + set_child_rect(owners); + + +} + +/////////////////////// + + +void DependencyRemoveDialog::_fill_owners(EditorFileSystemDirectory *efsd) { + + if (!efsd) + return; + + for(int i=0;iget_subdir_count();i++) { + _fill_owners(efsd->get_subdir(i)); + } + + for(int i=0;iget_file_count();i++) { + + Vector deps = efsd->get_file_deps(i); + //print_line(":::"+efsd->get_file_path(i)); + Set met; + for(int j=0;j icon; + String type=efsd->get_file_type(i); + if (!has_icon(type,"EditorIcons")) { + icon=get_icon("Object","EditorIcons"); + } else { + icon=get_icon(type,"EditorIcons"); + } + + + for(Set::Element *E=met.front();E;E=E->next()) { + + String which = E->get(); + if (!files[which]) { + TreeItem *ti=owners->create_item(owners->get_root()); + ti->set_text(0,which.get_file()); + files[which]=ti; + + } + TreeItem *ti=owners->create_item(files[which]); + ti->set_text(0,efsd->get_file_path(i)); + ti->set_icon(0,icon); + } + + } + +} + +void DependencyRemoveDialog::show(const Vector &to_erase) { + + exist=false; + owners->clear(); + files.clear(); + TreeItem *root=owners->create_item(); + for(int i=0;iget_filesystem()); + + if (exist) { + owners->show(); + text->set_text("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)"); + popup_centered_minsize(Size2(500,220)); + } else { + owners->hide(); + text->set_text("Remove selected files from the project? (no undo)"); + popup_centered_minsize(Size2(400,100)); + } + +} + +void DependencyRemoveDialog::ok_pressed() { + + + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + for (Map::Element *E=files.front();E;E=E->next()) { + + da->remove(E->key()); + EditorFileSystem::get_singleton()->update_file(E->key()); + } + memdelete(da); + +} + +DependencyRemoveDialog::DependencyRemoveDialog() { + + VBoxContainer *vb = memnew( VBoxContainer ); + add_child(vb); + set_child_rect(vb); + + text = memnew( Label ); + vb->add_child(text); + + owners = memnew( Tree ); + owners->set_hide_root(true); + vb->add_child(owners); + owners->set_v_size_flags(SIZE_EXPAND_FILL); + get_ok()->set_text("Remove"); +} + + +////////////// + + +void DependencyErrorDialog::show(const String& p_for_file,const Vector &report) { + + + for_file=p_for_file; + set_title("Error loading: "+p_for_file.get_file()); + files->clear(); + + TreeItem *root = files->create_item(NULL); + for(int i=0;i0) + type=report[i].get_slice("::",1); + + Ref icon; + if (!has_icon(type,"EditorIcons")) { + icon=get_icon("Object","EditorIcons"); + } else { + icon=get_icon(type,"EditorIcons"); + } + + TreeItem *ti=files->create_item(root); + ti->set_text(0,dep); + ti->set_icon(0,icon); + + } + + popup_centered_minsize(Size2(500,220)); + +} + +void DependencyErrorDialog::ok_pressed() { + + EditorNode::get_singleton()->load_scene(for_file,true); +} + +void DependencyErrorDialog::custom_action(const String&) { + + EditorNode::get_singleton()->fix_dependencies(for_file); +} + +DependencyErrorDialog::DependencyErrorDialog() { + + VBoxContainer *vb = memnew( VBoxContainer ); + add_child(vb); + set_child_rect(vb); + + + files = memnew( Tree ); + files->set_hide_root(true); + vb->add_margin_child("Scene failed to load due to missing dependencies:",files,true); + files->set_v_size_flags(SIZE_EXPAND_FILL); + get_ok()->set_text("Open Anyway"); + + text = memnew( Label ); + vb->add_child(text); + text->set_text("Which action should be taken?"); + + + fdep=add_button("Fix Dependencies",true,"fixdeps"); + + set_title("Errors loading!"); + +} diff --git a/tools/editor/dependency_editor.h b/tools/editor/dependency_editor.h new file mode 100644 index 00000000000..1c328e7a93d --- /dev/null +++ b/tools/editor/dependency_editor.h @@ -0,0 +1,94 @@ +#ifndef DEPENDENCY_EDITOR_H +#define DEPENDENCY_EDITOR_H + +#include "scene/gui/dialogs.h" +#include "scene/gui/tree.h" +#include "scene/gui/tab_container.h" +#include "editor_file_dialog.h" + +class EditorFileSystemDirectory; + +class DependencyEditor : public AcceptDialog { + OBJ_TYPE(DependencyEditor,AcceptDialog); + + + Tree *tree; + Button *fixdeps; + + EditorFileDialog *search; + + String replacing; + String editing; + List missing; + + + void _fix_and_find(EditorFileSystemDirectory *efsd, Map >& candidates); + + void _searched(const String& p_path); + void _load_pressed(Object* p_item,int p_cell,int p_button); + void _fix_all(); + void _update_list(); + + void _update_file(); + +protected: + + static void _bind_methods(); + void _notification(int p_what); +public: + + + void edit(const String& p_path); + DependencyEditor(); +}; + +class DependencyEditorOwners : public AcceptDialog { + OBJ_TYPE(DependencyEditorOwners,AcceptDialog); + + ItemList *owners; + String editing; + void _fill_owners(EditorFileSystemDirectory *efsd); + +public: + + void show(const String& p_path); + DependencyEditorOwners(); +}; + +class DependencyRemoveDialog : public ConfirmationDialog { + OBJ_TYPE(DependencyRemoveDialog,ConfirmationDialog); + + + Label *text; + Tree *owners; + bool exist; + Map files; + void _fill_owners(EditorFileSystemDirectory *efsd); + + void ok_pressed(); + +public: + + void show(const Vector &to_erase); + DependencyRemoveDialog(); +}; + + +class DependencyErrorDialog : public ConfirmationDialog { + OBJ_TYPE(DependencyErrorDialog,ConfirmationDialog); + + + String for_file; + Button *fdep; + Label *text; + Tree *files; + void ok_pressed(); + void custom_action(const String&); + +public: + + void show(const String& p_for,const Vector &report); + DependencyErrorDialog(); +}; + +#endif // DEPENDENCY_EDITOR_H diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp index 7f42f19a9b4..673ee30adbc 100644 --- a/tools/editor/editor_data.cpp +++ b/tools/editor/editor_data.cpp @@ -39,7 +39,7 @@ void EditorHistory::_cleanup_history() { bool fail=false; for(int j=0;jcast_to(); + Reference *r = obj->cast_to(); Obj o; if (r) - o.res=RES(r); + o.ref=REF(r); o.object=p_object; o.property=p_property; @@ -123,6 +123,27 @@ void EditorHistory::add_object(ObjectID p_object,int p_relevel){ _add_object(p_object,"",p_relevel); } +int EditorHistory::get_history_len() { + return history.size(); +} +int EditorHistory::get_history_pos() { + return current; +} + +ObjectID EditorHistory::get_history_obj(int p_obj) const { + ERR_FAIL_INDEX_V(p_obj,history.size(),0); + ERR_FAIL_INDEX_V(history[p_obj].level,history[p_obj].path.size(),0); + return history[p_obj].path[history[p_obj].level].object; +} + +bool EditorHistory::is_at_begining() const { + return current<=0; +} +bool EditorHistory::is_at_end() const { + + return ((current+1)>=history.size()); +} + bool EditorHistory::next() { @@ -523,7 +544,7 @@ Ref