diff options
49 files changed, 2067 insertions, 848 deletions
diff --git a/core/dvector.h b/core/dvector.h index cac9e8ef85..53a29738f7 100644 --- a/core/dvector.h +++ b/core/dvector.h @@ -89,7 +89,7 @@ class PoolVector { if (!alloc) return; - ERR_FAIL_COND(alloc->lock>0); +// ERR_FAIL_COND(alloc->lock>0); should not be illegal to lock this for copy on write, as it's a copy on write after all if (alloc->refcount.get()==1) return; //nothing to do diff --git a/core/image.cpp b/core/image.cpp index ed505b0f77..2d038691f2 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -2155,7 +2155,7 @@ void Image::fix_alpha_edges() { return; //not needed PoolVector<uint8_t> dcopy = data; - PoolVector<uint8_t>::Read rp = data.read(); + PoolVector<uint8_t>::Read rp = dcopy.read(); const uint8_t *srcptr=rp.ptr(); PoolVector<uint8_t>::Write wp = data.write(); diff --git a/core/input_map.cpp b/core/input_map.cpp index 8473bce806..dcce13ba1b 100644 --- a/core/input_map.cpp +++ b/core/input_map.cpp @@ -107,7 +107,7 @@ List<StringName> InputMap::get_actions() const { return actions; } -List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const InputEvent& p_event, bool p_mod_ignore=false) const { +List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const InputEvent& p_event, bool p_action_test) const { for (List<InputEvent>::Element *E=p_list.front();E;E=E->next()) { @@ -123,7 +123,13 @@ List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const case InputEvent::KEY: { - same=(e.key.scancode==p_event.key.scancode && (p_mod_ignore || e.key.mod == p_event.key.mod)); + if(p_action_test) { + uint32_t code = e.key.get_scancode_with_modifiers(); + uint32_t event_code = p_event.key.get_scancode_with_modifiers(); + same=(e.key.scancode==p_event.key.scancode && (!p_event.key.pressed || ((code & event_code) == code))); + } else { + same=(e.key.scancode==p_event.key.scancode && e.key.mod == p_event.key.mod); + } } break; case InputEvent::JOYPAD_BUTTON: { @@ -230,7 +236,7 @@ bool InputMap::event_is_action(const InputEvent& p_event, const StringName& p_ac return p_event.action.action==E->get().id; } - return _find_event(E->get().inputs,p_event,!p_event.is_pressed())!=NULL; + return _find_event(E->get().inputs,p_event,true)!=NULL; } const Map<StringName, InputMap::Action>& InputMap::get_action_map() const { diff --git a/core/input_map.h b/core/input_map.h index 306845fc89..6ccd24f29c 100644 --- a/core/input_map.h +++ b/core/input_map.h @@ -46,7 +46,7 @@ private: mutable Map<StringName, Action> input_map; mutable Map<int,StringName> input_id_map; - List<InputEvent>::Element *_find_event(List<InputEvent> &p_list,const InputEvent& p_event, bool p_mod_ignore) const; + List<InputEvent>::Element *_find_event(List<InputEvent> &p_list,const InputEvent& p_event, bool p_action_test=false) const; Array _get_action_list(const StringName& p_action); Array _get_actions(); diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index a9de740806..b944906e78 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -119,7 +119,10 @@ void ConfigFile::get_section_keys(const String& p_section,List<String> *r_keys) } +void ConfigFile::erase_section(const String& p_section) { + values.erase(p_section); +} Error ConfigFile::save(const String& p_path){ @@ -215,6 +218,8 @@ void ConfigFile::_bind_methods(){ ClassDB::bind_method(_MD("get_sections"),&ConfigFile::_get_sections); ClassDB::bind_method(_MD("get_section_keys","section"),&ConfigFile::_get_section_keys); + ClassDB::bind_method(_MD("erase_section","section"),&ConfigFile::erase_section); + ClassDB::bind_method(_MD("load:Error","path"),&ConfigFile::load); ClassDB::bind_method(_MD("save:Error","path"),&ConfigFile::save); diff --git a/core/io/config_file.h b/core/io/config_file.h index 397342f90f..c9c4a9fbc0 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -54,6 +54,8 @@ public: void get_sections(List<String> *r_sections) const; void get_section_keys(const String& p_section,List<String> *r_keys) const; + void erase_section(const String& p_section); + Error save(const String& p_path); Error load(const String& p_path); diff --git a/core/io/resource_import.cpp b/core/io/resource_import.cpp index 92b5d1de40..d0799cdbe6 100644 --- a/core/io/resource_import.cpp +++ b/core/io/resource_import.cpp @@ -30,7 +30,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String& p_path, PathAndTy return OK; } else if (err!=OK) { - ERR_PRINTS("ResourceFormatImporter::load - "+p_path+":"+itos(lines)+" error: "+error_text); + ERR_PRINTS("ResourceFormatImporter::load - "+p_path+".import:"+itos(lines)+" error: "+error_text); memdelete(f); return err; } @@ -71,12 +71,20 @@ RES ResourceFormatImporter::load(const String &p_path,const String& p_original_p } - return ResourceLoader::load(pat.path,pat.type,false,r_error); + RES res = ResourceLoader::load(pat.path,pat.type,false,r_error); + +#ifdef TOOLS_ENABLED + res->set_import_last_modified_time( res->get_last_modified_time() ); //pass this, if used + res->set_import_path(pat.path); +#endif + + return res; } void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extensions) const{ + print_line("getting exts from: "+itos(importers.size())); Set<String> found; for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) { @@ -84,6 +92,7 @@ void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extension E->get()->get_recognized_extensions(&local_exts); for (List<String>::Element *F=local_exts.front();F;F=F->next()) { if (!found.has(F->get())) { + print_line("adding ext "+String(F->get())); p_extensions->push_back(F->get()); found.insert(F->get()); } @@ -93,10 +102,18 @@ void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extension void ResourceFormatImporter::get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const{ + if (p_type=="") { + return get_recognized_extensions(p_extensions); + } + Set<String> found; for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) { - if (!ClassDB::is_parent_class(p_type,E->get()->get_resource_type())) + String res_type = E->get()->get_resource_type(); + if (res_type==String()) + continue; + + if (!ClassDB::is_parent_class(res_type,p_type)) continue; List<String> local_exts; @@ -112,13 +129,24 @@ void ResourceFormatImporter::get_recognized_extensions_for_type(const String& p_ bool ResourceFormatImporter::recognize_path(const String& p_path,const String& p_for_type) const{ - return (p_path.get_extension().to_lower()=="import"); + return FileAccess::exists(p_path+".import"); + } +bool ResourceFormatImporter::can_be_imported(const String& p_path) const { + + return ResourceFormatLoader::recognize_path(p_path); +} + + bool ResourceFormatImporter::handles_type(const String& p_type) const { for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) { - if (ClassDB::is_parent_class(p_type,E->get()->get_resource_type())) + + String res_type = E->get()->get_resource_type(); + if (res_type==String()) + continue; + if (ClassDB::is_parent_class(res_type,p_type)) return true; } @@ -152,3 +180,59 @@ void ResourceFormatImporter::get_dependencies(const String& p_path,List<String> return ResourceLoader::get_dependencies(pat.path,p_dependencies,p_add_types); } +Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String& p_name) { + + for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) { + if (E->get()->get_importer_name()==p_name) { + return E->get(); + } + } + + return Ref<ResourceImporter>(); +} + + +void ResourceFormatImporter::get_importers_for_extension(const String& p_extension,List<Ref<ResourceImporter> > *r_importers) { + + for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) { + List<String> local_exts; + E->get()->get_recognized_extensions(&local_exts); + for (List<String>::Element *F=local_exts.front();F;F=F->next()) { + if (p_extension.to_lower()==F->get()) { + r_importers->push_back(E->get()); + } + } + } +} + +Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String& p_extension) { + + + Ref<ResourceImporter> importer; + float priority=0; + + for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) { + + List<String> local_exts; + E->get()->get_recognized_extensions(&local_exts); + for (List<String>::Element *F=local_exts.front();F;F=F->next()) { + if (p_extension.to_lower()==F->get() && E->get()->get_priority() > priority) { + importer=E->get(); + priority=E->get()->get_priority(); + } + } + } + + return importer; +} + +String ResourceFormatImporter::get_import_base_path(const String& p_for_file) const { + + return "res://.import/"+p_for_file.get_file()+"-"+p_for_file.md5_text(); +} + +ResourceFormatImporter *ResourceFormatImporter::singleton=NULL; + +ResourceFormatImporter::ResourceFormatImporter() { + singleton=this; +} diff --git a/core/io/resource_import.h b/core/io/resource_import.h index d4b80030b2..939cecfbd9 100644 --- a/core/io/resource_import.h +++ b/core/io/resource_import.h @@ -15,35 +15,61 @@ class ResourceFormatImporter : public ResourceFormatLoader { Error _get_path_and_type(const String& p_path,PathAndType & r_path_and_type) const; + static ResourceFormatImporter *singleton; + Set< Ref<ResourceImporter> > importers; public: + static ResourceFormatImporter *get_singleton() { return singleton; } virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const; - bool recognize_path(const String& p_path,const String& p_for_type=String()) const; - virtual bool handles_type(const String& p_type) const=0; - virtual String get_resource_type(const String &p_path) const=0; + virtual bool recognize_path(const String& p_path,const String& p_for_type=String()) 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<String> *p_dependencies,bool p_add_types=false); + virtual bool can_be_imported(const String& p_path) const; + + + void add_importer(const Ref<ResourceImporter>& p_importer) { importers.insert(p_importer); } + Ref<ResourceImporter> get_importer_by_name(const String& p_name); + Ref<ResourceImporter> get_importer_by_extension(const String& p_extension); + void get_importers_for_extension(const String& p_extension,List<Ref<ResourceImporter> > *r_importers); + + String get_import_base_path(const String& p_for_file) const; + ResourceFormatImporter(); }; -class ResourceImporter { +class ResourceImporter : public Reference { + + GDCLASS(ResourceImporter,Reference) public: - virtual String get_name() const=0; + virtual String get_importer_name() const=0; virtual String get_visible_name() const=0; virtual void get_recognized_extensions(List<String> *p_extensions) const=0; + virtual String get_save_extension() const=0; virtual String get_resource_type() const=0; + virtual float get_priority() const { return 1.0; } struct ImportOption { PropertyInfo option; Variant default_value; + + ImportOption(const PropertyInfo& p_info,const Variant& p_default) { option=p_info; default_value=p_default; } + ImportOption() {} }; - virtual void get_import_options(List<ImportOption> *r_options)=0; - virtual RES import(const String& p_path,const Map<StringName,Variant>& p_options)=0; + virtual int get_preset_count() const { return 0; } + virtual String get_preset_name(int p_idx) const { return String(); } + + virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const=0; + virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const=0; + + + virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL)=0; }; diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 05a4d98d83..f464415e12 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -61,7 +61,7 @@ public: virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const=0; virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const; - bool recognize_path(const String& p_path,const String& p_for_type=String()) const; + virtual bool recognize_path(const String& p_path,const String& p_for_type=String()) 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<String> *p_dependencies,bool p_add_types=false); diff --git a/core/object.h b/core/object.h index b9a800afc4..3032452ccf 100644 --- a/core/object.h +++ b/core/object.h @@ -103,6 +103,7 @@ enum PropertyUsageFlags { PROPERTY_USAGE_SCRIPT_VARIABLE=8192, PROPERTY_USAGE_STORE_IF_NULL=16384, PROPERTY_USAGE_ANIMATE_AS_TRIGGER=32768, + PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED=65536, PROPERTY_USAGE_DEFAULT=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK, PROPERTY_USAGE_DEFAULT_INTL=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_INTERNATIONALIZED, diff --git a/core/pair.h b/core/pair.h index d75cbed642..174ffb3883 100644 --- a/core/pair.h +++ b/core/pair.h @@ -39,4 +39,13 @@ struct Pair { Pair( F p_first, S p_second) { first=p_first; second=p_second; } }; +template<class F,class S> +struct PairSort { + + bool operator()(const Pair<F,S>& A, const Pair<F,S>& B) const { + return A.first < B.first; + } +}; + + #endif // PAIR_H diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 8cbfdf0b01..ab94b56cdc 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -45,6 +45,7 @@ #include "compressed_translation.h" #include "io/translation_loader_po.h" #include "io/resource_format_binary.h" +#include "io/resource_import.h" #include "io/stream_peer_ssl.h" #include "os/input.h" #include "core/io/xml_parser.h" @@ -57,7 +58,7 @@ static ResourceFormatSaverBinary *resource_saver_binary=NULL; static ResourceFormatLoaderBinary *resource_loader_binary=NULL; - +static ResourceFormatImporter *resource_format_importer=NULL; static _ResourceLoader *_resource_loader=NULL; static _ResourceSaver *_resource_saver=NULL; @@ -105,6 +106,9 @@ void register_core_types() { resource_loader_binary = memnew( ResourceFormatLoaderBinary ); ResourceLoader::add_resource_format_loader(resource_loader_binary); + resource_format_importer = memnew( ResourceFormatImporter ); + ResourceLoader::add_resource_format_loader(resource_format_importer); + ClassDB::register_class<Object>(); @@ -183,7 +187,6 @@ void register_core_singletons() { GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("ClassDB",_classdb ) ); GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("Marshalls",_Marshalls::get_singleton() ) ); GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("TranslationServer",TranslationServer::get_singleton() ) ); - GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("TS",TranslationServer::get_singleton() ) ); GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("Input",Input::get_singleton() ) ); GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("InputMap",InputMap::get_singleton() ) ); @@ -207,6 +210,8 @@ void unregister_core_types() { memdelete(resource_saver_binary); if (resource_loader_binary) memdelete(resource_loader_binary); + if (resource_format_importer) + memdelete(resource_format_importer); memdelete( resource_format_po ); diff --git a/core/resource.cpp b/core/resource.cpp index 765000d662..9b5bac5f32 100644 --- a/core/resource.cpp +++ b/core/resource.cpp @@ -353,6 +353,7 @@ Resource::Resource() { #ifdef TOOLS_ENABLED last_modified_time=0; + import_last_modified_time=0; #endif subindex=0; diff --git a/core/resource.h b/core/resource.h index b2873e4866..b29077a3b8 100644 --- a/core/resource.h +++ b/core/resource.h @@ -66,6 +66,8 @@ friend class ResourceCache; #ifdef TOOLS_ENABLED uint64_t last_modified_time; + uint64_t import_last_modified_time; + String import_path; #endif bool local_to_scene; @@ -118,6 +120,12 @@ public: virtual void set_last_modified_time(uint64_t p_time) { last_modified_time=p_time; } uint64_t get_last_modified_time() const { return last_modified_time; } + virtual void set_import_last_modified_time(uint64_t p_time) { import_last_modified_time=p_time; } + uint64_t get_import_last_modified_time() const { return import_last_modified_time; } + + void set_import_path(const String& p_path) { import_path=p_path; } + String get_import_path() const { return import_path; } + #endif virtual RID get_rid() const; // some resources may offer conversion to RID diff --git a/core/translation.cpp b/core/translation.cpp index d5ec61b8d6..8835cb133c 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -751,6 +751,20 @@ static const char* locale_names[]={ 0 }; +bool TranslationServer::is_locale_valid(const String& p_locale) { + + const char **ptr=locale_list; + + while (*ptr) { + + if (*ptr==p_locale) + return true; + ptr++; + } + + return false; + +} Vector<String> TranslationServer::get_all_locales() { diff --git a/core/translation.h b/core/translation.h index 85ab4a229d..feed352549 100644 --- a/core/translation.h +++ b/core/translation.h @@ -102,6 +102,7 @@ public: static Vector<String> get_all_locales(); static Vector<String> get_all_locale_names(); + static bool is_locale_valid(const String& p_locale); void set_tool_translation(const Ref<Translation>& p_translation); StringName tool_translate(const StringName& p_message) const; diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 0b8c5cc11c..9223b887a3 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -667,7 +667,7 @@ </methods> <constants> <constant name="PI" value="3.141593"> - Constant that represents how many times the diameter of a circumference fits around it's perimeter. + Constant that represents how many times the diameter of a circumference fits around its perimeter. </constant> </constants> </class> @@ -8025,7 +8025,7 @@ Circular Shape for 2D Physics. </brief_description> <description> - Circular Shape for 2D Physics. This shape is useful for modeling balls or small characters and it's collision detection with everything else is very fast. + Circular Shape for 2D Physics. This shape is useful for modeling balls or small characters and its collision detection with everything else is very fast. </description> <methods> <method name="get_radius" qualifiers="const"> @@ -11258,7 +11258,7 @@ This function is called for each file exported and depending from the return value one of many things might happen. 1) If returned value is null, the file is exported as is. 2) If the returned value is a RawAray (array of bytes), the content of that array becomes the new file being exported. - 3) If the file must also change it's name when exported, then a [Dictionary] must be returned with two fields: 'name' with the new filename and 'data' with a [RawArray] containing the raw contents of the file. Even if the name is changed, the run-time will redirect the old file to the new file automatically when accessed. + 3) If the file must also change its name when exported, then a [Dictionary] must be returned with two fields: 'name' with the new filename and 'data' with a [RawArray] containing the raw contents of the file. Even if the name is changed, the run-time will redirect the old file to the new file automatically when accessed. </description> </method> </methods> @@ -11706,7 +11706,7 @@ </class> <class name="EditorPlugin" inherits="Node" category="Core"> <brief_description> - Used by the editor to extend it's functionality. + Used by the editor to extend its functionality. </brief_description> <description> Plugins are used by the editor to extend functionality. The most common types of plugins are those which edit a given node or resource type, import plugins and export plugins. @@ -12005,7 +12005,7 @@ </method> <method name="save_external_data" qualifiers="virtual"> <description> - This method is called after the editor save the project or when the it's closed. It asks the plugin to save edited external scenes/resources. + This method is called after the editor saves the project or when it's closed. It asks the plugin to save edited external scenes/resources. </description> </method> <method name="set_state" qualifiers="virtual"> @@ -15970,7 +15970,7 @@ Request does not have a response(yet). </constant> <constant name="RESULT_BODY_SIZE_LIMIT_EXCEEDED" value="7"> - Request exceded it's maximum size limit, see [method set_body_size_limit]. + Request exceded its maximum size limit, see [method set_body_size_limit]. </constant> <constant name="RESULT_REQUEST_FAILED" value="8"> Request failed. (unused) @@ -15982,7 +15982,7 @@ HTTPRequest couldn't write to the download file. </constant> <constant name="RESULT_REDIRECT_LIMIT_REACHED" value="11"> - Request reached it's maximum redirect limit, see [method set_max_redirects]. + Request reached its maximum redirect limit, see [method set_max_redirects]. </constant> </constants> </class> @@ -16088,7 +16088,7 @@ <argument index="0" name="id" type="int"> </argument> <description> - Return the status of hostname queued for resolving, given it's queue ID. Returned status can be any of the RESOLVER_STATUS_* enumeration. + Return the status of hostname queued for resolving, given its queue ID. Returned status can be any of the RESOLVER_STATUS_* enumeration. </description> </method> <method name="resolve_hostname"> @@ -22660,7 +22660,7 @@ Nodes can also process input events. When set, the [method _input] function will be called for each input that the program receives. In many cases, this can be overkill (unless used for simple projects), and the [method _unhandled_input] function might be preferred; it is called when the input event was not handled by anyone else (typically, GUI [Control] nodes), ensuring that the node only receives the events that were meant for it. To keep track of the scene hierarchy (especially when instancing scenes into other scenes), an "owner" can be set for the node with [method set_owner]. This keeps track of who instanced what. This is mostly useful when writing editors and tools, though. Finally, when a node is freed with [method free] or [method queue_free], it will also free all its children. - [b]Networking with nodes:[/b] After connecting to a server (or making one, see [NetworkedMultiplayerENet]) it is possible to use the built-in RPC (remote procedure call) system to easily communicate over the network. By calling [method rpc] with a method name, it will be called locally, and in all connected peers (peers = clients and the server that accepts connections), with behaviour varying depending on the network mode ([method set_network_mode]) on the receiving peer. To identify which [Node] receives the RPC call Godot will use it's [NodePath] (make sure node names are the same on all peers). + [b]Networking with nodes:[/b] After connecting to a server (or making one, see [NetworkedMultiplayerENet]) it is possible to use the built-in RPC (remote procedure call) system to easily communicate over the network. By calling [method rpc] with a method name, it will be called locally, and in all connected peers (peers = clients and the server that accepts connections), with behaviour varying depending on the network mode ([method set_network_mode]) on the receiving peer. To identify which [Node] receives the RPC call Godot will use its [NodePath] (make sure node names are the same on all peers). </description> <methods> <method name="_enter_tree" qualifiers="virtual"> @@ -33832,7 +33832,7 @@ </signal> <signal name="sleeping_state_changed"> <description> - Emitted when the body changes it's sleeping state. Either by sleeping or waking up. + Emitted when the body changes its sleeping state. Either by sleeping or waking up. </description> </signal> </signals> @@ -34227,7 +34227,7 @@ </signal> <signal name="sleeping_state_changed"> <description> - Emitted when the body changes it's sleeping state. Either by sleeping or waking up. + Emitted when the body changes its sleeping state. Either by sleeping or waking up. </description> </signal> </signals> @@ -35889,7 +35889,7 @@ <return type="Error"> </return> <description> - Tries to wait for the [Semaphore], if it's value is zero, blocks until non-zero. + Tries to wait for the [Semaphore], if its value is zero, blocks until non-zero. </description> </method> </methods> diff --git a/main/input_default.cpp b/main/input_default.cpp index 82dec86067..0561f2bb34 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -381,15 +381,12 @@ void InputDefault::parse_input_event(const InputEvent& p_event) { if (!p_event.is_echo()) { for (const Map<StringName,InputMap::Action>::Element *E=InputMap::get_singleton()->get_action_map().front();E;E=E->next()) { - if (InputMap::get_singleton()->event_is_action(p_event,E->key())) { - - if(is_action_pressed(E->key()) != p_event.is_pressed()) { - Action action; - action.fixed_frame=Engine::get_singleton()->get_fixed_frames(); - action.idle_frame=Engine::get_singleton()->get_idle_frames(); - action.pressed=p_event.is_pressed(); - action_state[E->key()]=action; - } + if (InputMap::get_singleton()->event_is_action(p_event,E->key()) && is_action_pressed(E->key()) != p_event.is_pressed()) { + Action action; + action.fixed_frame=Engine::get_singleton()->get_fixed_frames(); + action.idle_frame=Engine::get_singleton()->get_idle_frames(); + action.pressed=p_event.is_pressed(); + action_state[E->key()]=action; } } } diff --git a/main/main.cpp b/main/main.cpp index 6dde1e521c..094b6aedae 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -183,8 +183,6 @@ void Main::print_help(const char* p_binary) { #ifdef TOOLS_ENABLED OS::get_singleton()->print("\t-doctool FILE: Dump the whole engine api to FILE in XML format. If FILE exists, it will be merged.\n"); OS::get_singleton()->print("\t-nodocbase: Disallow dump the base types (used with -doctool).\n"); - OS::get_singleton()->print("\t-optimize FILE Save an optimized copy of scene to FILE.\n"); - OS::get_singleton()->print("\t-optimize_preset [preset] Use a given preset for optimization.\n"); OS::get_singleton()->print("\t-export [target] Export the project using given export target.\n"); #endif } @@ -1074,12 +1072,9 @@ bool Main::start() { String script; String test; String screen; - String optimize; - String optimize_preset; String _export_platform; String _import; String _import_script; - String dumpstrings; bool noquit=false; bool export_debug=false; bool project_manager_request = false; @@ -1108,10 +1103,6 @@ bool Main::start() { Engine::get_singleton()->_custom_level=args[i+1]; } else if (args[i]=="-test") { test=args[i+1]; - } else if (args[i]=="-optimize") { - optimize=args[i+1]; - } else if (args[i]=="-optimize_preset") { - optimize_preset=args[i+1]; } else if (args[i]=="-export") { editor=true; //needs editor _export_platform=args[i+1]; @@ -1125,9 +1116,6 @@ bool Main::start() { } else if (args[i]=="-import_script") { editor=true; //needs editor _import_script=args[i+1]; - } else if (args[i]=="-dumpstrings") { - editor=true; //needs editor - dumpstrings=args[i+1]; } else { // The parameter does not match anything known, don't skip the next argument parsed_pair=false; @@ -1162,10 +1150,6 @@ bool Main::start() { return false; } - if (optimize!="") - editor=true; //need editor - - #endif @@ -1399,22 +1383,7 @@ bool Main::start() { Error serr = editor_node->load_scene(local_game_path); - if (serr==OK) { - if (optimize!="") { - - editor_node->save_optimized_copy(optimize,optimize_preset); - if (!noquit) - sml->quit(); - } - - if (dumpstrings!="") { - - editor_node->save_translatable_strings(dumpstrings); - if (!noquit) - sml->quit(); - } - } } OS::get_singleton()->set_context(OS::CONTEXT_EDITOR); diff --git a/platform/x11/detect.py b/platform/x11/detect.py index b5f6359d21..89cf639114 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -61,6 +61,7 @@ def get_opts(): ('use_static_cpp', 'link stdc++ statically', 'no'), ('use_sanitizer', 'Use llvm compiler sanitize address', 'no'), ('use_leak_sanitizer', 'Use llvm compiler sanitize memory leaks', 'no'), + ('use_lto', 'Use link time optimization', 'no'), ('pulseaudio', 'Detect & Use pulseaudio', 'yes'), ('udev', 'Use udev for gamepad connection callbacks', 'no'), ('debug_release', 'Add debug symbols to release version', 'no'), @@ -97,12 +98,12 @@ def configure(env): env.extra_suffix = ".llvm" if (env["use_sanitizer"] == "yes"): - env.Append(CXXFLAGS=['-fsanitize=address', '-fno-omit-frame-pointer']) + env.Append(CCFLAGS=['-fsanitize=address', '-fno-omit-frame-pointer']) env.Append(LINKFLAGS=['-fsanitize=address']) env.extra_suffix += "s" if (env["use_leak_sanitizer"] == "yes"): - env.Append(CXXFLAGS=['-fsanitize=address', '-fno-omit-frame-pointer']) + env.Append(CCFLAGS=['-fsanitize=address', '-fno-omit-frame-pointer']) env.Append(LINKFLAGS=['-fsanitize=address']) env.extra_suffix += "s" @@ -111,22 +112,28 @@ def configure(env): # env['OBJSUFFIX'] = ".nt"+env['OBJSUFFIX'] # env['LIBSUFFIX'] = ".nt"+env['LIBSUFFIX'] - if (env["target"] == "release"): + if (env["use_lto"] == "yes"): + env.Append(CCFLAGS=['-flto']) + env.Append(LINKFLAGS=['-flto']) + + + env.Append(CCFLAGS=['-pipe']) + env.Append(LINKFLAGS=['-pipe']) + if (env["target"] == "release"): + env.Prepend(CCFLAGS=['-Ofast']) if (env["debug_release"] == "yes"): - env.Append(CCFLAGS=['-g2']) - else: - env.Append(CCFLAGS=['-O3', '-ffast-math']) + env.Prepend(CCFLAGS=['-g2']) elif (env["target"] == "release_debug"): - env.Append(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED']) + env.Prepend(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED']) if (env["debug_release"] == "yes"): - env.Append(CCFLAGS=['-g2']) + env.Prepend(CCFLAGS=['-g2']) elif (env["target"] == "debug"): - env.Append(CCFLAGS=['-g2', '-Wall', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED']) + env.Prepend(CCFLAGS=['-g2', '-Wall', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED']) env.ParseConfig('pkg-config x11 --cflags --libs') env.ParseConfig('pkg-config xinerama --cflags --libs') diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index d1a8c458ba..6036b3f9df 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -482,14 +482,6 @@ void TextEdit::_notification(int p_what) { Color color = cache.font_color; int in_region=-1; - if (line_length_guideline) { - int x=xmargin_beg+cache.font->get_char_size('0').width*line_length_guideline_col-cursor.x_ofs; - if (x>xmargin_beg && x<xmargin_end) { - Color guideline_color(color.r,color.g,color.b,color.a*0.25f); - VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(x,0),Point2(x,cache.size.height),guideline_color); - } - } - if (syntax_coloring) { if (cache.background_color.a>0.01) { @@ -1080,6 +1072,14 @@ void TextEdit::_notification(int p_what) { } } + if (line_length_guideline) { + int x=xmargin_beg+cache.font->get_char_size('0').width*line_length_guideline_col-cursor.x_ofs; + if (x>xmargin_beg && x<xmargin_end) { + VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(x,0),Point2(x,cache.size.height),cache.line_length_guideline_color); + } + } + + bool completion_below = false; if (completion_active) { // code completion box @@ -3484,6 +3484,7 @@ void TextEdit::_update_caches() { cache.selection_color=get_color("selection_color"); cache.mark_color=get_color("mark_color"); cache.current_line_color=get_color("current_line_color"); + cache.line_length_guideline_color=get_color("line_length_guideline_color"); cache.breakpoint_color=get_color("breakpoint_color"); cache.brace_mismatch_color=get_color("brace_mismatch_color"); cache.word_highlighted_color=get_color("word_highlighted_color"); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 6113fd72c2..437e22ca40 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -91,6 +91,7 @@ class TextEdit : public Control { Color mark_color; Color breakpoint_color; Color current_line_color; + Color line_length_guideline_color; Color brace_mismatch_color; Color word_highlighted_color; Color search_result_color; diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp index 2d098d01f5..4d15ab86fd 100644 --- a/scene/io/resource_format_image.cpp +++ b/scene/io/resource_format_image.cpp @@ -27,6 +27,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "resource_format_image.h" + +#if 0 #include "scene/resources/texture.h" #include "io/image_loader.h" #include "globals.h" @@ -260,3 +262,4 @@ ResourceFormatLoaderImage::ResourceFormatLoaderImage() { GLOBAL_DEF("rendering/image_loader/repeat",false); } +#endif diff --git a/scene/io/resource_format_image.h b/scene/io/resource_format_image.h index 6e4ead2a0b..0638e97787 100644 --- a/scene/io/resource_format_image.h +++ b/scene/io/resource_format_image.h @@ -29,6 +29,8 @@ #ifndef RESOURCE_FORMAT_IMAGE_H #define RESOURCE_FORMAT_IMAGE_H +#if 0 + #include "io/resource_loader.h" #include "io/resource_saver.h" /** @@ -49,3 +51,4 @@ public: }; #endif +#endif diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 7e8a033c40..0ad140f7c3 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -230,7 +230,6 @@ #include "scene/resources/scene_format_text.h" -static ResourceFormatLoaderImage *resource_loader_image=NULL; //static ResourceFormatLoaderWAV *resource_loader_wav=NULL; @@ -245,6 +244,8 @@ static ResourceFormatLoaderText *resource_loader_text=NULL; static ResourceFormatLoaderDynamicFont *resource_loader_dynamic_font=NULL; +static ResourceFormatLoaderStreamTexture *resource_loader_stream_texture=NULL; + //static SceneStringNames *string_names; void register_scene_types() { @@ -255,14 +256,14 @@ void register_scene_types() { Node::init_node_hrcr(); - resource_loader_image = memnew( ResourceFormatLoaderImage ); - ResourceLoader::add_resource_format_loader( resource_loader_image ); - //resource_loader_wav = memnew( ResourceFormatLoaderWAV ); //ResourceLoader::add_resource_format_loader( resource_loader_wav ); resource_loader_dynamic_font = memnew( ResourceFormatLoaderDynamicFont ); ResourceLoader::add_resource_format_loader( resource_loader_dynamic_font ); + resource_loader_stream_texture = memnew( ResourceFormatLoaderStreamTexture); + ResourceLoader::add_resource_format_loader( resource_loader_stream_texture ); + #ifdef TOOLS_ENABLED //scene first! @@ -570,6 +571,7 @@ void register_scene_types() { ClassDB::register_virtual_class<Texture>(); ClassDB::register_virtual_class<SkyBox>(); ClassDB::register_class<ImageSkyBox>(); + ClassDB::register_class<StreamTexture>(); ClassDB::register_class<ImageTexture>(); ClassDB::register_class<AtlasTexture>(); ClassDB::register_class<LargeTexture>(); @@ -643,9 +645,9 @@ void unregister_scene_types() { clear_default_theme(); - memdelete( resource_loader_image ); // memdelete( resource_loader_wav ); memdelete( resource_loader_dynamic_font ); + memdelete( resource_loader_stream_texture ); #ifdef TOOLS_ENABLED diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index a1ad5d8237..a853b62254 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -453,6 +453,335 @@ ImageTexture::~ImageTexture() { VisualServer::get_singleton()->free( texture ); } +////////////////////////////////////////// + + + +uint32_t StreamTexture::get_flags() const { + + return flags; +} +Image::Format StreamTexture::get_format() const { + + return format; +} + + +Error StreamTexture::_load_data(const String& p_path,int &tw,int &th,int& flags,Image& image,int p_size_limit) { + + + FileAccess *f = FileAccess::open(p_path,FileAccess::READ); + ERR_FAIL_COND_V(!f,ERR_CANT_OPEN); + + uint8_t header[4]; + f->get_buffer(header,4); + if (header[0]!='G' || header[1]!='D' || header[2]!='S' || header[3]!='T') { + memdelete(f); + ERR_FAIL_COND_V(header[0]!='G' || header[1]!='D' || header[2]!='S' || header[3]!='T',ERR_FILE_CORRUPT); + } + + tw = f->get_32(); + th = f->get_32(); + flags= f->get_32(); //texture flags! + uint32_t df = f->get_32(); //data format + + print_line("width: "+itos(tw)); + print_line("height: "+itos(th)); + print_line("flags: "+itos(flags)); + print_line("df: "+itos(df)); + + if (!(df&FORMAT_BIT_STREAM)) { + p_size_limit=0; + } + + + if (df&FORMAT_BIT_LOSSLESS || df&FORMAT_BIT_LOSSY) { + //look for a PNG or WEBP file inside + + int sw=tw; + int sh=th; + + uint32_t mipmaps = f->get_32(); + uint32_t size = f->get_32(); + + print_line("mipmaps: "+itos(mipmaps)); + + while(mipmaps>1 && p_size_limit>0 && (sw>p_size_limit || sh>p_size_limit)) { + + f->seek(f->get_pos()+size); + mipmaps = f->get_32(); + size = f->get_32(); + + sw=MAX(sw>>1,1); + sh=MAX(sh>>1,1); + mipmaps--; + } + + //mipmaps need to be read independently, they will be later combined + Vector<Image> mipmap_images; + int total_size=0; + + for(int i=0;i<mipmaps;i++) { + PoolVector<uint8_t> pv; + pv.resize(size); + { + PoolVector<uint8_t>::Write w = pv.write(); + f->get_buffer(w.ptr(),size); + } + + Image img; + if (df&FORMAT_BIT_LOSSLESS) { + img = Image::lossless_unpacker(pv); + } else { + img = Image::lossy_unpacker(pv); + } + + if (img.empty()) { + memdelete(f); + ERR_FAIL_COND_V(img.empty(),ERR_FILE_CORRUPT); + } + total_size+=img.get_data().size(); + + mipmap_images.push_back(img); + } + + print_line("mipmap read total: "+itos(mipmap_images.size())); + + + memdelete(f); //no longer needed + + if (mipmap_images.size()==1) { + + image=mipmap_images[0]; + return OK; + + } else { + PoolVector<uint8_t> img_data; + img_data.resize(total_size); + + { + PoolVector<uint8_t>::Write w=img_data.write(); + + int ofs=0; + for(int i=0;i<mipmap_images.size();i++) { + + PoolVector<uint8_t> id = mipmap_images[i].get_data(); + int len = id.size(); + PoolVector<uint8_t>::Read r = id.read(); + copymem(&w[ofs],r.ptr(),len); + ofs+=len; + } + } + + image = Image(sw,sh,true,mipmap_images[0].get_format(),img_data); + return OK; + } + + } else { + + //look for regular format + Image::Format format = (Image::Format)(df&FORMAT_MASK_IMAGE_FORMAT); + bool mipmaps = df&FORMAT_BIT_HAS_MIPMAPS; + + if (!mipmaps) { + int size = Image::get_image_data_size(tw,th,format,0); + + PoolVector<uint8_t> img_data; + img_data.resize(size); + + { + PoolVector<uint8_t>::Write w=img_data.write(); + f->get_buffer(w.ptr(),size); + } + + memdelete(f); + + image = Image(tw,th,false,format,img_data); + return OK; + } else { + + int sw=tw; + int sh=th; + + int mipmaps = Image::get_image_required_mipmaps(tw,th,format); + int total_size = Image::get_image_data_size(tw,th,format,mipmaps); + int idx=0; + int ofs=0; + + + while(mipmaps>1 && p_size_limit>0 && (sw>p_size_limit || sh>p_size_limit)) { + + sw=MAX(sw>>1,1); + sh=MAX(sh>>1,1); + mipmaps--; + idx++; + } + + if (idx>0) { + ofs=Image::get_image_data_size(tw,th,format,idx-1); + } + + if (total_size - ofs <=0) { + memdelete(f); + ERR_FAIL_V(ERR_FILE_CORRUPT); + } + + f->seek(f->get_pos()+ofs); + + + PoolVector<uint8_t> img_data; + img_data.resize(total_size - ofs); + + { + PoolVector<uint8_t>::Write w=img_data.write(); + int bytes = f->get_buffer(w.ptr(),total_size - ofs); + + memdelete(f); + + if (bytes != total_size - ofs) { + ERR_FAIL_V(ERR_FILE_CORRUPT); + } + } + + image = Image(sw,sh,true,format,img_data); + + return OK; + } + } + + return ERR_BUG; //unreachable +} + +Error StreamTexture::load(const String& p_path) { + + + int lw,lh,lflags; + Image image; + Error err = _load_data(p_path,lw,lh,lflags,image); + if (err) + return err; + + VS::get_singleton()->texture_allocate(texture,image.get_width(),image.get_height(),image.get_format(),lflags); + VS::get_singleton()->texture_set_data(texture,image); + + w=lw; + h=lh; + flags=lflags; + path_to_file=p_path; + format=image.get_format(); + + return OK; +} +String StreamTexture::get_load_path() const { + + return path_to_file; +} + +int StreamTexture::get_width() const { + + return w; +} +int StreamTexture::get_height() const { + + return h; +} +RID StreamTexture::get_rid() const { + + return texture; +} + + +void StreamTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const { + + if ((w|h)==0) + return; + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, Size2(w,h)),texture,false,p_modulate,p_transpose); + +} +void StreamTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const { + + if ((w|h)==0) + return; + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,texture,p_tile,p_modulate,p_transpose); + +} +void StreamTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) const{ + + if ((w|h)==0) + return; + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,texture,p_src_rect,p_modulate,p_transpose); +} + +bool StreamTexture::has_alpha() const { + + return false; +} +void StreamTexture::set_flags(uint32_t p_flags){ + +} + +void StreamTexture::reload_from_file() { + + load(path_to_file); +} + +void StreamTexture::_bind_methods() { + + ClassDB::bind_method(_MD("load","path"),&StreamTexture::load); + ClassDB::bind_method(_MD("get_load_path"),&StreamTexture::get_load_path); + + ADD_PROPERTY( PropertyInfo(Variant::STRING,"load_path",PROPERTY_HINT_FILE,"*.stex"),_SCS("load"),_SCS("get_load_path")); +} + + +StreamTexture::StreamTexture() { + + format=Image::FORMAT_MAX; + flags=0; + w=0; + h=0; + + texture = VS::get_singleton()->texture_create(); +} + +StreamTexture::~StreamTexture() { + + VS::get_singleton()->free(texture); +} + + + +RES ResourceFormatLoaderStreamTexture::load(const String &p_path,const String& p_original_path,Error *r_error) { + + Ref<StreamTexture> st; + st.instance(); + Error err = st->load(p_path); + if (r_error) + *r_error=err; + if (err!=OK) + return RES(); + + return st; +} + +void ResourceFormatLoaderStreamTexture::get_recognized_extensions(List<String> *p_extensions) const{ + + p_extensions->push_back("stex"); +} +bool ResourceFormatLoaderStreamTexture::handles_type(const String& p_type) const{ + return p_type=="StreamTexture"; + +} +String ResourceFormatLoaderStreamTexture::get_resource_type(const String &p_path) const{ + + if (p_path.get_extension().to_lower()=="stex") + return "StreamTexture"; + return ""; +} + + + + ////////////////////////////////////////// diff --git a/scene/resources/texture.h b/scene/resources/texture.h index aac3514af3..919c588894 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -31,6 +31,7 @@ #include "resource.h" #include "servers/visual_server.h" +#include "io/resource_loader.h" #include "math_2d.h" /** @@ -160,6 +161,76 @@ public: }; + +class StreamTexture : public Texture { + + GDCLASS( StreamTexture, Texture ); +public: + enum DataFormat { + DATA_FORMAT_IMAGE, + DATA_FORMAT_LOSSLESS, + DATA_FORMAT_LOSSY + }; + + enum FormatBits { + FORMAT_MASK_IMAGE_FORMAT=(1<<20)-1, + FORMAT_BIT_LOSSLESS=1<<20, + FORMAT_BIT_LOSSY=1<<21, + FORMAT_BIT_STREAM=1<<22, + FORMAT_BIT_HAS_MIPMAPS=1<<23, + }; + +private: + + Error _load_data(const String &p_path, int &tw, int &th, int& flags, Image& image, int p_size_limit=0); + String path_to_file; + RID texture; + Image::Format format; + uint32_t flags; + int w,h; + + virtual void reload_from_file(); + +protected: + + static void _bind_methods(); + +public: + + + uint32_t get_flags() const; + Image::Format get_format() const; + Error load(const String& p_path); + String get_load_path() const; + + int get_width() const; + int get_height() const; + virtual RID get_rid() const; + + virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + + virtual bool has_alpha() const; + virtual void set_flags(uint32_t p_flags); + + StreamTexture(); + ~StreamTexture(); + +}; + + +class ResourceFormatLoaderStreamTexture : public ResourceFormatLoader { +public: + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; + +}; + + + VARIANT_ENUM_CAST( ImageTexture::Storage ); class AtlasTexture : public Texture { diff --git a/tools/editor/SCsub b/tools/editor/SCsub index 85d4d11073..a0e6802348 100644 --- a/tools/editor/SCsub +++ b/tools/editor/SCsub @@ -78,3 +78,4 @@ if (env["tools"] == "yes"): SConscript('plugins/SCsub') SConscript('fileserver/SCsub') SConscript('io_plugins/SCsub') + SConscript('import/SCsub') diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp index 120cbb9712..1d7d58591c 100644 --- a/tools/editor/editor_file_system.cpp +++ b/tools/editor/editor_file_system.cpp @@ -34,8 +34,10 @@ #include "os/file_access.h" #include "editor_node.h" #include "io/resource_saver.h" +#include "io/resource_import.h" #include "editor_settings.h" #include "editor_resource_preview.h" +#include "variant_parser.h" EditorFileSystem *EditorFileSystem::singleton=NULL; @@ -115,74 +117,12 @@ String EditorFileSystemDirectory::get_file_path(int p_idx) const { return "res://"+file; } -bool EditorFileSystemDirectory::get_file_meta(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),""); - return files[p_idx]->meta.enabled; -} Vector<String> EditorFileSystemDirectory::get_file_deps(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>()); - return files[p_idx]->meta.deps; - -} -Vector<String> EditorFileSystemDirectory::get_missing_sources(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>()); - Vector<String> missing; - for(int i=0;i<files[p_idx]->meta.sources.size();i++) { - if (files[p_idx]->meta.sources[i].missing) - missing.push_back(files[p_idx]->meta.sources[i].path); - } - - return missing; - - -} -bool EditorFileSystemDirectory::is_missing_sources(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),false); - for(int i=0;i<files[p_idx]->meta.sources.size();i++) { - if (files[p_idx]->meta.sources[i].missing) - return true; - } - - return false; -} - -bool EditorFileSystemDirectory::have_sources_changed(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),false); - return files[p_idx]->meta.sources_changed; - -} - -int EditorFileSystemDirectory::get_source_count(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),0); - if (!files[p_idx]->meta.enabled) - return 0; - return files[p_idx]->meta.sources.size(); -} -String EditorFileSystemDirectory::get_source_file(int p_idx,int p_source) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),String()); - ERR_FAIL_INDEX_V(p_source,files[p_idx]->meta.sources.size(),String()); - if (!files[p_idx]->meta.enabled) - return String(); - - return files[p_idx]->meta.sources[p_source].path; - -} -bool EditorFileSystemDirectory::is_source_file_missing(int p_idx,int p_source) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),false); - ERR_FAIL_INDEX_V(p_source,files[p_idx]->meta.sources.size(),false); - if (!files[p_idx]->meta.enabled) - return false; + return files[p_idx]->deps; - return files[p_idx]->meta.sources[p_source].missing; } @@ -210,7 +150,6 @@ void EditorFileSystemDirectory::_bind_methods() { ClassDB::bind_method(_MD("get_file","idx"),&EditorFileSystemDirectory::get_file); ClassDB::bind_method(_MD("get_file_path","idx"),&EditorFileSystemDirectory::get_file_path); ClassDB::bind_method(_MD("get_file_type","idx"),&EditorFileSystemDirectory::get_file_type); - ClassDB::bind_method(_MD("is_missing_sources","idx"),&EditorFileSystemDirectory::is_missing_sources); ClassDB::bind_method(_MD("get_name"),&EditorFileSystemDirectory::get_name); ClassDB::bind_method(_MD("get_path"),&EditorFileSystemDirectory::get_path); ClassDB::bind_method(_MD("get_parent:EditorFileSystemDirectory"),&EditorFileSystemDirectory::get_parent); @@ -244,42 +183,6 @@ EditorFileSystemDirectory::~EditorFileSystemDirectory() { - -EditorFileSystemDirectory::ImportMeta EditorFileSystem::_get_meta(const String& p_path) { - - return EditorFileSystemDirectory::ImportMeta(); -#if 0 - Ref<ResourceImportMetadata> imd = ResourceLoader::load_import_metadata(p_path); - EditorFileSystemDirectory::ImportMeta m; - if (imd.is_null()) { - m.enabled=false; - m.sources_changed=false; - } else { - m.enabled=true; - m.sources_changed=false; - - for(int i=0;i<imd->get_source_count();i++) { - EditorFileSystemDirectory::ImportMeta::Source s; - s.path=imd->get_source_path(i); - s.md5=imd->get_source_md5(i); - s.modified_time=0; - s.missing=false; - m.sources.push_back(s); - } - m.import_editor=imd->get_editor(); - } - - List<String> deps; - ResourceLoader::get_dependencies(p_path,&deps); - for(List<String>::Element *E=deps.front();E;E=E->next()) { - m.deps.push_back(E->get()); - } - - return m; -#endif -} - - void EditorFileSystem::_scan_filesystem() { ERR_FAIL_COND(!scanning || new_filesystem); @@ -292,7 +195,7 @@ void EditorFileSystem::_scan_filesystem() { String project=GlobalConfig::get_singleton()->get_resource_path(); - String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache"); + String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache2"); FileAccess *f =FileAccess::open(fscache,FileAccess::READ); if (f) { @@ -322,30 +225,14 @@ void EditorFileSystem::_scan_filesystem() { FileCache fc; fc.type=split[1]; fc.modification_time=split[2].to_int64(); - String meta = split[3].strip_edges(); - fc.meta.enabled=false; - if (meta.find("<>")!=-1){ - Vector<String> spl = meta.split("<>"); - int sc = spl.size()-1; - if (sc%3==0){ - fc.meta.enabled=true; - fc.meta.import_editor=spl[0]; - fc.meta.sources.resize(sc/3); - for(int i=0;i<fc.meta.sources.size();i++) { - fc.meta.sources[i].path=spl[1+i*3+0]; - fc.meta.sources[i].md5=spl[1+i*3+1]; - fc.meta.sources[i].modified_time=spl[1+i*3+2].to_int64(); - } + fc.import_modification_time = split[3].to_int64(); - } - - } String deps = split[4].strip_edges(); if (deps.length()) { Vector<String> dp = deps.split("<>"); for(int i=0;i<dp.size();i++) { String path=dp[i]; - fc.meta.deps.push_back(path); + fc.deps.push_back(path); } } @@ -393,7 +280,14 @@ void EditorFileSystem::_scan_filesystem() { } +void EditorFileSystem::_save_filesystem_cache() { + String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache2"); + FileAccess *f=FileAccess::open(fscache,FileAccess::WRITE); + _save_filesystem_cache(filesystem,f); + f->close(); + memdelete(f); +} void EditorFileSystem::_thread_func(void *_userdata) { @@ -408,6 +302,8 @@ bool EditorFileSystem::_update_scan_actions() { bool fs_changed=false; + Vector<String> reimports; + for (List<ItemAction>::Element *E=scan_actions.front();E;E=E->next()) { ItemAction&ia = E->get(); @@ -472,18 +368,25 @@ bool EditorFileSystem::_update_scan_actions() { //print_line("*ACTION REMOVE FILE: "+ia.file); } break; - case ItemAction::ACTION_FILE_SOURCES_CHANGED: { + case ItemAction::ACTION_FILE_REIMPORT: { + int idx = ia.dir->find_file_index(ia.file); ERR_CONTINUE(idx==-1); String full_path = ia.dir->get_file_path(idx); - sources_changed.push_back(full_path); + reimports.push_back(full_path); + fs_changed=true; } break; } } + + if (reimports.size()) { + reimport_files(reimports); + + } scan_actions.clear(); return fs_changed; @@ -495,9 +398,10 @@ void EditorFileSystem::scan() { if (false /*&& bool(Globals::get_singleton()->get("debug/disable_scan"))*/) return; - if (scanning || scanning_sources|| thread) + if (scanning || scanning_changes|| thread) return; + _update_extensions(); abort_scan=false; if (!use_threads) { @@ -532,43 +436,6 @@ void EditorFileSystem::scan() { } -bool EditorFileSystem::_check_meta_sources(EditorFileSystemDirectory::ImportMeta & p_meta) { - - if (p_meta.enabled) { - - for(int j=0;j<p_meta.sources.size();j++) { - -#if 0 - String src = EditorImportPlugin::expand_source_path(p_meta.sources[j].path); - - if (!FileAccess::exists(src)) { - p_meta.sources[j].missing=true; - continue; - } - - p_meta.sources[j].missing=false; - - uint64_t mt = FileAccess::get_modified_time(src); - - if (mt!=p_meta.sources[j].modified_time) { - //scan - String md5 = FileAccess::get_md5(src); - //print_line("checking: "+src); - //print_line("md5: "+md5); - //print_line("vs: "+p_meta.sources[j].md5); - if (md5!=p_meta.sources[j].md5) { - //really changed - return true; - } - p_meta.sources[j].modified_time=mt; - } -#endif - } - } - - return false; -} - void EditorFileSystem::ScanProgress::update(int p_current,int p_total) const { float ratio = low + ((hi-low)/p_total)*p_current; @@ -584,9 +451,75 @@ EditorFileSystem::ScanProgress EditorFileSystem::ScanProgress::get_sub(int p_cur sp.hi=slice; return sp; - } +bool EditorFileSystem::_check_missing_imported_files(const String& p_path) { + + if (!reimport_on_missing_imported_files) + return true; + + Error err; + FileAccess *f= FileAccess::open(p_path+".import",FileAccess::READ,&err); + + if (!f) { + print_line("could not open import for "+p_path); + return false; + } + + VariantParser::StreamFile stream; + stream.f=f; + + String assign; + Variant value; + VariantParser::Tag next_tag; + + int lines=0; + String error_text; + + List<String> to_check; + + while(true) { + + assign=Variant(); + next_tag.fields.clear(); + next_tag.name=String(); + + err = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,NULL,true); + if (err==ERR_FILE_EOF) { + memdelete(f); + return OK; + } + else if (err!=OK) { + ERR_PRINTS("ResourceFormatImporter::load - "+p_path+".import:"+itos(lines)+" error: "+error_text); + memdelete(f); + return false; + } + + if (assign!=String()) { + if (assign.begins_with("path")) { + to_check.push_back(value); + } else if (assign=="files") { + Array fa = value; + for(int i=0;i<fa.size();i++) { + to_check.push_back(fa[i]); + } + } + + } else if (next_tag.name!="remap" && next_tag.name!="deps") { + break; + } + } + + memdelete(f); + + for (List<String>::Element *E=to_check.front();E;E=E->next()) { + if (!FileAccess::exists(E->get())) { + print_line("missing "+E->get()+", reimport" ); + return false; + } + } + return true; +} void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess *da,const ScanProgress& p_progress) { @@ -675,9 +608,11 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess for (List<String>::Element*E=files.front();E;E=E->next(),idx++) { + String ext = E->get().get_extension().to_lower(); - if (!valid_extensions.has(ext)) + if (!valid_extensions.has(ext)) { continue; //invalid + } EditorFileSystemDirectory::FileInfo *fi = memnew( EditorFileSystemDirectory::FileInfo ); fi->file=E->get(); @@ -687,32 +622,45 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess FileCache *fc = file_cache.getptr(path); uint64_t mt = FileAccess::get_modified_time(path); - if (fc && fc->modification_time == mt) { + if (import_extensions.has(ext)) { - fi->meta=fc->meta; - fi->type=fc->type; - fi->modified_time=fc->modification_time; - } else { - fi->meta=_get_meta(path); - fi->type=ResourceLoader::get_resource_type(path); - fi->modified_time=mt; + //is imported + uint64_t import_mt=0; + if (FileAccess::exists(path+".import")) { + import_mt=FileAccess::get_modified_time(path+".import"); + } - } + if (fc && fc->modification_time==mt && fc->import_modification_time==import_mt && _check_missing_imported_files(path)) { + + fi->type=fc->type; + fi->modified_time=fc->modification_time; + fi->import_modified_time=fc->import_modification_time; + + } else { + + print_line("REIMPORT BECAUSE: time changed"); + fi->type=ResourceFormatImporter::get_singleton()->get_resource_type(path); + fi->modified_time=0; + fi->import_modified_time=0; - if (fi->meta.enabled) { - if (_check_meta_sources(fi->meta)) { ItemAction ia; - ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED; + ia.action=ItemAction::ACTION_FILE_REIMPORT; ia.dir=p_dir; ia.file=E->get(); scan_actions.push_back(ia); - fi->meta.sources_changed=true; - } else { - fi->meta.sources_changed=false; } - } else { - fi->meta.sources_changed=true; + //not imported, so just update type if changed + if (fc && fc->modification_time == mt) { + + fi->type=fc->type; + fi->modified_time=fc->modification_time; + fi->import_modified_time=0; + } else { + fi->type=ResourceLoader::get_resource_type(path); + fi->modified_time=mt; + fi->import_modified_time=0; + } } p_dir->files.push_back(fi); @@ -722,11 +670,13 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess } + void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const ScanProgress& p_progress) { uint64_t current_mtime = FileAccess::get_modified_time(p_dir->get_path()); bool updated_dir=false; + String cd = p_dir->get_path(); //print_line("dir: "+p_dir->get_path()+" MODTIME: "+itos(p_dir->modified_time)+" CTIME: "+itos(current_mtime)); @@ -751,7 +701,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S //then scan files and directories and check what's different DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); - String cd = p_dir->get_path(); + da->change_dir(cd); da->list_dir_begin(); while (true) { @@ -807,7 +757,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S String path = cd.plus_file(fi->file); fi->modified_time=FileAccess::get_modified_time(path); - fi->meta=_get_meta(path); + fi->import_modified_time=0; fi->type=ResourceLoader::get_resource_type(path); { @@ -817,19 +767,18 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S ia.file=f; ia.new_file=fi; scan_actions.push_back(ia); - } - //take the chance and scan sources - if (_check_meta_sources(fi->meta)) { + } + + if (import_extensions.has(ext)) { + //if it can be imported, and it was added, it needs to be reimported + print_line("REIMPORT: file was not found before, reimport"); ItemAction ia; - ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED; + ia.action=ItemAction::ACTION_FILE_REIMPORT; ia.dir=p_dir; ia.file=f; scan_actions.push_back(ia); - fi->meta.sources_changed=true; - } else { - fi->meta.sources_changed=false; } } else { @@ -859,15 +808,42 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S } - if (_check_meta_sources(p_dir->files[i]->meta)) { - ItemAction ia; - ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED; - ia.dir=p_dir; - ia.file=p_dir->files[i]->file; - scan_actions.push_back(ia); - p_dir->files[i]->meta.sources_changed=true; - } else { - p_dir->files[i]->meta.sources_changed=false; + if (import_extensions.has(p_dir->files[i]->file.get_extension().to_lower())) { + //check here if file must be imported or not + + String path = cd.plus_file(p_dir->files[i]->file); + + uint64_t mt = FileAccess::get_modified_time(path); + + bool reimport=false; + + if (mt!=p_dir->files[i]->modified_time) { + print_line("REIMPORT: modified time changed, reimport"); + reimport=true; //it was modified, must be reimported. + } else if (!FileAccess::exists(path+".import")) { + print_line("REIMPORT: no .import exists, reimport"); + reimport=true; //no .import file, obviously reimport + } else { + + uint64_t import_mt=FileAccess::get_modified_time(path+".import"); + if (import_mt!=p_dir->files[i]->import_modified_time) { + print_line("REIMPORT: import modified changed, reimport"); + reimport=true; + } else if (!_check_missing_imported_files(path)) { + print_line("REIMPORT: imported files removed"); + reimport=true; + } + } + + if (reimport) { + + ItemAction ia; + ia.action=ItemAction::ACTION_FILE_REIMPORT; + ia.dir=p_dir; + ia.file=p_dir->files[i]->file; + scan_actions.push_back(ia); + } + } EditorResourcePreview::get_singleton()->check_for_invalidation(p_dir->get_file_path(i)); @@ -900,7 +876,7 @@ void EditorFileSystem::_thread_func_sources(void *_userdata) { sp.low=0; efs->_scan_fs_changes(efs->filesystem,sp); } - efs->scanning_sources_done=true; + efs->scanning_changes_done=true; } void EditorFileSystem::get_changed_sources(List<String> *r_changed) { @@ -908,14 +884,15 @@ void EditorFileSystem::get_changed_sources(List<String> *r_changed) { *r_changed=sources_changed; } -void EditorFileSystem::scan_sources() { +void EditorFileSystem::scan_changes() { - if (scanning || scanning_sources|| thread) + if (scanning || scanning_changes|| thread) return; + _update_extensions(); sources_changed.clear(); - scanning_sources=true; - scanning_sources_done=false; + scanning_changes=true; + scanning_changes_done=false; abort_scan=false; @@ -931,8 +908,8 @@ void EditorFileSystem::scan_sources() { if (_update_scan_actions()) emit_signal("filesystem_changed"); } - scanning_sources=false; - scanning_sources_done=true; + scanning_changes=false; + scanning_changes_done=true; emit_signal("sources_changed",sources_changed.size()>0); } else { @@ -987,11 +964,11 @@ void EditorFileSystem::_notification(int p_what) { if (use_threads) { - if (scanning_sources) { + if (scanning_changes) { - if (scanning_sources_done) { + if (scanning_changes_done) { - scanning_sources=false; + scanning_changes=false; set_process(false); @@ -1053,22 +1030,13 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory*p_dir,Fi for(int i=0;i<p_dir->files.size();i++) { - String s=p_dir->files[i]->file+"::"+p_dir->files[i]->type+"::"+String::num(p_dir->files[i]->modified_time)+"::"; - if (p_dir->files[i]->meta.enabled) { - s+=p_dir->files[i]->meta.import_editor; - for(int j=0;j<p_dir->files[i]->meta.sources.size();j++){ - s+="<>"+p_dir->files[i]->meta.sources[j].path; - s+="<>"+p_dir->files[i]->meta.sources[j].md5; - s+="<>"+String::num(p_dir->files[i]->meta.sources[j].modified_time); - - } - } + String s=p_dir->files[i]->file+"::"+p_dir->files[i]->type+"::"+itos(p_dir->files[i]->modified_time)+"::"+itos(p_dir->files[i]->import_modified_time); s+="::"; - for(int j=0;j<p_dir->files[i]->meta.deps.size();j++) { + for(int j=0;j<p_dir->files[i]->deps.size();j++) { if (j>0) s+="<>"; - s+=p_dir->files[i]->meta.deps[j]; + s+=p_dir->files[i]->deps[j]; } p_file->store_line(s); @@ -1261,35 +1229,9 @@ void EditorFileSystem::_resource_saved(const String& p_path){ } -String EditorFileSystem::_find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const { - - for(int i=0;i<p_dir->files.size();i++) { - for(int j=0;j<p_dir->files[i]->meta.sources.size();j++) { - - if (p_dir->files[i]->meta.sources[j].path==p_src) - return p_dir->get_file_path(i); - } - } - - for(int i=0;i<p_dir->subdirs.size();i++) { - - String ret = _find_first_from_source(p_dir->subdirs[i],p_src); - if (ret.length()>0) - return ret; - } - - return String(); -} - -String EditorFileSystem::find_resource_from_source(const String& p_path) const { - if (filesystem) - return _find_first_from_source(filesystem,p_path); - return String(); -} - void EditorFileSystem::update_file(const String& p_file) { EditorFileSystemDirectory *fs=NULL; @@ -1339,7 +1281,7 @@ void EditorFileSystem::update_file(const String& p_file) { //print_line("UPDATING: "+p_file); fs->files[cpos]->type=type; fs->files[cpos]->modified_time=FileAccess::get_modified_time(p_file); - fs->files[cpos]->meta=_get_meta(p_file); + fs->files[cpos]->import_modified_time=0; EditorResourcePreview::get_singleton()->call_deferred("check_for_invalidation",p_file); call_deferred("emit_signal","filesystem_changed"); //update later @@ -1347,6 +1289,148 @@ void EditorFileSystem::update_file(const String& p_file) { } +void EditorFileSystem::_reimport_file(const String& p_file) { + + print_line("REIMPORTING: "+p_file); + + EditorFileSystemDirectory *fs=NULL; + int cpos=-1; + bool found = _find_file(p_file,&fs,cpos); + ERR_FAIL_COND(!found); + + //try to obtain existing params + + Map<StringName,Variant> params; + String importer_name; + + if (FileAccess::exists(p_file+".import")) { + + Ref<ConfigFile> cf; + cf.instance(); + Error err = cf->load(p_file+".import"); + if (err==OK) { + List<String> sk; + cf->get_section_keys("params",&sk); + for(List<String>::Element *E=sk.front();E;E=E->next()) { + params[E->get()]=cf->get_value("params",E->get()); + } + importer_name = cf->get_value("remap","importer"); + } + } + + Ref<ResourceImporter> importer; + //find the importer + if (importer_name!="") { + importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); + } + + if (importer.is_null()) { + //not found by name, find by extension + importer = ResourceFormatImporter::get_singleton()->get_importer_by_extension(p_file.get_extension()); + if (importer.is_null()) { + ERR_PRINT("BUG: File queued for import, but can't be imported!"); + ERR_FAIL(); + + } + } + + //mix with default params, in case a parameter is missing + + List<ResourceImporter::ImportOption> opts; + importer->get_import_options(&opts); + for (List<ResourceImporter::ImportOption>::Element *E=opts.front();E;E=E->next()) { + if (!params.has(E->get().option.name)) { //this one is not present + params[E->get().option.name]=E->get().default_value; + } + } + + //finally, perform import!! + String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_file); + + List<String> import_variants; + List<String> gen_files; + + Error err = importer->import(p_file,base_path,params,&import_variants,&gen_files); + + if (err!=OK) { + ERR_PRINTS("Error importing: "+p_file); + } + + //as import is complete, save the .import file + + FileAccess *f = FileAccess::open(p_file+".import",FileAccess::WRITE); + ERR_FAIL_COND(!f); + + //write manually, as order matters ([remap] has to go first for performance). + f->store_line("[remap]"); + f->store_line(""); + f->store_line("importer=\""+importer->get_importer_name()+"\""); + if (importer->get_resource_type()!="") { + f->store_line("type=\""+importer->get_resource_type()+"\""); + } + + if (importer->get_save_extension()=="") { + //no path + } else if (import_variants.size()) { + //import with variants + for(List<String>::Element *E=import_variants.front();E;E=E->next()) { + + + f->store_line("path."+E->get()+"=\""+base_path.c_escape()+"."+E->get()+"."+importer->get_save_extension()+"\""); + } + } else { + + f->store_line("path=\""+base_path+"."+importer->get_save_extension()+"\""); + } + + f->store_line(""); + if (gen_files.size()) { + f->store_line("[gen]"); + Array genf; + for (List<String>::Element *E=gen_files.front();E;E=E->next()) { + genf.push_back(E->get()); + } + + String value; + VariantWriter::write_to_string(genf,value); + f->store_line("files="+value); + f->store_line(""); + } + + + f->store_line("[params]"); + f->store_line(""); + + //store options in provided order, to avoid file changing + for (List<ResourceImporter::ImportOption>::Element *E=opts.front();E;E=E->next()) { + + String base = E->get().option.name; + String value; + VariantWriter::write_to_string(params[base],value); + f->store_line(base+"="+value); + + + } + + memdelete(f); + + //update modified times, to avoid reimport + fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); + fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file+".import"); +} + +void EditorFileSystem::reimport_files(const Vector<String>& p_files) { + + + EditorProgress pr("reimport",TTR("(Re)Importing Assets"),p_files.size()); + for(int i=0;i<p_files.size();i++) { + pr.step(p_files[i].get_file(),i); + + _reimport_file(p_files[i]); + } + + _save_filesystem_cache(); +} void EditorFileSystem::_bind_methods() { @@ -1355,7 +1439,7 @@ void EditorFileSystem::_bind_methods() { ClassDB::bind_method(_MD("is_scanning"),&EditorFileSystem::is_scanning); ClassDB::bind_method(_MD("get_scanning_progress"),&EditorFileSystem::get_scanning_progress); ClassDB::bind_method(_MD("scan"),&EditorFileSystem::scan); - ClassDB::bind_method(_MD("scan_sources"),&EditorFileSystem::scan_sources); + ClassDB::bind_method(_MD("scan_sources"),&EditorFileSystem::scan_changes); ClassDB::bind_method(_MD("update_file","path"),&EditorFileSystem::update_file); ClassDB::bind_method(_MD("get_filesystem_path:EditorFileSystemDirectory","path"),&EditorFileSystem::get_filesystem_path); ClassDB::bind_method(_MD("get_file_type","path"),&EditorFileSystem::get_file_type); @@ -1365,10 +1449,29 @@ void EditorFileSystem::_bind_methods() { } +void EditorFileSystem::_update_extensions() { + + valid_extensions.clear(); + import_extensions.clear(); + + List<String> extensionsl; + ResourceLoader::get_recognized_extensions_for_type("",&extensionsl); + for(List<String>::Element *E = extensionsl.front();E;E=E->next()) { + + valid_extensions.insert(E->get()); + } + extensionsl.clear(); + ResourceFormatImporter::get_singleton()->get_recognized_extensions(&extensionsl); + for(List<String>::Element *E = extensionsl.front();E;E=E->next()) { + + import_extensions.insert(E->get()); + } +} EditorFileSystem::EditorFileSystem() { + reimport_on_missing_imported_files = GLOBAL_DEF("editor/reimport_missing_imported_files",true); singleton=this; filesystem=memnew( EditorFileSystemDirectory ); //like, empty @@ -1379,16 +1482,14 @@ EditorFileSystem::EditorFileSystem() { thread_sources=NULL; new_filesystem=NULL; - scanning_sources=false; + scanning_changes=false; ResourceSaver::set_save_callback(_resource_saved); - List<String> extensionsl; - ResourceLoader::get_recognized_extensions_for_type("",&extensionsl); - for(List<String>::Element *E = extensionsl.front();E;E=E->next()) { - - valid_extensions.insert(E->get()); + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (da->change_dir("res://.import")!=OK) { + da->make_dir("res://.import"); } - + memdelete(da); scan_total=0; } diff --git a/tools/editor/editor_file_system.h b/tools/editor/editor_file_system.h index 3a26f46aa9..92169907a4 100644 --- a/tools/editor/editor_file_system.h +++ b/tools/editor/editor_file_system.h @@ -48,30 +48,13 @@ class EditorFileSystemDirectory : public Object { EditorFileSystemDirectory *parent; Vector<EditorFileSystemDirectory*> subdirs; - struct ImportMeta { - - struct Source { - - String path; - String md5; - uint64_t modified_time; - bool missing; - - }; - - Vector<Source> sources; - String import_editor; - Vector<String> deps; - bool enabled; - bool sources_changed; - - }; struct FileInfo { String file; StringName type; uint64_t modified_time; - ImportMeta meta; + uint64_t import_modified_time; + Vector<String> deps; bool verified; //used for checking changes }; @@ -101,14 +84,7 @@ public: String get_file(int p_idx) const; String get_file_path(int p_idx) const; StringName get_file_type(int p_idx) const; - bool get_file_meta(int p_idx) const; - bool is_missing_sources(int p_idx) const; - bool have_sources_changed(int p_idx) const; - Vector<String> get_missing_sources(int p_idx) const; Vector<String> get_file_deps(int p_idx) const; - int get_source_count(int p_idx) const; - String get_source_file(int p_idx,int p_source) const; - bool is_source_file_missing(int p_idx,int p_source) const; EditorFileSystemDirectory *get_parent(); @@ -136,7 +112,7 @@ class EditorFileSystem : public Node { ACTION_DIR_REMOVE, ACTION_FILE_ADD, ACTION_FILE_REMOVE, - ACTION_FILE_SOURCES_CHANGED + ACTION_FILE_REIMPORT }; Action action; @@ -171,7 +147,7 @@ class EditorFileSystem : public Node { String type; uint64_t modification_time; - EditorFileSystemDirectory::ImportMeta meta; + uint64_t import_modification_time; Vector<String> deps; }; @@ -186,25 +162,25 @@ class EditorFileSystem : public Node { ScanProgress get_sub(int p_current,int p_total) const; }; - static EditorFileSystemDirectory::ImportMeta _get_meta(const String& p_path); - - bool _check_meta_sources(EditorFileSystemDirectory::ImportMeta & p_meta); + void _save_filesystem_cache(); void _save_filesystem_cache(EditorFileSystemDirectory *p_dir,FileAccess *p_file); bool _find_file(const String& p_file,EditorFileSystemDirectory ** r_d, int &r_file_pos) const; void _scan_fs_changes(EditorFileSystemDirectory *p_dir, const ScanProgress &p_progress); + int md_count; Set<String> valid_extensions; + Set<String> import_extensions; void _scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess *da,const ScanProgress& p_progress); Thread *thread_sources; - bool scanning_sources; - bool scanning_sources_done; + bool scanning_changes; + bool scanning_changes_done; static void _thread_func_sources(void *_userdata); @@ -214,7 +190,14 @@ class EditorFileSystem : public Node { bool _update_scan_actions(); static void _resource_saved(const String& p_path); - String _find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const; + + void _update_extensions(); + + void _reimport_file(const String &p_file); + + bool _check_missing_imported_files(const String& p_path); + + bool reimport_on_missing_imported_files; protected: @@ -229,14 +212,16 @@ public: bool is_scanning() const; float get_scanning_progress() const; void scan(); - void scan_sources(); + void scan_changes(); void get_changed_sources(List<String> *r_changed); void update_file(const String& p_file); - String find_resource_from_source(const String& p_path) const; + EditorFileSystemDirectory *get_filesystem_path(const String& p_path); String get_file_type(const String& p_file) const; EditorFileSystemDirectory* find_file(const String& p_file,int* r_index) const; + void reimport_files(const Vector<String>& p_files); + EditorFileSystem(); ~EditorFileSystem(); }; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 4bbef01acf..a51507e96f 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -99,7 +99,8 @@ #include "plugins/color_ramp_editor_plugin.h" #include "plugins/collision_shape_2d_editor_plugin.h" #include "plugins/gi_probe_editor_plugin.h" - +#include "import/resource_import_texture.h" +#include "import/resource_importer_csv_translation.h" // end #include "editor_settings.h" #include "io_plugins/editor_texture_import_plugin.h" @@ -333,21 +334,6 @@ void EditorNode::_notification(int p_what) { _editor_select(EDITOR_3D); - if (defer_load_scene!="") { - - load_scene(defer_load_scene); - defer_load_scene=""; - } - - if (defer_translatable!="") { - - Error ok = save_translatable_strings(defer_translatable); - if (ok!=OK) - OS::get_singleton()->set_exit_code(255); - defer_translatable=""; - get_tree()->quit(); - } - /* if (defer_optimize!="") { Error ok = save_optimized_copy(defer_optimize,defer_optimize_preset); @@ -370,40 +356,7 @@ void EditorNode::_notification(int p_what) { if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) { - /* - List<Ref<Resource> > cached; - ResourceCache::get_cached_resources(&cached); - - bool changes=false; - for(List<Ref<Resource> >::Element *E=cached.front();E;E=E->next()) { - - if (!E->get()->can_reload_from_file()) - continue; - if (E->get()->get_path().find("::")!=-1) - continue; - uint64_t mt = FileAccess::get_modified_time(E->get()->get_path()); - if (mt!=E->get()->get_last_modified_time()) { - changes=true; - break; - } - } - - - - sources_button->get_popup()->set_item_disabled(sources_button->get_popup()->get_item_index(DEPENDENCY_UPDATE_LOCAL),!changes); - if (changes && sources_button->get_popup()->is_item_disabled(sources_button->get_popup()->get_item_index(DEPENDENCY_UPDATE_IMPORTED))) { - sources_button->set_icon(gui_base->get_icon("DependencyLocalChanged","EditorIcons")); - } -*/ - - if (bool(EDITOR_DEF("filesystem/resources/auto_reload_modified_images",true))) { - - _menu_option_confirm(DEPENDENCY_LOAD_CHANGED_IMAGES,true); - } - - waiting_for_sources_changed=true; - EditorFileSystem::get_singleton()->scan_sources(); - + EditorFileSystem::get_singleton()->scan_changes(); } if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) { @@ -435,59 +388,69 @@ void EditorNode::_fs_changed() { export_defer.platform=""; } -} + { -void EditorNode::_sources_changed(bool p_exist) { + //reload changed resources + List<Ref<Resource> > changed; - if (p_exist && bool(EditorSettings::get_singleton()->get("filesystem/import/automatic_reimport_on_sources_changed"))) { - p_exist=false; + List<Ref<Resource> > cached; + ResourceCache::get_cached_resources(&cached); + //this should probably be done in a thread.. + for(List<Ref<Resource> >::Element *E=cached.front();E;E=E->next()) { - List<String> changed_sources; - EditorFileSystem::get_singleton()->get_changed_sources(&changed_sources); + if (!E->get()->editor_can_reload_from_file()) + continue; + if (!E->get()->get_path().is_resource_file() && !E->get()->get_path().is_abs_path()) + continue; + if (!FileAccess::exists(E->get()->get_path())) + continue; + if (E->get()->get_import_path()!=String()) { + //imported resource + uint64_t mt = FileAccess::get_modified_time(E->get()->get_import_path()); - EditorProgress ep("reimport",TTR("Re-Importing"),changed_sources.size()); - int step_idx=0; -#if 0 - for(List<String>::Element *E=changed_sources.front();E;E=E->next()) { + if (mt!=E->get()->get_import_last_modified_time()) { + changed.push_back(E->get()); + } - ep.step(TTR("Importing:")+" "+E->get(),step_idx++); + } else { + uint64_t mt = FileAccess::get_modified_time(E->get()->get_path()); - Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(E->get()); - ERR_CONTINUE(rimd.is_null()); - String editor = rimd->get_editor(); - if (editor.begins_with("texture_")) { - editor="texture"; //compatibility fix for old versions - } - Ref<EditorImportPlugin> eip = EditorImportExport::get_singleton()->get_import_plugin_by_name(editor); - ERR_CONTINUE(eip.is_null()); - Error err = eip->import(E->get(),rimd); - if (err!=OK) { - EditorNode::add_io_error("Error Re Importing:\n "+E->get()); + if (mt!=E->get()->get_last_modified_time()) { + changed.push_back(E->get()); + } } + } + + if (changed.size()) { + //EditorProgress ep("reload_res","Reload Modified Resources",changed.size()); + int idx=0; + for(List<Ref<Resource> >::Element *E=changed.front();E;E=E->next()) { + //ep.step(E->get()->get_path(),idx++); + E->get()->reload_from_file(); + } } -#endif - EditorFileSystem::get_singleton()->scan_sources(); - waiting_for_sources_changed=false; - return; + } +} - if (p_exist) { +void EditorNode::_sources_changed(bool p_exist) { - sources_button->set_icon(gui_base->get_icon("DependencyChanged","EditorIcons")); - sources_button->set_disabled(false); + if (waiting_for_first_scan) { - } else { + if (defer_load_scene!="") { - sources_button->set_icon(gui_base->get_icon("DependencyOk","EditorIcons")); - sources_button->set_disabled(true); + print_line("loading scene DEFERED"); + load_scene(defer_load_scene); + defer_load_scene=""; + } + waiting_for_first_scan=false; } - waiting_for_sources_changed=false; } @@ -1206,12 +1169,6 @@ void EditorNode::_dialog_action(String p_file) { get_undo_redo()->clear_history(); } break; - case FILE_DUMP_STRINGS: { - - save_translatable_strings(p_file); - - } break; - case FILE_SAVE_SCENE: case FILE_SAVE_AS_SCENE: { @@ -2203,46 +2160,6 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { _menu_option_confirm(FILE_SAVE_AND_RUN, true); } break; - case FILE_DUMP_STRINGS: { - - Node *scene = editor_data.get_edited_scene_root(); - - if (!scene) { - - current_option=-1; - //confirmation->get_cancel()->hide(); - accept->get_ok()->set_text(TTR("I see..")); - accept->set_text("This operation can't be done without a tree root."); - accept->popup_centered_minsize(); - break; - } - - String cpath; - if (scene->get_filename()!="") { - cpath = scene->get_filename(); - - String fn = cpath.substr(0,cpath.length() - cpath.get_extension().size()); - String ext=cpath.get_extension(); - cpath=fn+".pot"; - - - } else { - current_option=-1; - //confirmation->get_cancel()->hide(); - accept->get_ok()->set_text(TTR("I see..")); - accept->set_text(TTR("Please save the scene first.")); - accept->popup_centered_minsize(); - break; - - } - - file->set_mode(EditorFileDialog::MODE_SAVE_FILE); - - file->set_current_path(cpath); - file->set_title(TTR("Save Translatable Strings")); - file->popup_centered_ratio(); - - } break; case FILE_SAVE_OPTIMIZED: { #if 0 Node *scene = editor_data.get_edited_scene_root(); @@ -2867,24 +2784,6 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { case DEPENDENCY_LOAD_CHANGED_IMAGES: { - List<Ref<Resource> > cached; - ResourceCache::get_cached_resources(&cached); - //this should probably be done in a thread.. - for(List<Ref<Resource> >::Element *E=cached.front();E;E=E->next()) { - - if (!E->get()->editor_can_reload_from_file()) - continue; - if (!E->get()->get_path().is_resource_file() && !E->get()->get_path().is_abs_path()) - continue; - if (!FileAccess::exists(E->get()->get_path())) - continue; - uint64_t mt = FileAccess::get_modified_time(E->get()->get_path()); - if (mt!=E->get()->get_last_modified_time()) { - E->get()->reload_from_file(); - } - - } - } break; case DEPENDENCY_UPDATE_IMPORTED: { @@ -3211,232 +3110,6 @@ void EditorNode::set_edited_scene(Node *p_scene) { } -void EditorNode::_fetch_translatable_strings(const Object *p_object,Set<StringName>& strings) { - - - List<String> tstrings; - p_object->get_translatable_strings(&tstrings); - for(List<String>::Element *E=tstrings.front();E;E=E->next()) - strings.insert(E->get()); - - - - const Node * node = p_object->cast_to<Node>(); - - if (!node) - return; - - Ref<Script> script = node->get_script(); - if (script.is_valid()) - _fetch_translatable_strings(script.ptr(),strings); - - for(int i=0;i<node->get_child_count();i++) { - - Node *c=node->get_child(i); - if (c->get_owner()!=get_edited_scene()) - continue; - - _fetch_translatable_strings(c,strings); - } - -} - - -Error EditorNode::save_translatable_strings(const String& p_to_file) { - - if (!is_inside_tree()) { - defer_translatable=p_to_file; - return OK; - } - - ERR_FAIL_COND_V(!get_edited_scene(),ERR_INVALID_DATA); - - Set<StringName> strings; - _fetch_translatable_strings(get_edited_scene(),strings); - - Error err; - FileAccess *f = FileAccess::open(p_to_file,FileAccess::WRITE,&err); - ERR_FAIL_COND_V(err,err); - - OS::Date date = OS::get_singleton()->get_date(); - OS::Time time = OS::get_singleton()->get_time(); - f->store_line("# Translation Strings Dump."); - f->store_line("# Created By."); - f->store_line("# \t" VERSION_FULL_NAME " (c) 2008-2017 Juan Linietsky, Ariel Manzur."); - f->store_line("# From Scene: "); - f->store_line("# \t"+get_edited_scene()->get_filename()); - f->store_line(""); - f->store_line("msgid \"\""); - f->store_line("msgstr \"\""); - f->store_line("\"Report-Msgid-Bugs-To: <define>\\n\""); - f->store_line("\"POT-Creation-Date: "+itos(date.year)+"-"+itos(date.month)+"-"+itos(date.day)+" "+itos(time.hour)+":"+itos(time.min)+"0000\\n\""); - //f->store_line("\"PO-Revision-Date: 2006-08-30 13:56-0700\\n\""); - //f->store_line("\"Last-Translator: Rubén C. DÃaz Alonso <outime@gmail.com>\\n\""); - f->store_line("\"Language-Team: <define>\\n\""); - f->store_line("\"MIME-Version: 1.0\\n\""); - f->store_line("\"Content-Type: text/plain; charset=UTF-8\\n\""); - f->store_line("\"Content-Transfer-Encoding: 8bit\\n\""); - f->store_line(""); - - for(Set<StringName>::Element *E=strings.front();E;E=E->next()) { - - String s = E->get(); - if (s=="" || s.strip_edges()=="") - continue; - Vector<String> substr = s.split("\n"); - ERR_CONTINUE(substr.size()==0); - - f->store_line(""); - - if (substr.size()==1) { - - f->store_line("msgid \""+substr[0].c_escape()+"\""); - } else { - - f->store_line("msgid \"\""); - for(int i=0;i<substr.size();i++) { - - String s = substr[i]; - if (i!=substr.size()-1) - s+="\n"; - f->store_line("\""+s.c_escape()+"\""); - } - } - - f->store_line("msgstr \"\""); - - } - - - f->close(); - memdelete(f); - - return OK; - -} - -Error EditorNode::save_optimized_copy(const String& p_scene,const String& p_preset) { - -#if 0 - - if (!is_inside_scene()) { - defer_optimize=p_scene; - defer_optimize_preset=p_preset; - return OK; - } - - - if (!get_edited_scene()) { - - get_scene()->quit(); - ERR_EXPLAIN("No scene to optimize (loading failed?)"); - ERR_FAIL_V(ERR_FILE_NOT_FOUND); - } - - - String src_scene=GlobalConfig::get_singleton()->localize_path(get_edited_scene()->get_filename()); - - - String path=p_scene; - print_line("p_path: "+p_scene); - print_line("src_scene: "+p_scene); - - if (path.is_rel_path()) { - print_line("rel path!?"); - path=src_scene.get_base_dir()+"/"+path; - } - path = GlobalConfig::get_singleton()->localize_path(path); - - print_line("path: "+path); - - - String preset = "optimizer_presets/"+p_preset; - if (!GlobalConfig::get_singleton()->has(preset)) { - - //accept->"()->hide(); - accept->get_ok()->set_text("I see.."); - accept->set_text("Optimizer preset not found: "+p_preset); - accept->popup_centered(Size2(300,70)); - ERR_EXPLAIN("Optimizer preset not found: "+p_preset); - ERR_FAIL_V(ERR_INVALID_PARAMETER); - - } - - Dictionary d = GlobalConfig::get_singleton()->get(preset); - - ERR_FAIL_COND_V(!d.has("__type__"),ERR_INVALID_DATA); - String type=d["__type__"]; - - Ref<EditorOptimizedSaver> saver; - - for(int i=0;i<editor_data.get_optimized_saver_count();i++) { - - print_line(type+" vs "+editor_data.get_optimized_saver(i)->get_target_name()); - if (editor_data.get_optimized_saver(i)->get_target_name()==type) { - saver=editor_data.get_optimized_saver(i); - } - } - - ERR_EXPLAIN("Preset '"+p_preset+"' references nonexistent saver: "+type); - ERR_FAIL_COND_V(saver.is_null(),ERR_INVALID_DATA); - - List<Variant> keys; - d.get_key_list(&keys); - - saver->clear(); - - for(List<Variant>::Element *E=keys.front();E;E=E->next()) { - - saver->set(E->get(),d[E->get()]); - } - - uint32_t flags=0; - - /* - if (saver->is_bundle_scenes_enabled()) - flags|=ResourceSaver::FLAG_BUNDLE_INSTANCED_SCENES; - */ - if (saver->is_bundle_resources_enabled()) - flags|=ResourceSaver::FLAG_BUNDLE_RESOURCES; - if (saver->is_remove_editor_data_enabled()) - flags|=ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES; - if (saver->is_big_endian_data_enabled()) - flags|=ResourceSaver::FLAG_SAVE_BIG_ENDIAN; - - String platform=saver->get_target_platform(); - if (platform=="") - platform="all"; - - Ref<PackedScene> sdata = memnew( PackedScene ); - Error err = sdata->pack(get_edited_scene()); - - if (err) { - - current_option=-1; - //accept->get_cancel()->hide(); - accept->get_ok()->set_text("I see.."); - accept->set_text("Couldn't save scene. Likely dependencies (instances) couldn't be satisfied."); - accept->popup_centered(Size2(300,70)); - return ERR_INVALID_DATA; - - } - err = ResourceSaver::save(path,sdata,flags); //todo, saverSceneSaver::save(path,get_edited_scene(),flags,saver); - - if (err) { - - //accept->"()->hide(); - accept->get_ok()->set_text("I see.."); - accept->set_text("Error saving optimized scene: "+path); - accept->popup_centered(Size2(300,70)); - - ERR_FAIL_COND_V(err,err); - - } - - project_settings->add_remapped_path(src_scene,path,platform); -#endif - return OK; -} int EditorNode::_get_current_main_editor() { @@ -3834,6 +3507,10 @@ void EditorNode::request_instance_scenes(const Vector<String>& p_files) { scene_tree_dock->instance_scenes(p_files); } +ImportDock *EditorNode::get_import_dock() { + return import_dock; +} + FileSystemDock *EditorNode::get_filesystem_dock() { return filesystem_dock; @@ -5063,7 +4740,6 @@ Variant EditorNode::drag_resource(const Ref<Resource>& p_res,Control* p_from) { TextureRect *drag_preview = memnew( TextureRect ); Label* label=memnew( Label ); - waiting_for_sources_changed=true; // Ref<Texture> preview; { @@ -5440,6 +5116,18 @@ EditorNode::EditorNode() { ResourceLoader::set_timestamp_on_load(true); ResourceSaver::set_timestamp_on_save(true); + + { //register importers at the begining, so dialogs are created with the right extensions + Ref<ResourceImporterTexture> import_texture; + import_texture.instance(); + ResourceFormatImporter::get_singleton()->add_importer(import_texture); + + Ref<ResourceImporterCSVTranslation> import_csv_translation; + import_csv_translation.instance(); + ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation); + + } + _pvrtc_register_compressors(); editor_selection = memnew( EditorSelection ); @@ -5765,7 +5453,6 @@ EditorNode::EditorNode() { pm_export->set_name("Export"); p->add_child(pm_export); p->add_submenu_item(TTR("Convert To.."),"Export"); - pm_export->add_item(TTR("Translatable Strings.."),FILE_DUMP_STRINGS); pm_export->add_separator(); pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_MeshLibrary", TTR("MeshLibrary..")), FILE_EXPORT_MESH_LIBRARY); pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_TileSet", TTR("TileSet..")), FILE_EXPORT_TILESET); @@ -6248,6 +5935,11 @@ EditorNode::EditorNode() { property_editor->set_undo_redo(&editor_data.get_undo_redo()); + import_dock = memnew( ImportDock ); + dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(import_dock); + import_dock->set_name(TTR("Import")); + + node_dock = memnew( NodeDock ); //node_dock->set_undoredo(&editor_data.get_undo_redo()); if (use_single_dock_column) { @@ -6584,6 +6276,9 @@ EditorNode::EditorNode() { plugin_init_callbacks[i](); } + + + /*resource_preview->add_preview_generator( Ref<EditorTexturePreviewPlugin>( memnew(EditorTexturePreviewPlugin ))); resource_preview->add_preview_generator( Ref<EditorPackedScenePreviewPlugin>( memnew(EditorPackedScenePreviewPlugin ))); resource_preview->add_preview_generator( Ref<EditorMaterialPreviewPlugin>( memnew(EditorMaterialPreviewPlugin ))); @@ -6730,6 +6425,7 @@ EditorNode::EditorNode() { FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify); + waiting_for_first_scan=true; } diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index faf11f5d20..785136a968 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -50,6 +50,7 @@ #include "tools/editor/reparent_dialog.h" #include "tools/editor/connections_dialog.h" #include "tools/editor/node_dock.h" +#include "tools/editor/import_dock.h" #include "tools/editor/settings_config_dialog.h" #include "tools/editor/groups_editor.h" #include "tools/editor/editor_data.h" @@ -134,7 +135,6 @@ private: FILE_EXPORT_MESH_LIBRARY, FILE_EXPORT_TILESET, FILE_SAVE_OPTIMIZED, - FILE_DUMP_STRINGS, FILE_OPEN_RECENT, FILE_OPEN_OLD_SCENE, FILE_QUICK_OPEN_SCENE, @@ -278,6 +278,7 @@ private: //ResourcesDock *resources_dock; PropertyEditor *property_editor; NodeDock *node_dock; + ImportDock *import_dock; VBoxContainer *prop_editor_vb; FileSystemDock *filesystem_dock; EditorRunNative *run_native; @@ -318,9 +319,6 @@ private: //TabContainer *prop_pallete; //TabContainer *top_pallete; String defer_load_scene; - String defer_translatable; - String defer_optimize; - String defer_optimize_preset; String defer_export; String defer_export_platform; bool defer_export_debug; @@ -376,6 +374,7 @@ private: bool unsaved_cache; String open_navigate; bool changing_scene; + bool waiting_for_first_scan; bool waiting_for_sources_changed; @@ -488,7 +487,6 @@ private: static void _load_error_notify(void* p_ud,const String& p_text); bool has_main_screen() const { return true; } - void _fetch_translatable_strings(const Object *p_object,Set<StringName>& strings); bool _find_editing_changed_scene(Node *p_from); @@ -683,7 +681,6 @@ public: Node *get_edited_scene() { return editor_data.get_edited_scene_root(); } Viewport *get_scene_root() { return scene_root; } //root of the scene being edited - Error save_optimized_copy(const String& p_scene,const String& p_preset); void fix_dependencies(const String& p_for_file); void clear_scene() { _cleanup_scene(); } @@ -703,13 +700,12 @@ public: void request_instance_scene(const String &p_path); void request_instance_scenes(const Vector<String>& p_files); FileSystemDock *get_filesystem_dock(); + ImportDock *get_import_dock(); SceneTreeDock *get_scene_tree_dock(); static UndoRedo* get_undo_redo() { return &singleton->editor_data.get_undo_redo(); } EditorSelection *get_editor_selection() { return editor_selection; } - Error save_translatable_strings(const String& p_to_file); - void set_convert_old_scene(bool p_old) { convert_old=p_old; } void notify_child_process_exited(); @@ -784,7 +780,6 @@ public: }; - struct EditorProgress { String task; diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index 822497fcab..1cdc426541 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -715,6 +715,7 @@ void EditorSettings::_load_default_text_editor_theme() { set("text_editor/highlighting/selection_color",Color::html("7b5dbe")); set("text_editor/highlighting/brace_mismatch_color",Color(1,0.2,0.2)); set("text_editor/highlighting/current_line_color",Color(0.3,0.5,0.8,0.15)); + set("text_editor/highlighting/line_length_guideline_color",Color(0.3,0.5,0.8,0.1)); set("text_editor/highlighting/mark_color", Color(1.0,0.4,0.4,0.4)); set("text_editor/highlighting/breakpoint_color", Color(0.8,0.8,0.4,0.2)); set("text_editor/highlighting/word_highlighted_color",Color(0.8,0.9,0.9,0.15)); @@ -972,6 +973,7 @@ bool EditorSettings::_save_text_editor_theme(String p_file) { cf->set_value(theme_section, "selection_color", ((Color)get("text_editor/highlighting/selection_color")).to_html()); cf->set_value(theme_section, "brace_mismatch_color", ((Color)get("text_editor/highlighting/brace_mismatch_color")).to_html()); cf->set_value(theme_section, "current_line_color", ((Color)get("text_editor/highlighting/current_line_color")).to_html()); + cf->set_value(theme_section, "line_length_guideline_color", ((Color)get("text_editor/highlighting/line_length_guideline_color")).to_html()); cf->set_value(theme_section, "mark_color", ((Color)get("text_editor/highlighting/mark_color")).to_html()); cf->set_value(theme_section, "breakpoint_color", ((Color)get("text_editor/highlighting/breakpoint_color")).to_html()); cf->set_value(theme_section, "word_highlighted_color", ((Color)get("text_editor/highlighting/word_highlighted_color")).to_html()); diff --git a/tools/editor/filesystem_dock.cpp b/tools/editor/filesystem_dock.cpp index 2af5650605..08b8307eb4 100644 --- a/tools/editor/filesystem_dock.cpp +++ b/tools/editor/filesystem_dock.cpp @@ -350,25 +350,9 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path,List<FileInfo>* m FileInfo fi; fi.name=file; fi.type=p_path->get_file_type(i); - fi.path=p_path->get_file_path(i); - if (p_path->get_file_meta(i)) { - if (p_path->is_missing_sources(i)) { - fi.import_status=3; - } else if (p_path->have_sources_changed(i)) { - fi.import_status=2; - } else { - fi.import_status=1; - } - } else { - fi.import_status=0; - } - for(int j=0;j<p_path->get_source_count(i);j++) { - /*String s = EditorImportPlugin::expand_source_path(p_path->get_source_file(i,j)); - if (p_path->is_source_file_missing(i,j)) { - s+=" (Missing)"; - } - fi.sources.push_back(s);*/ - } + fi.path=p_path->get_file_path(i); + fi.import_status=0; + matches->push_back(fi); if (matches->size()>p_max_items) @@ -500,25 +484,7 @@ void FileSystemDock::_update_files(bool p_keep_selection) { fi.name=efd->get_file(i); fi.path=path.plus_file(fi.name); fi.type=efd->get_file_type(i); - if (efd->get_file_meta(i)) { - if (efd->is_missing_sources(i)) { - fi.import_status=3; - } else if (efd->have_sources_changed(i)) { - fi.import_status=2; - } else { - fi.import_status=1; - } - - for(int j=0;j<efd->get_source_count(i);j++) { - /*String s = EditorImportPlugin::expand_source_path(efd->get_source_file(i,j)); - if (efd->is_source_file_missing(i,j)) { - s+=" (Missing)"; - } - fi.sources.push_back(s);*/ - } - } else { - fi.import_status=0; - } + fi.import_status=0; @@ -1538,26 +1504,6 @@ void FileSystemDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) { if (efsd) { - if (!efsd->get_file_meta(pos)) { - all_can_reimport=false; - - - } else { - /* - Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(path); - if (rimd.is_valid()) { - - String editor=rimd->get_editor(); - if (editor.begins_with("texture_")) { //compatibility fix for old texture format - editor="texture"; - } - types.insert(editor); - - } else { - all_can_reimport=false; - - }*/ - } } else { all_can_reimport=false; @@ -1642,6 +1588,57 @@ void FileSystemDock::select_file(const String& p_file) { } +void FileSystemDock::_file_multi_selected(int p_index,bool p_selected) { + + + _file_selected(); +} + +void FileSystemDock::_file_selected() { + + //check import + Vector<String> imports; + String import_type; + + for(int i=0;i<files->get_item_count();i++) { + if (!files->is_selected(i)) + continue; + + String p = files->get_item_metadata(i); + if (!FileAccess::exists(p+".import")) { + imports.clear(); + break; + } + Ref<ConfigFile> cf; + cf.instance(); + Error err = cf->load(p+".import"); + if (err!=OK) { + imports.clear(); + break; + } + + String type = cf->get_value("remap","type"); + if (import_type=="") { + import_type=type; + } else if (import_type!=type) { + //all should be the same type + imports.clear(); + break; + } + imports.push_back(p); + } + + + if (imports.size()==0) { + EditorNode::get_singleton()->get_import_dock()->clear(); + } else if (imports.size()==1) { + EditorNode::get_singleton()->get_import_dock()->set_edit_path(imports[0]); + } else { + EditorNode::get_singleton()->get_import_dock()->set_edit_multiple_paths(imports); + } +} + + void FileSystemDock::_bind_methods() { ClassDB::bind_method(_MD("_update_tree"),&FileSystemDock::_update_tree); @@ -1673,6 +1670,8 @@ void FileSystemDock::_bind_methods() { ClassDB::bind_method(_MD("_files_list_rmb_select"),&FileSystemDock::_files_list_rmb_select); ClassDB::bind_method(_MD("_preview_invalidated"),&FileSystemDock::_preview_invalidated); + ClassDB::bind_method(_MD("_file_selected"),&FileSystemDock::_file_selected); + ClassDB::bind_method(_MD("_file_multi_selected"),&FileSystemDock::_file_multi_selected); ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::POOL_STRING_ARRAY, "files"))); @@ -1777,6 +1776,8 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { files->set_select_mode(ItemList::SELECT_MULTI); files->set_drag_forwarding(this); files->connect("item_rmb_selected",this,"_files_list_rmb_select"); + files->connect("item_selected",this,"_file_selected"); + files->connect("multi_selected",this,"_file_multi_selected"); files->set_allow_rmb_select(true); file_list_vb = memnew( VBoxContainer ); diff --git a/tools/editor/filesystem_dock.h b/tools/editor/filesystem_dock.h index 73265657e5..224efe0f28 100644 --- a/tools/editor/filesystem_dock.h +++ b/tools/editor/filesystem_dock.h @@ -126,6 +126,11 @@ private: Tree * tree; //directories ItemList *files; + + void _file_multi_selected(int p_index, bool p_selected); + void _file_selected(); + + void _go_to_tree(); void _go_to_dir(const String& p_dir); void _select_file(int p_idx); diff --git a/tools/editor/import/SCsub b/tools/editor/import/SCsub new file mode 100644 index 0000000000..4bf55189cc --- /dev/null +++ b/tools/editor/import/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import('env') +Export('env') +env.add_source_files(env.tool_sources, "*.cpp") diff --git a/tools/editor/import/resource_import_texture.cpp b/tools/editor/import/resource_import_texture.cpp new file mode 100644 index 0000000000..940b932e54 --- /dev/null +++ b/tools/editor/import/resource_import_texture.cpp @@ -0,0 +1,274 @@ +#include "resource_import_texture.h" +#include "io/image_loader.h" +#include "scene/resources/texture.h" + +String ResourceImporterTexture::get_importer_name() const { + + return "texture"; +} + +String ResourceImporterTexture::get_visible_name() const{ + + return "Texture"; +} +void ResourceImporterTexture::get_recognized_extensions(List<String> *p_extensions) const{ + + ImageLoader::get_recognized_extensions(p_extensions); +} +String ResourceImporterTexture::get_save_extension() const { + return "stex"; +} + +String ResourceImporterTexture::get_resource_type() const{ + + return "StreamTexture"; +} + +bool ResourceImporterTexture::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const { + + if (p_option=="compress/lossy_quality" && int(p_options["compress/mode"])!=COMPRESS_LOSSY) + return false; + + return true; +} + +int ResourceImporterTexture::get_preset_count() const { + return 4; +} +String ResourceImporterTexture::get_preset_name(int p_idx) const { + + static const char* preset_names[]={ + "2D, Detect 3D", + "2D", + "2D Pixel", + "3D" + }; + + return preset_names[p_idx]; +} + + +void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,int p_preset) const { + + + r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Lossless,Lossy,Video RAM,Uncompressed",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),p_preset==PRESET_3D?2:0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"compress/lossy_quality",PROPERTY_HINT_RANGE,"0,1,0.01"),0.7)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"flags/repeat",PROPERTY_HINT_ENUM,"Disabled,Enabled,Mirrored"),p_preset==PRESET_3D?1:0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/filter"),p_preset==PRESET_2D_PIXEL?false:true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/mipmaps"),p_preset==PRESET_3D?true:false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/anisotropic"),false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/srgb",PROPERTY_HINT_ENUM,"Disable,Enable,Detect"),2)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/fix_alpha_border"),p_preset!=PRESET_3D?true:false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/premult_alpha"),true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"stream"),false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"size_limit",PROPERTY_HINT_RANGE,"0,4096,1"),0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"detect_3d"),p_preset==PRESET_DETECT)); + +} + + +void ResourceImporterTexture::_save_stex(const Image& p_image,const String& p_to_path,int p_compress_mode,float p_lossy_quality,Image::CompressMode p_vram_compression,bool p_mipmaps,int p_texture_flags,bool p_streamable) { + + + FileAccess *f = FileAccess::open(p_to_path,FileAccess::WRITE); + f->store_8('G'); + f->store_8('D'); + f->store_8('S'); + f->store_8('T'); //godot streamable texture + + f->store_32(p_image.get_width()); + f->store_32(p_image.get_height()); + f->store_32(p_texture_flags); + + uint32_t format=0; + + if (p_streamable) + format|=StreamTexture::FORMAT_BIT_STREAM; + if (p_mipmaps || p_compress_mode==COMPRESS_VIDEO_RAM) //VRAM always uses mipmaps + format|=StreamTexture::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit + + switch (p_compress_mode) { + case COMPRESS_LOSSLESS: { + + Image image = p_image; + if (p_mipmaps) { + image.generate_mipmaps(); + } else { + image.clear_mipmaps(); + } + + int mmc = image.get_mipmap_count() + 1; + + format=StreamTexture::FORMAT_BIT_LOSSLESS; + f->store_32(format); + f->store_32(mmc); + + for(int i=0;i<mmc;i++) { + + if (i>0) { + image.shrink_x2(); + } + + PoolVector<uint8_t> data = Image::lossless_packer(image); + int data_len = data.size(); + f->store_32(data_len); + + PoolVector<uint8_t>::Read r= data.read(); + f->store_buffer(r.ptr(),data_len); + + } + + + } break; + case COMPRESS_LOSSY: { + Image image = p_image; + if (p_mipmaps) { + image.generate_mipmaps(); + } else { + image.clear_mipmaps(); + } + + int mmc = image.get_mipmap_count() + 1; + + format=StreamTexture::FORMAT_BIT_LOSSY; + f->store_32(format); + f->store_32(mmc); + + for(int i=0;i<mmc;i++) { + + if (i>0) { + image.shrink_x2(); + } + + PoolVector<uint8_t> data = Image::lossy_packer(image,p_lossy_quality); + int data_len = data.size(); + f->store_32(data_len); + + PoolVector<uint8_t>::Read r = data.read(); + f->store_buffer(r.ptr(),data_len); + + } + } break; + case COMPRESS_VIDEO_RAM: { + + Image image = p_image; + image.generate_mipmaps(); + image.compress(p_vram_compression); + + format |= image.get_format(); + + f->store_32(format); + + PoolVector<uint8_t> data=image.get_data(); + int dl = data.size(); + PoolVector<uint8_t>::Read r = data.read(); + + f->store_buffer(r.ptr(),dl); + + } break; + case COMPRESS_UNCOMPRESSED: { + + Image image = p_image; + if (p_mipmaps) { + image.generate_mipmaps(); + } else { + image.clear_mipmaps(); + } + + format |= image.get_format(); + f->store_32(format); + + PoolVector<uint8_t> data=image.get_data(); + int dl = data.size(); + PoolVector<uint8_t>::Read r = data.read(); + + f->store_buffer(r.ptr(),dl); + + } break; + } + + memdelete(f); +} + +Error ResourceImporterTexture::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) { + + int compress_mode = p_options["compress/mode"]; + float lossy= p_options["compress/lossy_quality"]; + int repeat= p_options["flags/repeat"]; + bool filter= p_options["flags/filter"]; + bool mipmaps= p_options["flags/mipmaps"]; + bool anisotropic= p_options["flags/anisotropic"]; + bool srgb= p_options["flags/srgb"]; + bool fix_alpha_border= p_options["process/fix_alpha_border"]; + bool premult_alpha= p_options["process/premult_alpha"]; + bool stream = p_options["stream"]; + int size_limit = p_options["size_limit"]; + + + Image image; + Error err = ImageLoader::load_image(p_source_file,&image); + if (err!=OK) + return err; + + + int tex_flags=0; + if (repeat>0) + tex_flags|=Texture::FLAG_REPEAT; + if (repeat==2) + tex_flags|=Texture::FLAG_MIRRORED_REPEAT; + if (filter) + tex_flags|=Texture::FLAG_FILTER; + if (mipmaps || compress_mode==COMPRESS_VIDEO_RAM) + tex_flags|=Texture::FLAG_MIPMAPS; + if (anisotropic) + tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER; + if (srgb) + tex_flags|=Texture::FLAG_CONVERT_TO_LINEAR; + + if (size_limit >0 && (image.get_width()>size_limit || image.get_height()>size_limit )) { + //limit size + if (image.get_width() >= image.get_height()) { + int new_width = size_limit; + int new_height = image.get_height() * new_width / image.get_width(); + + image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC); + } else { + + int new_height = size_limit; + int new_width = image.get_width() * new_height / image.get_height(); + + image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC); + } + } + + if (fix_alpha_border) { + image.fix_alpha_edges(); + } + + if (premult_alpha) { + image.premultiply_alpha(); + } + + + if (compress_mode==COMPRESS_VIDEO_RAM) { + //must import in all formats + //Android, GLES 2.x + _save_stex(image,p_save_path+".etc.stex",compress_mode,lossy,Image::COMPRESS_ETC,mipmaps,tex_flags,stream); + r_platform_variants->push_back("etc"); + //_save_stex(image,p_save_path+".etc2.stex",compress_mode,lossy,Image::COMPRESS_ETC2,mipmaps,tex_flags,stream); + //r_platform_variants->push_back("etc2"); + _save_stex(image,p_save_path+".s3tc.stex",compress_mode,lossy,Image::COMPRESS_S3TC,mipmaps,tex_flags,stream); + r_platform_variants->push_back("s3tc"); + + } else { + //import normally + _save_stex(image,p_save_path+".stex",compress_mode,lossy,Image::COMPRESS_16BIT /*this is ignored */,mipmaps,tex_flags,stream); + } + + return OK; +} + +ResourceImporterTexture::ResourceImporterTexture() +{ + +} diff --git a/tools/editor/import/resource_import_texture.h b/tools/editor/import/resource_import_texture.h new file mode 100644 index 0000000000..84f7b77838 --- /dev/null +++ b/tools/editor/import/resource_import_texture.h @@ -0,0 +1,43 @@ +#ifndef RESOURCEIMPORTTEXTURE_H +#define RESOURCEIMPORTTEXTURE_H + +#include "io/resource_import.h" + +class ResourceImporterTexture : public ResourceImporter { + GDCLASS(ResourceImporterTexture,ResourceImporter) +public: + virtual String get_importer_name() const; + virtual String get_visible_name() const; + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual String get_save_extension() const; + virtual String get_resource_type() const; + + + enum Preset { + PRESET_DETECT, + PRESET_2D, + PRESET_2D_PIXEL, + PRESET_3D, + }; + + enum CompressMode { + COMPRESS_LOSSLESS, + COMPRESS_LOSSY, + COMPRESS_VIDEO_RAM, + COMPRESS_UNCOMPRESSED + }; + + virtual int get_preset_count() const; + virtual String get_preset_name(int p_idx) const; + + virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const; + virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const; + + void _save_stex(const Image& p_image, const String& p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable); + + virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL); + + ResourceImporterTexture(); +}; + +#endif // RESOURCEIMPORTTEXTURE_H diff --git a/tools/editor/import/resource_importer_csv_translation.cpp b/tools/editor/import/resource_importer_csv_translation.cpp new file mode 100644 index 0000000000..f14c10fb99 --- /dev/null +++ b/tools/editor/import/resource_importer_csv_translation.cpp @@ -0,0 +1,126 @@ + +#include "resource_importer_csv_translation.h" +#include "os/file_access.h" +#include "translation.h" +#include "io/resource_saver.h" +#include "compressed_translation.h" + +String ResourceImporterCSVTranslation::get_importer_name() const { + + return "csv_translation"; +} + +String ResourceImporterCSVTranslation::get_visible_name() const{ + + return "CSV Translation"; +} +void ResourceImporterCSVTranslation::get_recognized_extensions(List<String> *p_extensions) const{ + + p_extensions->push_back("csv"); +} + +String ResourceImporterCSVTranslation::get_save_extension() const { + return ""; //does not save a single resoure +} + +String ResourceImporterCSVTranslation::get_resource_type() const{ + + return "StreamCSVTranslation"; +} + +bool ResourceImporterCSVTranslation::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const { + + return true; +} + +int ResourceImporterCSVTranslation::get_preset_count() const { + return 0; +} +String ResourceImporterCSVTranslation::get_preset_name(int p_idx) const { + + return ""; +} + + +void ResourceImporterCSVTranslation::get_import_options(List<ImportOption> *r_options,int p_preset) const { + + + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"compress"),true)); + +} + + + +Error ResourceImporterCSVTranslation::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) { + + + bool compress = p_options["compress"]; + FileAccessRef f = FileAccess::open(p_source_file,FileAccess::READ); + + ERR_FAIL_COND_V( !f, ERR_INVALID_PARAMETER ); + + Vector<String> line = f->get_csv_line(); + if (line.size()<=1) { + return ERR_PARSE_ERROR; + } + + Vector<String> locales; + Vector<Ref<Translation> > translations; + + for(int i=1;i<line.size();i++) { + + String locale = line[i]; + if (!TranslationServer::is_locale_valid(locale)) { + return ERR_PARSE_ERROR; + } + + locales.push_back(locale); + Ref<Translation> translation; + translation.instance(); + translation->set_locale(locale); + translations.push_back(translation); + } + + line = f->get_csv_line(); + + while(line.size()==locales.size()+1) { + + String key = line[0]; + if (key!="") { + + for(int i=1;i<line.size();i++) { + translations[i-1]->add_message(key,line[i]); + } + } + + line = f->get_csv_line(); + } + + + for(int i=0;i<translations.size();i++) { + Ref<Translation> xlt = translations[i]; + + if (compress) { + Ref<PHashTranslation> cxl = memnew( PHashTranslation ); + cxl->generate( xlt ); + xlt=cxl; + } + + String save_path = p_source_file.get_basename()+"."+translations[i]->get_locale()+".xl"; + + ResourceSaver::save(save_path,xlt); + if (r_gen_files) { + r_gen_files->push_back(save_path); + } + } + + + + return OK; + +} + +ResourceImporterCSVTranslation::ResourceImporterCSVTranslation() +{ + +} diff --git a/tools/editor/import/resource_importer_csv_translation.h b/tools/editor/import/resource_importer_csv_translation.h new file mode 100644 index 0000000000..d08218e7d9 --- /dev/null +++ b/tools/editor/import/resource_importer_csv_translation.h @@ -0,0 +1,27 @@ +#ifndef RESOURCEIMPORTERCSVTRANSLATION_H +#define RESOURCEIMPORTERCSVTRANSLATION_H + +#include "io/resource_import.h" + + +class ResourceImporterCSVTranslation : public ResourceImporter { + GDCLASS(ResourceImporterCSVTranslation,ResourceImporter) +public: + virtual String get_importer_name() const; + virtual String get_visible_name() const; + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual String get_save_extension() const; + virtual String get_resource_type() const; + + virtual int get_preset_count() const; + virtual String get_preset_name(int p_idx) const; + + virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const; + virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const; + + virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL); + + ResourceImporterCSVTranslation(); +}; + +#endif // RESOURCEIMPORTERCSVTRANSLATION_H diff --git a/tools/editor/import_dock.cpp b/tools/editor/import_dock.cpp new file mode 100644 index 0000000000..b1bd698239 --- /dev/null +++ b/tools/editor/import_dock.cpp @@ -0,0 +1,331 @@ +#include "import_dock.h" + +class ImportDockParameters : public Object { + GDCLASS(ImportDockParameters,Object) +public: + Map<StringName,Variant> values; + List<PropertyInfo> properties; + Ref<ResourceImporter> importer; + Vector<String> paths; + + + bool _set(const StringName& p_name, const Variant& p_value) { + + if (values.has(p_name)) { + values[p_name]=p_value; + return true; + } + + return false; + } + + bool _get(const StringName& p_name,Variant &r_ret) const { + + if (values.has(p_name)) { + r_ret=values[p_name]; + return true; + } + + return false; + + } + void _get_property_list( List<PropertyInfo> *p_list) const { + + for (const List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) { + if (!importer->get_option_visibility(E->get().name,values)) + continue; + p_list->push_back(E->get()); + } + } + + void update() { + _change_notify(); + } +}; + +void ImportDock::set_edit_path(const String& p_path) { + + Ref<ConfigFile> config; + config.instance(); + Error err = config->load(p_path+".import"); + if (err!=OK) { + clear(); + return; + } + + + params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(config->get_value("remap","importer")); + if (params->importer.is_null()) { + clear(); + return; + } + + List<ResourceImporter::ImportOption> options; + params->importer->get_import_options(&options); + + params->properties.clear(); + params->values.clear(); + + for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) { + + params->properties.push_back(E->get().option); + if (config->has_section_key("params",E->get().option.name)) { + params->values[E->get().option.name]=config->get_value("params",E->get().option.name); + } else { + params->values[E->get().option.name]=E->get().default_value; + } + } + + params->update(); + + List<Ref<ResourceImporter> > importers; + ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_path.get_extension(),&importers); + List<Pair<String,String> > importer_names; + + for (List<Ref<ResourceImporter> > ::Element *E=importers.front();E;E=E->next()) { + importer_names.push_back(Pair<String,String>(E->get()->get_visible_name(),E->get()->get_importer_name())); + } + + importer_names.sort_custom<PairSort<String,String> >(); + + import_as->clear(); + + for (List<Pair<String,String> >::Element *E=importer_names.front();E;E=E->next()) { + import_as->add_item(E->get().first); + import_as->set_item_metadata(import_as->get_item_count()-1,E->get().second); + if (E->get().second==params->importer->get_importer_name()) { + import_as->select(import_as->get_item_count()-1); + } + } + + preset->get_popup()->clear(); + + if (params->importer->get_preset_count()==0) { + preset->get_popup()->add_item(TTR("Default")); + } else { + for (int i=0;i<params->importer->get_preset_count();i++) { + preset->get_popup()->add_item(params->importer->get_preset_name(i)); + } + } + + params->paths.clear(); + params->paths.push_back(p_path); + import->set_disabled(false); + import_as->set_disabled(false); + + imported->set_text(p_path.get_file()); +} + +void ImportDock::set_edit_multiple_paths(const Vector<String>& p_paths) { + + clear(); + + //use the value that is repeated the mot + Map<String,Dictionary> value_frequency; + + for(int i=0;i<p_paths.size();i++) { + + Ref<ConfigFile> config; + config.instance(); + Error err = config->load(p_paths[i]+".import"); + ERR_CONTINUE(err!=OK); + + if (i==0) { + params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(config->get_value("remap","importer")); + if (params->importer.is_null()) { + clear(); + return; + } + } + + List<String> keys; + config->get_section_keys("params",&keys); + + + for (List<String>::Element *E=keys.front();E;E=E->next()) { + + if (!value_frequency.has(E->get())) { + value_frequency[E->get()]=Dictionary(); + } + + Variant value = config->get_value("params",E->get()); + + if (value_frequency[E->get()].has(value)) { + value_frequency[E->get()][value]=int(value_frequency[E->get()][value])+1; + } else { + value_frequency[E->get()][value]=1; + } + } + + } + + ERR_FAIL_COND(params->importer.is_null()); + + List<ResourceImporter::ImportOption> options; + params->importer->get_import_options(&options); + + params->properties.clear(); + params->values.clear(); + + for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) { + + params->properties.push_back(E->get().option); + + if (value_frequency.has(E->get().option.name)) { + + Dictionary d = value_frequency[E->get().option.name]; + int freq=0; + List<Variant> v; + d.get_key_list(&v); + Variant value; + for (List<Variant>::Element *F=v.front();F;F=F->next()) { + int f = d[F->get()]; + if (f>freq) { + value=F->get(); + } + } + + params->values[E->get().option.name]=value; + } else { + params->values[E->get().option.name]=E->get().default_value; + } + } + + params->update(); + + List<Ref<ResourceImporter> > importers; + ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_paths[0].get_extension(),&importers); + List<Pair<String,String> > importer_names; + + for (List<Ref<ResourceImporter> > ::Element *E=importers.front();E;E=E->next()) { + importer_names.push_back(Pair<String,String>(E->get()->get_visible_name(),E->get()->get_importer_name())); + } + + importer_names.sort_custom<PairSort<String,String> >(); + + import_as->clear(); + + for (List<Pair<String,String> >::Element *E=importer_names.front();E;E=E->next()) { + import_as->add_item(E->get().first); + import_as->set_item_metadata(import_as->get_item_count()-1,E->get().second); + if (E->get().second==params->importer->get_importer_name()) { + import_as->select(import_as->get_item_count()-1); + } + } + + preset->get_popup()->clear(); + + if (params->importer->get_preset_count()==0) { + preset->get_popup()->add_item(TTR("Default")); + } else { + for (int i=0;i<params->importer->get_preset_count();i++) { + preset->get_popup()->add_item(params->importer->get_preset_name(i)); + } + } + + params->paths=p_paths; + import->set_disabled(false); + import_as->set_disabled(false); + + imported->set_text(itos(p_paths.size())+TTR(" Files")); +} + +void ImportDock::_preset_selected(int p_idx) { + + print_line("preset selected? "+p_idx); + List<ResourceImporter::ImportOption> options; + + params->importer->get_import_options(&options,p_idx); + + for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) { + + params->values[E->get().option.name]=E->get().default_value; + } + + params->update(); + +} + + +void ImportDock::clear() { + + imported->set_text(""); + import->set_disabled(true); + import_as->clear(); + import_as->set_disabled(true); + params->values.clear(); + params->properties.clear(); + params->update(); + preset->get_popup()->clear(); + +} + +void ImportDock::_reimport() { + + for(int i=0;i<params->paths.size();i++) { + + Ref<ConfigFile> config; + config.instance(); + Error err = config->load(params->paths[i]+".import"); + ERR_CONTINUE(err!=OK); + + config->erase_section("params"); + + for (List<PropertyInfo>::Element *E=params->properties.front();E;E=E->next()) { + config->set_value("params",E->get().name,params->values[E->get().name]); + } + + config->save(params->paths[i]+".import"); + } + + EditorFileSystem::get_singleton()->reimport_files(params->paths); + EditorFileSystem::get_singleton()->emit_signal("filesystem_changed"); //it changed, so force emitting the signal + +} + +void ImportDock::_bind_methods() { + + ClassDB::bind_method(_MD("_reimport"),&ImportDock::_reimport); + ClassDB::bind_method(_MD("_preset_selected"),&ImportDock::_preset_selected); +} + +ImportDock::ImportDock() { + + + imported = memnew( LineEdit ); + imported->set_editable(false); + add_child(imported); + HBoxContainer *hb = memnew(HBoxContainer); + add_margin_child(TTR("Import As:"),hb); + import_as = memnew( OptionButton ); + hb->add_child(import_as); + import_as->set_h_size_flags(SIZE_EXPAND_FILL); + preset = memnew( MenuButton ); + preset->set_text(TTR("Preset..")); + preset->get_popup()->connect("index_pressed",this,"_preset_selected"); + hb->add_child(preset); + + import_opts = memnew( PropertyEditor ); + add_child(import_opts); + import_opts->set_v_size_flags(SIZE_EXPAND_FILL); + import_opts->hide_top_label(); + import_opts->set_hide_script(true); + + hb = memnew( HBoxContainer ); + add_child(hb); + import = memnew( Button ); + import->set_text(TTR("Reimport")); + import->connect("pressed",this,"_reimport"); + hb->add_spacer(); + hb->add_child(import); + hb->add_spacer(); + + params = memnew( ImportDockParameters ); + import_opts->edit(params); + +} + +ImportDock::~ImportDock() { + + memdelete(params); +} diff --git a/tools/editor/import_dock.h b/tools/editor/import_dock.h new file mode 100644 index 0000000000..bddf5480b8 --- /dev/null +++ b/tools/editor/import_dock.h @@ -0,0 +1,42 @@ +#ifndef IMPORTDOCK_H +#define IMPORTDOCK_H + +#include "io/resource_import.h" +#include "editor_file_system.h" +#include "scene/gui/box_container.h" +#include "scene/gui/option_button.h" +#include "scene/gui/popup_menu.h" +#include "property_editor.h" + +class ImportDockParameters; +class ImportDock : public VBoxContainer { + GDCLASS(ImportDock,VBoxContainer) + + LineEdit *imported; + OptionButton *import_as; + MenuButton *preset; + PropertyEditor *import_opts; + + List<PropertyInfo> properties; + Map<StringName,Variant> property_values; + + Button *import; + + ImportDockParameters *params; + + void _preset_selected(int p_idx); + + void _reimport(); +protected: + static void _bind_methods(); +public: + + void set_edit_path(const String& p_path); + void set_edit_multiple_paths(const Vector<String>& p_paths); + void clear(); + + ImportDock(); + ~ImportDock(); +}; + +#endif // IMPORTDOCK_H diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.h b/tools/editor/io_plugins/editor_texture_import_plugin.h index 08e0db5d6e..ce15df0f18 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.h +++ b/tools/editor/io_plugins/editor_texture_import_plugin.h @@ -29,6 +29,11 @@ #ifndef EDITOR_TEXTURE_IMPORT_PLUGIN_H #define EDITOR_TEXTURE_IMPORT_PLUGIN_H + + + + + #if 0 #include "tools/editor/editor_import_export.h" #include "scene/gui/dialogs.h" diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp index b3d16bb660..f10526fb77 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.cpp +++ b/tools/editor/plugins/animation_player_editor_plugin.cpp @@ -448,22 +448,27 @@ void AnimationPlayerEditor::_animation_save_as(const Ref<Resource>& p_resource) file->set_title(TTR("Save Resource As..")); current_option = RESOURCE_SAVE; } + void AnimationPlayerEditor::_animation_remove() { - if (animation->get_item_count()==0) + if (animation->get_item_count() == 0) return; - String current = animation->get_item_text(animation->get_selected()); - Ref<Animation> anim = player->get_animation(current); + delete_dialog->set_text(TTR("Delete Animation?")); + delete_dialog->popup_centered_minsize(); +} + +void AnimationPlayerEditor::_animation_remove_confirmed() { + String current = animation->get_item_text(animation->get_selected()); + Ref<Animation> anim = player->get_animation(current); undo_redo->create_action(TTR("Remove Animation")); - undo_redo->add_do_method(player,"remove_animation",current); - undo_redo->add_undo_method(player,"add_animation",current,anim); - undo_redo->add_do_method(this,"_animation_player_changed",player); - undo_redo->add_undo_method(this,"_animation_player_changed",player); + undo_redo->add_do_method(player, "remove_animation", current); + undo_redo->add_undo_method(player, "add_animation", current, anim); + undo_redo->add_do_method(this, "_animation_player_changed", player); + undo_redo->add_undo_method(this, "_animation_player_changed", player); undo_redo->commit_action(); - } void AnimationPlayerEditor::_select_anim_by_name(const String& p_anim) { @@ -1268,6 +1273,7 @@ void AnimationPlayerEditor::_bind_methods() { ClassDB::bind_method(_MD("_animation_rename"),&AnimationPlayerEditor::_animation_rename); ClassDB::bind_method(_MD("_animation_load"),&AnimationPlayerEditor::_animation_load); ClassDB::bind_method(_MD("_animation_remove"),&AnimationPlayerEditor::_animation_remove); + ClassDB::bind_method(_MD("_animation_remove_confirmed"),&AnimationPlayerEditor::_animation_remove_confirmed); ClassDB::bind_method(_MD("_animation_blend"),&AnimationPlayerEditor::_animation_blend); ClassDB::bind_method(_MD("_animation_edit"),&AnimationPlayerEditor::_animation_edit); ClassDB::bind_method(_MD("_animation_resource_edit"),&AnimationPlayerEditor::_animation_resource_edit); @@ -1392,6 +1398,10 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { add_child(accept); accept->connect("confirmed", this, "_menu_confirm_current"); + delete_dialog = memnew(ConfirmationDialog); + add_child(delete_dialog); + delete_dialog->connect("confirmed", this, "_animation_remove_confirmed"); + duplicate_anim = memnew( ToolButton ); hb->add_child(duplicate_anim); ED_SHORTCUT("animation_player_editor/duplicate_animation", TTR("Duplicate Animation")); @@ -1405,7 +1415,6 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { rename_anim->set_tooltip(TTR("Rename Animation")); remove_anim = memnew( ToolButton ); - hb->add_child(remove_anim); ED_SHORTCUT("animation_player_editor/remove_animation", TTR("Remove Animation")); remove_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/remove_animation")); diff --git a/tools/editor/plugins/animation_player_editor_plugin.h b/tools/editor/plugins/animation_player_editor_plugin.h index 840c39ba49..e28600a7ab 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.h +++ b/tools/editor/plugins/animation_player_editor_plugin.h @@ -97,6 +97,7 @@ class AnimationPlayerEditor : public VBoxContainer { EditorFileDialog *file; AcceptDialog *accept; + ConfirmationDialog* delete_dialog; int current_option; struct BlendEditor { @@ -138,6 +139,7 @@ class AnimationPlayerEditor : public VBoxContainer { void _animation_save_as(const Ref<Resource>& p_resource); void _animation_remove(); + void _animation_remove_confirmed(); void _animation_blend(); void _animation_edit(); void _animation_duplicate(); diff --git a/tools/editor/plugins/script_text_editor.cpp b/tools/editor/plugins/script_text_editor.cpp index e26a3b23bc..9ec6266419 100644 --- a/tools/editor/plugins/script_text_editor.cpp +++ b/tools/editor/plugins/script_text_editor.cpp @@ -115,6 +115,7 @@ void ScriptTextEditor::_load_theme_settings() { text_edit->add_color_override("selection_color",EDITOR_DEF("text_editor/highlighting/selection_color",Color(0.2,0.2,1))); text_edit->add_color_override("brace_mismatch_color",EDITOR_DEF("text_editor/highlighting/brace_mismatch_color",Color(1,0.2,0.2))); text_edit->add_color_override("current_line_color",EDITOR_DEF("text_editor/highlighting/current_line_color",Color(0.3,0.5,0.8,0.15))); + text_edit->add_color_override("line_length_guideline_color", EDITOR_DEF("text_editor/highlighting/line_length_guideline_color", Color(0,0,0))); text_edit->add_color_override("word_highlighted_color",EDITOR_DEF("text_editor/highlighting/word_highlighted_color",Color(0.8,0.9,0.9,0.15))); text_edit->add_color_override("number_color",EDITOR_DEF("text_editor/highlighting/number_color",Color(0.9,0.6,0.0,2))); text_edit->add_color_override("function_color",EDITOR_DEF("text_editor/highlighting/function_color",Color(0.4,0.6,0.8))); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 19720dfd65..8e3791eb8d 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -118,7 +118,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { Set<String> valid_extensions; for (List<String>::Element *E=extensions.front();E;E=E->next()) { - + print_line("found: "+E->get()); valid_extensions.insert(E->get()); } @@ -3140,6 +3140,10 @@ void PropertyEditor::update_tree() { } else if ( ! (p.usage&PROPERTY_USAGE_EDITOR ) ) continue; + + if (hide_script && p.name=="script/script") + continue; + String basename=p.name; if (group!="") { if (group_base!="") { @@ -3886,7 +3890,7 @@ void PropertyEditor::_item_selected() { } -void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) { +void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value, bool p_refresh_all) { if (autoclear) { TreeItem *item = tree->get_selected(); @@ -3899,7 +3903,11 @@ void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) { if (!undo_redo || obj->cast_to<MultiNodeEdit>() || obj->cast_to<ArrayPropertyEdit>()) { //kind of hacky obj->set(p_name,p_value); - _changed_callbacks(obj,p_name); + if (p_refresh_all) + _changed_callbacks(obj,""); + else + _changed_callbacks(obj,p_name); + emit_signal(_prop_edited,p_name); @@ -3909,9 +3917,14 @@ void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) { undo_redo->add_do_property(obj,p_name,p_value); undo_redo->add_undo_property(obj,p_name,obj->get(p_name)); + if (p_refresh_all) { + undo_redo->add_do_method(this,"_changed_callback",obj,""); + undo_redo->add_undo_method(this,"_changed_callback",obj,""); + } else { - undo_redo->add_do_method(this,"_changed_callback",obj,p_name); - undo_redo->add_undo_method(this,"_changed_callback",obj,p_name); + undo_redo->add_do_method(this,"_changed_callback",obj,p_name); + undo_redo->add_undo_method(this,"_changed_callback",obj,p_name); + } Resource *r = obj->cast_to<Resource>(); if (r) { @@ -3973,6 +3986,9 @@ void PropertyEditor::_item_edited() { int type=d["type"]; int hint= d["hint"]; + int usage = d["usage"]; + bool refresh_all = usage&PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED; + String hint_text=d["hint_text"]; switch(type) { @@ -3981,7 +3997,7 @@ void PropertyEditor::_item_edited() { } break; case Variant::BOOL: { - _edit_set(name,item->is_checked(1)); + _edit_set(name,item->is_checked(1),refresh_all); item->set_tooltip(1, item->is_checked(1) ? "True" : "False"); } break; case Variant::INT: @@ -3995,9 +4011,9 @@ void PropertyEditor::_item_edited() { break; if (type==Variant::INT) - _edit_set(name,int(item->get_range(1))); + _edit_set(name,int(item->get_range(1)),refresh_all); else - _edit_set(name,item->get_range(1)); + _edit_set(name,item->get_range(1),refresh_all); } break; case Variant::STRING: { @@ -4012,9 +4028,9 @@ void PropertyEditor::_item_edited() { txt=strings[idx]; } - _edit_set(name,txt); + _edit_set(name,txt,refresh_all); } else { - _edit_set(name,item->get_text(1)); + _edit_set(name,item->get_text(1),refresh_all); } } break; // math types @@ -4045,7 +4061,7 @@ void PropertyEditor::_item_edited() { } break; case Variant::NODE_PATH: { - _edit_set(name, NodePath(item->get_text(1))); + _edit_set(name, NodePath(item->get_text(1)),refresh_all); } break; @@ -4476,6 +4492,8 @@ PropertyEditor::PropertyEditor() { _prop_edited="property_edited"; + hide_script=false; + undo_redo=NULL; obj=NULL; search_box=NULL; diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index 3f8d071a01..969340d5a2 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -192,6 +192,7 @@ class PropertyEditor : public Control { bool use_doc_hints; bool use_filter; bool subsection_selectable; + bool hide_script; HashMap<String,String> pending; String selected_property; @@ -224,7 +225,7 @@ class PropertyEditor : public Control { void _node_removed(Node *p_node); friend class ProjectExportDialog; - void _edit_set(const String& p_name, const Variant& p_value); + void _edit_set(const String& p_name, const Variant& p_value,bool p_refresh_all=false); void _draw_flags(Object *ti,const Rect2& p_rect); bool _might_be_in_instance(); @@ -276,6 +277,7 @@ public: void set_show_categories(bool p_show); void set_use_doc_hints(bool p_enable) { use_doc_hints=p_enable; } + void set_hide_script(bool p_hide) { hide_script=p_hide; } void set_use_filter(bool p_use); void register_text_enter(Node *p_line_edit); diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index b3e4c8ed70..ea1de29d0f 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -768,6 +768,7 @@ Node *SceneTreeDock::_duplicate(Node *p_node, Map<Node*,Node*> &duplimap) { ERR_FAIL_COND_V(!sd.is_valid(),NULL); node = sd->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); ERR_FAIL_COND_V(!node,NULL); + node->set_scene_instance_load_placeholder(p_node->get_scene_instance_load_placeholder()); //node->generate_instance_state(); } else { Object *obj = ClassDB::instance(p_node->get_class()); @@ -1760,7 +1761,9 @@ void SceneTreeDock::_nodes_dragged(Array p_nodes,NodePath p_to,int p_type) { for(int i=0;i<p_nodes.size();i++) { Node *n=get_node((p_nodes[i])); - nodes.push_back(n); + if (n) { + nodes.push_back(n); + } } if (nodes.size()==0) |