Changed import workflow

-Rearrange favorites in fs dock with drag and drop
-Removed import -> sub-scene, moved to scenetree contextual menu
-Removed import -> re-import , moved and integrated to FS dock
-Added ability in FS dock to re-import more than one resource
simultaneously
-Added ability to drag from native filesystem explorer to Godot, only
works on Windows though
-Removed scene reimport merge options, never worked well. Eventually
merging materials should be re-added
-Added ability to set custom root node type when importing scenes
-Re-Import is now automatic, can be configured back to manual in editor
settings
-Added resource previews in property list for many resource types
This commit is contained in:
Juan Linietsky 2016-05-27 14:18:40 -03:00
parent eb7227a20b
commit 8be2fabbe5
54 changed files with 1258 additions and 636 deletions

View File

@ -243,6 +243,7 @@ Ref<ResourceImportMetadata> ResourceLoader::load_import_metadata(const String &p
break;
}
return ret;
}

View File

@ -1756,6 +1756,7 @@ bool Object::is_queued_for_deletion() const {
void Object::set_edited(bool p_edited) {
_edited=p_edited;
_edited_version++;
}
bool Object::is_edited() const {
@ -1763,6 +1764,11 @@ bool Object::is_edited() const {
return _edited;
}
uint32_t Object::get_edited_version() const {
return _edited_version;
}
#endif
Object::Object() {
@ -1778,6 +1784,7 @@ Object::Object() {
#ifdef TOOLS_ENABLED
_edited=false;
_edited_version=0;
#endif
#ifdef DEBUG_ENABLED

View File

@ -388,6 +388,7 @@ friend void postinitialize_handler(Object*);
bool _can_translate;
#ifdef TOOLS_ENABLED
bool _edited;
uint32_t _edited_version;
#endif
ScriptInstance *script_instance;
RefPtr script;
@ -589,6 +590,7 @@ public:
#ifdef TOOLS_ENABLED
void set_edited(bool p_edited);
bool is_edited() const;
uint32_t get_edited_version() const; //this function is used to check when something changed beyond a point, it's used mainly for generating previews
#endif
void set_script_instance(ScriptInstance *p_instance);

View File

@ -43,6 +43,7 @@ void MainLoop::_bind_methods() {
BIND_VMETHOD( MethodInfo("_initialize") );
BIND_VMETHOD( MethodInfo("_iteration",PropertyInfo(Variant::REAL,"delta")) );
BIND_VMETHOD( MethodInfo("_idle",PropertyInfo(Variant::REAL,"delta")) );
BIND_VMETHOD( MethodInfo("_drop_files",PropertyInfo(Variant::STRING_ARRAY,"files"),PropertyInfo(Variant::INT,"screen")) );
BIND_VMETHOD( MethodInfo("_finalize") );
BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER);
@ -108,6 +109,15 @@ bool MainLoop::idle(float p_time) {
return false;
}
void MainLoop::drop_files(const Vector<String>& p_files,int p_from_screen) {
if (get_script_instance())
get_script_instance()->call("_drop_files",p_files,p_from_screen);
}
void MainLoop::finish() {
if (get_script_instance()) {

View File

@ -64,6 +64,8 @@ public:
virtual bool idle(float p_time);
virtual void finish();
virtual void drop_files(const Vector<String>& p_files,int p_from_screen=0);
void set_init_script(const Ref<Script>& p_init_script);
MainLoop();

View File

@ -330,6 +330,31 @@ Ref<ResourceImportMetadata> Resource::get_import_metadata() const {
}
#ifdef TOOLS_ENABLED
uint32_t Resource::hash_edited_version() const {
uint32_t hash = hash_djb2_one_32(get_edited_version());
List<PropertyInfo> plist;
get_property_list(&plist);
for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
if (E->get().type==Variant::OBJECT && E->get().hint==PROPERTY_HINT_RESOURCE_TYPE) {
RES res = get(E->get().name);
if (res.is_valid()) {
hash = hash_djb2_one_32(res->hash_edited_version(),hash);
}
}
}
return hash;
}
#endif
Resource::Resource() {
@ -341,6 +366,8 @@ Resource::Resource() {
}
Resource::~Resource() {
if (path_cache!="")

View File

@ -142,8 +142,12 @@ public:
Ref<ResourceImportMetadata> get_import_metadata() const;
#ifdef TOOLS_ENABLED
uint32_t hash_edited_version() const;
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; }

View File

@ -4737,10 +4737,10 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
}
void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner) {
void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner,int p_material) {
Material *m=NULL;
RID m_src=p_instance->material_override.is_valid() ? p_instance->material_override : p_geometry->material;
RID m_src=p_instance->material_override.is_valid() ? p_instance->material_override :(p_material>=0?p_instance->materials[p_material]:p_geometry->material);
#ifdef DEBUG_ENABLED
if (current_debug==VS::SCENARIO_DEBUG_OVERDRAW) {
@ -4988,8 +4988,9 @@ void RasterizerGLES2::add_mesh( const RID& p_mesh, const InstanceData *p_data) {
for (int i=0;i<ssize;i++) {
int mat_idx = p_data->materials[i].is_valid() ? i : -1;
Surface *s = mesh->surfaces[i];
_add_geometry(s,p_data,s,NULL);
_add_geometry(s,p_data,s,NULL,mat_idx);
}
mesh->last_pass=frame;

View File

@ -1070,7 +1070,7 @@ class RasterizerGLES2 : public Rasterizer {
Plane camera_plane;
void _add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner);
void _add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner,int p_material=-1);
void _render_list_forward(RenderList *p_render_list,const Transform& p_view_transform,const Transform& p_view_transform_inverse, const CameraMatrix& p_projection,bool p_reverse_cull=false,bool p_fragment_light=false,bool p_alpha_pass=false);
//void _setup_light(LightInstance* p_instance, int p_idx);

View File

@ -724,6 +724,32 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
}
} break;
case WM_DROPFILES: {
HDROP hDropInfo = NULL;
hDropInfo = (HDROP) wParam;
const int buffsize=4096;
wchar_t buf[buffsize];
int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF,NULL,0);
Vector<String> files;
for(int i=0;i<fcount;i++) {
DragQueryFileW(hDropInfo, i, buf, buffsize);
String file=buf;
files.push_back(file);
}
if (files.size() && main_loop) {
main_loop->drop_files(files,0);
}
} break;
default: {
@ -1035,6 +1061,8 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
_ensure_data_dir();
DragAcceptFiles(hWnd,true);
}

View File

@ -31,8 +31,8 @@
#include "skeleton.h"
#include "physics_body.h"
#include "body_shape.h"
#include "scene/scene_string_names.h"
#include "core_string_names.h"
bool MeshInstance::_set(const StringName& p_name, const Variant& p_value) {
//this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else.
@ -43,15 +43,24 @@ bool MeshInstance::_set(const StringName& p_name, const Variant& p_value) {
Map<StringName,MorphTrack>::Element *E = morph_tracks.find(p_name);
if (!E)
return false;
if (E) {
E->get().value=p_value;
VisualServer::get_singleton()->instance_set_morph_target_weight(get_instance(),E->get().idx,E->get().value);
return true;
}
if (p_name.operator String().begins_with("material/")) {
int idx = p_name.operator String().get_slicec('/',1).to_int();
if (idx>=materials.size() || idx<0)
return false;
set_surface_material(idx,p_value);
return true;
}
return false;
}
bool MeshInstance::_get(const StringName& p_name,Variant &r_ret) const {
@ -59,14 +68,21 @@ bool MeshInstance::_get(const StringName& p_name,Variant &r_ret) const {
return false;
const Map<StringName,MorphTrack>::Element *E = morph_tracks.find(p_name);
if (!E)
return false;
if (E) {
r_ret = E->get().value;
return true;
}
if (p_name.operator String().begins_with("material/")) {
int idx = p_name.operator String().get_slicec('/',1).to_int();
if (idx>=materials.size() || idx<0)
return false;
r_ret=materials[idx];
return true;
}
return false;
}
void MeshInstance::_get_property_list( List<PropertyInfo> *p_list) const {
List<String> ls;
@ -80,6 +96,12 @@ void MeshInstance::_get_property_list( List<PropertyInfo> *p_list) const {
for(List<String>::Element *E=ls.front();E;E=E->next()) {
p_list->push_back( PropertyInfo(Variant::REAL,E->get(),PROPERTY_HINT_RANGE,"0,1,0.01"));
}
if (mesh.is_valid()) {
for(int i=0;i<mesh->get_surface_count();i++) {
p_list->push_back( PropertyInfo(Variant::OBJECT, "material/"+itos(i), PROPERTY_HINT_RESOURCE_TYPE, "Material"));
}
}
}
@ -87,6 +109,14 @@ void MeshInstance::_get_property_list( List<PropertyInfo> *p_list) const {
void MeshInstance::set_mesh(const Ref<Mesh>& p_mesh) {
if (mesh==p_mesh)
return;
if (mesh.is_valid()) {
mesh->disconnect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_mesh_changed);
materials.clear();
}
mesh=p_mesh;
morph_tracks.clear();
@ -100,13 +130,17 @@ void MeshInstance::set_mesh(const Ref<Mesh>& p_mesh) {
mt.value=0;
morph_tracks["morph/"+String(mesh->get_morph_target_name(i))]=mt;
}
mesh->connect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_mesh_changed);
materials.resize(mesh->get_surface_count());
set_base(mesh->get_rid());
} else {
set_base(RID());
}
_change_notify("mesh");
_change_notify();
}
Ref<Mesh> MeshInstance::get_mesh() const {
@ -232,6 +266,32 @@ void MeshInstance::_notification(int p_what) {
}
void MeshInstance::set_surface_material(int p_surface,const Ref<Material>& p_material) {
ERR_FAIL_INDEX(p_surface,materials.size());
materials[p_surface]=p_material;
if (materials[p_surface].is_valid())
VS::get_singleton()->instance_set_surface_material(get_instance(),p_surface,materials[p_surface]->get_rid());
else
VS::get_singleton()->instance_set_surface_material(get_instance(),p_surface,RID());
}
Ref<Material> MeshInstance::get_surface_material(int p_surface) const {
ERR_FAIL_INDEX_V(p_surface,materials.size(),Ref<Material>());
return materials[p_surface];
}
void MeshInstance::_mesh_changed() {
materials.resize( mesh->get_surface_count() );
}
void MeshInstance::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_mesh","mesh:Mesh"),&MeshInstance::set_mesh);
@ -243,6 +303,7 @@ void MeshInstance::_bind_methods() {
ObjectTypeDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT);
ObjectTypeDB::bind_method(_MD("create_convex_collision"),&MeshInstance::create_convex_collision);
ObjectTypeDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT);
ObjectTypeDB::bind_method(_MD("_mesh_changed"),&MeshInstance::_mesh_changed);
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "mesh/mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh" ), _SCS("set_mesh"), _SCS("get_mesh"));
ADD_PROPERTY( PropertyInfo (Variant::NODE_PATH, "mesh/skeleton"), _SCS("set_skeleton_path"), _SCS("get_skeleton_path"));
}

View File

@ -50,7 +50,9 @@ class MeshInstance : public GeometryInstance {
};
Map<StringName,MorphTrack> morph_tracks;
Vector<Ref<Material> > materials;
void _mesh_changed();
void _resolve_skeleton_path();
protected:
@ -69,6 +71,9 @@ public:
void set_skeleton_path(const NodePath& p_skeleton);
NodePath get_skeleton_path();
void set_surface_material(int p_surface,const Ref<Material>& p_material);
Ref<Material> get_surface_material(int p_surface) const;
Node* create_trimesh_collision_node();
void create_trimesh_collision();

View File

@ -1593,6 +1593,14 @@ void SceneTree::_live_edit_reparent_node_func(const NodePath& p_at,const NodePat
#endif
void SceneTree::drop_files(const Vector<String>& p_files,int p_from_screen) {
emit_signal("files_dropped",p_files,p_from_screen);
MainLoop::drop_files(p_files,p_from_screen);
}
void SceneTree::_bind_methods() {
@ -1666,6 +1674,8 @@ void SceneTree::_bind_methods() {
ADD_SIGNAL( MethodInfo("idle_frame"));
ADD_SIGNAL( MethodInfo("fixed_frame"));
ADD_SIGNAL( MethodInfo("files_dropped",PropertyInfo(Variant::STRING_ARRAY,"files"),PropertyInfo(Variant::INT,"screen")) );
BIND_CONSTANT( GROUP_CALL_DEFAULT );
BIND_CONSTANT( GROUP_CALL_REVERSE );
BIND_CONSTANT( GROUP_CALL_REALTIME );

View File

@ -344,6 +344,7 @@ public:
static SceneTree* get_singleton() { return singleton; }
void drop_files(const Vector<String>& p_files,int p_from_screen=0);
SceneTree();
~SceneTree();

View File

@ -30,7 +30,6 @@
#include "scene/resources/concave_polygon_shape.h"
#include "scene/resources/convex_polygon_shape.h"
#include "surface_tool.h"
static const char*_array_name[]={
"vertex_array",
"normal_array",
@ -288,6 +287,7 @@ void Mesh::add_surface(PrimitiveType p_primitive,const Array& p_arrays,const Arr
triangle_mesh=Ref<TriangleMesh>();
_change_notify();
emit_changed();
}
@ -387,6 +387,7 @@ void Mesh::surface_remove(int p_idx) {
triangle_mesh=Ref<TriangleMesh>();
_recompute_aabb();
_change_notify();
emit_changed();
}
@ -491,6 +492,8 @@ void Mesh::add_surface_from_mesh_data(const Geometry::MeshData& p_mesh_data) {
surfaces.push_back(s);
_change_notify();
emit_changed();
}
RID Mesh::get_rid() const {

View File

@ -176,4 +176,11 @@ SceneStringNames::SceneStringNames() {
path_pp=NodePath("..");
_default=StaticCString::create("default");
for(int i=0;i<MAX_MATERIALS;i++) {
mesh_materials[i]="material/"+itos(i);
}
_mesh_changed=StaticCString::create("_mesh_changed");
}

View File

@ -186,6 +186,12 @@ public:
StringName node_configuration_warning_changed;
enum {
MAX_MATERIALS=32
};
StringName mesh_materials[MAX_MATERIALS];
StringName _mesh_changed;
};

View File

@ -542,6 +542,7 @@ public:
RID skeleton;
RID material_override;
RID sampled_light;
Vector<RID> materials;
Vector<RID> light_instances;
Vector<float> morph_values;
BakedLightData *baked_light;

View File

@ -398,7 +398,7 @@ void VisualServerRaster::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat
void VisualServerRaster::mesh_add_surface(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,bool p_alpha_sort) {
VS_CHANGED;
_dependency_queue_update(p_mesh,true);
_dependency_queue_update(p_mesh,true,true);
rasterizer->mesh_add_surface(p_mesh,p_primitive,p_arrays,p_blend_shapes,p_alpha_sort);
}
@ -452,6 +452,7 @@ VisualServer::PrimitiveType VisualServerRaster::mesh_surface_get_primitive_type(
void VisualServerRaster::mesh_remove_surface(RID p_mesh,int p_surface){
rasterizer->mesh_remove_surface(p_mesh,p_surface);
_dependency_queue_update(p_mesh,true,true);
}
int VisualServerRaster::mesh_get_surface_count(RID p_mesh) const{
@ -480,6 +481,8 @@ void VisualServerRaster::mesh_clear(RID p_mesh) {
while(rasterizer->mesh_get_surface_count(p_mesh)) {
rasterizer->mesh_remove_surface(p_mesh,0);
}
_dependency_queue_update(p_mesh,true,true);
}
@ -2038,7 +2041,7 @@ Variant VisualServerRaster::environment_fx_get_param(RID p_env,EnvironmentFxPara
/* SCENARIO API */
void VisualServerRaster::_dependency_queue_update(RID p_rid,bool p_update_aabb) {
void VisualServerRaster::_dependency_queue_update(RID p_rid,bool p_update_aabb,bool p_update_materials) {
Map< RID, Set<RID> >::Element * E = instance_dependency_map.find( p_rid );
@ -2051,17 +2054,19 @@ void VisualServerRaster::_dependency_queue_update(RID p_rid,bool p_update_aabb)
while(I) {
Instance *ins = instance_owner.get( I->get() );
_instance_queue_update( ins , p_update_aabb );
_instance_queue_update( ins , p_update_aabb, p_update_materials );
I = I->next();
}
}
void VisualServerRaster::_instance_queue_update(Instance *p_instance,bool p_update_aabb) {
void VisualServerRaster::_instance_queue_update(Instance *p_instance,bool p_update_aabb,bool p_update_materials) {
if (p_update_aabb)
p_instance->update_aabb=true;
if (p_update_materials)
p_instance->update_materials=true;
if (p_instance->update)
return;
@ -2273,6 +2278,7 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) {
}
instance->data.morph_values.clear();
instance->data.materials.clear();
}
@ -2286,6 +2292,7 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) {
if (rasterizer->is_mesh(p_base)) {
instance->base_type=INSTANCE_MESH;
instance->data.morph_values.resize( rasterizer->mesh_get_morph_target_count(p_base));
instance->data.materials.resize( rasterizer->mesh_get_surface_count(p_base));
} else if (rasterizer->is_multimesh(p_base)) {
instance->base_type=INSTANCE_MULTIMESH;
} else if (rasterizer->is_immediate(p_base)) {
@ -2510,6 +2517,16 @@ float VisualServerRaster::instance_get_morph_target_weight(RID p_instance,int p_
return instance->data.morph_values[p_shape];
}
void VisualServerRaster::instance_set_surface_material(RID p_instance,int p_surface, RID p_material) {
VS_CHANGED;
Instance *instance = instance_owner.get( p_instance );
ERR_FAIL_COND( !instance);
ERR_FAIL_INDEX( p_surface, instance->data.materials.size() );
instance->data.materials[p_surface]=p_material;
}
void VisualServerRaster::instance_set_transform(RID p_instance, const Transform& p_transform) {
VS_CHANGED;
Instance *instance = instance_owner.get( p_instance );
@ -3046,6 +3063,7 @@ void VisualServerRaster::_update_instance(Instance *p_instance) {
}
if (p_instance->aabb.has_no_surface())
return;
@ -3301,10 +3319,17 @@ void VisualServerRaster::_update_instances() {
if (instance->update_aabb)
_update_instance_aabb(instance);
if (instance->update_materials) {
if (instance->base_type==INSTANCE_MESH) {
instance->data.materials.resize(rasterizer->mesh_get_surface_count(instance->base_rid));
}
}
_update_instance(instance);
instance->update=false;
instance->update_aabb=false;
instance->update_materials=false;
instance->update_next=0;
}
}

View File

@ -160,6 +160,7 @@ class VisualServerRaster : public VisualServer {
Scenario *scenario;
bool update;
bool update_aabb;
bool update_materials;
Instance *update_next;
InstanceType base_type;
@ -317,6 +318,8 @@ class VisualServerRaster : public VisualServer {
draw_range_end=0;
extra_margin=0;
visible_in_all_rooms=false;
update_aabb=false;
update_materials=false;
baked_light=NULL;
baked_light_info=NULL;
@ -583,8 +586,8 @@ class VisualServerRaster : public VisualServer {
void _portal_disconnect(Instance *p_portal,bool p_cleanup=false);
void _portal_attempt_connect(Instance *p_portal);
void _dependency_queue_update(RID p_rid,bool p_update_aabb=false);
_FORCE_INLINE_ void _instance_queue_update(Instance *p_instance,bool p_update_aabb=false);
void _dependency_queue_update(RID p_rid, bool p_update_aabb=false, bool p_update_materials=false);
_FORCE_INLINE_ void _instance_queue_update(Instance *p_instance,bool p_update_aabb=false,bool p_update_materials=false);
void _update_instances();
void _update_instance_aabb(Instance *p_instance);
void _update_instance(Instance *p_instance);
@ -1083,6 +1086,9 @@ public:
virtual void instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight);
virtual float instance_get_morph_target_weight(RID p_instance,int p_shape) const;
virtual void instance_set_surface_material(RID p_instance,int p_surface, RID p_material);
virtual void instance_set_transform(RID p_instance, const Transform& p_transform);
virtual Transform instance_get_transform(RID p_instance) const;

View File

@ -525,6 +525,8 @@ public:
FUNC3(instance_set_morph_target_weight,RID,int, float);
FUNC2RC(float,instance_get_morph_target_weight,RID,int);
FUNC3(instance_set_surface_material,RID,int, RID);
FUNC2(instance_set_transform,RID, const Transform&);
FUNC1RC(Transform,instance_get_transform,RID);

View File

@ -919,6 +919,8 @@ public:
virtual void instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight)=0;
virtual float instance_get_morph_target_weight(RID p_instance,int p_shape) const=0;
virtual void instance_set_surface_material(RID p_instance,int p_surface, RID p_material)=0;
virtual void instance_attach_skeleton(RID p_instance,RID p_skeleton)=0;
virtual RID instance_get_skeleton(RID p_instance) const=0;

View File

@ -255,6 +255,15 @@ void CreateDialog::set_base_type(const String& p_base) {
_update_search();
}
String CreateDialog::get_selected_type() {
TreeItem *selected = search_options->get_selected();
if (selected)
return selected->get_text(0);
else
return String();
}
Object *CreateDialog::instance_selected() {
TreeItem *selected = search_options->get_selected();

View File

@ -66,6 +66,7 @@ protected:
public:
Object *instance_selected();
String get_selected_type();
void set_base_type(const String& p_base);
String get_base_type() const;

View File

@ -149,6 +149,41 @@ bool EditorFileSystemDirectory::is_missing_sources(int p_idx) const {
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;
}
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]->meta.sources[p_source].missing;
}
StringName EditorFileSystemDirectory::get_file_type(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,files.size(),"");
@ -210,8 +245,11 @@ EditorFileSystemDirectory::ImportMeta EditorFileSystem::_get_meta(const String&
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);
@ -649,7 +687,13 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess
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;
}
p_dir->files.push_back(fi);
@ -764,6 +808,9 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S
ia.dir=p_dir;
ia.file=f;
scan_actions.push_back(ia);
fi->meta.sources_changed=true;
} else {
fi->meta.sources_changed=false;
}
} else {
@ -800,6 +847,9 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S
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;
}
}
@ -1113,6 +1163,25 @@ String EditorFileSystem::get_file_type(const String& p_file) const {
}
EditorFileSystemDirectory* EditorFileSystem::find_file(const String& p_file,int* r_index) const {
if (!filesystem || scanning)
return NULL;
EditorFileSystemDirectory *fs=NULL;
int cpos=-1;
if (!_find_file(p_file,&fs,cpos)) {
return NULL;
}
if (r_index)
*r_index=cpos;
return fs;
}
EditorFileSystemDirectory *EditorFileSystem::get_path(const String& p_path) {

View File

@ -63,6 +63,7 @@ class EditorFileSystemDirectory : public Object {
String import_editor;
Vector<String> deps;
bool enabled;
bool sources_changed;
};
@ -102,8 +103,12 @@ public:
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();
@ -230,6 +235,7 @@ public:
String find_resource_from_source(const String& p_path) const;
EditorFileSystemDirectory *get_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;
EditorFileSystem();
~EditorFileSystem();
};

View File

@ -85,6 +85,9 @@ void EditorImportPlugin::_bind_methods() {
ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo("import_dialog",PropertyInfo(Variant::STRING,"from")));
ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo(Variant::INT,"import",PropertyInfo(Variant::STRING,"path"),PropertyInfo(Variant::OBJECT,"from",PROPERTY_HINT_RESOURCE_TYPE,"ResourceImportMetadata")));
ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo(Variant::RAW_ARRAY,"custom_export",PropertyInfo(Variant::STRING,"path"),PropertyInfo(Variant::OBJECT,"platform",PROPERTY_HINT_RESOURCE_TYPE,"EditorExportPlatform")));
ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo("import_from_drop",PropertyInfo(Variant::STRING_ARRAY,"files"),PropertyInfo(Variant::STRING,"dest_path")));
ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo("reimport_multiple_files",PropertyInfo(Variant::STRING_ARRAY,"files")));
ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo(Variant::BOOL,"can_reimport_multiple_files"));
// BIND_VMETHOD( mi );
}
@ -130,13 +133,37 @@ Error EditorImportPlugin::import(const String& p_path, const Ref<ResourceImportM
Vector<uint8_t> EditorImportPlugin::custom_export(const String& p_path, const Ref<EditorExportPlatform> &p_platform) {
if (get_script_instance() && get_script_instance()->has_method("_custom_export")) {
get_script_instance()->call("_custom_export",p_path,p_platform);
if (get_script_instance() && get_script_instance()->has_method("custom_export")) {
get_script_instance()->call("custom_export",p_path,p_platform);
}
return Vector<uint8_t>();
}
bool EditorImportPlugin::can_reimport_multiple_files() const {
if (get_script_instance() && get_script_instance()->has_method("can_reimport_multiple_files")) {
return get_script_instance()->call("can_reimport_multiple_files");
}
return false;
}
void EditorImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
if (get_script_instance() && get_script_instance()->has_method("reimport_multiple_files")) {
get_script_instance()->call("reimport_multiple_files",p_list);
}
}
void EditorImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
if (get_script_instance() && get_script_instance()->has_method("import_from_drop")) {
get_script_instance()->call("import_from_drop",p_drop,p_dest_path);
}
}
EditorImportPlugin::EditorImportPlugin() {

View File

@ -60,6 +60,9 @@ public:
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
virtual void reimport_multiple_files(const Vector<String>& p_list);
virtual bool can_reimport_multiple_files() const;
virtual Vector<uint8_t> custom_export(const String& p_path,const Ref<EditorExportPlatform> &p_platform);
EditorImportPlugin();

View File

@ -288,6 +288,7 @@ void EditorNode::_notification(int p_what) {
get_tree()->get_root()->set_as_audio_listener(false);
get_tree()->get_root()->set_as_audio_listener_2d(false);
get_tree()->set_auto_accept_quit(false);
get_tree()->connect("files_dropped",this,"_dropped_files");
//VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport(),false);
//import_monitor->scan_changes();
@ -375,6 +376,7 @@ void EditorNode::_notification(int p_what) {
_menu_option_confirm(DEPENDENCY_LOAD_CHANGED_IMAGES,true);
}
waiting_for_sources_changed=true;
EditorFileSystem::get_singleton()->scan_sources();
}
@ -412,6 +414,42 @@ void EditorNode::_fs_changed() {
void EditorNode::_sources_changed(bool p_exist) {
if (p_exist && bool(EditorSettings::get_singleton()->get("import/automatic_reimport_on_sources_changed"))) {
p_exist=false;
List<String> changed_sources;
EditorFileSystem::get_singleton()->get_changed_sources(&changed_sources);
EditorProgress ep("reimport",TTR("Re-Importing"),changed_sources.size());
int step_idx=0;
for(List<String>::Element *E=changed_sources.front();E;E=E->next()) {
ep.step(TTR("Importing:")+" "+E->get(),step_idx++);
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());
}
}
EditorFileSystem::get_singleton()->scan_sources();
waiting_for_sources_changed=false;
return;
}
if (p_exist) {
sources_button->set_icon(gui_base->get_icon("DependencyChanged","EditorIcons"));
@ -424,6 +462,8 @@ void EditorNode::_sources_changed(bool p_exist) {
}
waiting_for_sources_changed=false;
}
void EditorNode::_vp_resized() {
@ -435,13 +475,13 @@ void EditorNode::_rebuild_import_menu()
{
PopupMenu* p = import_menu->get_popup();
p->clear();
p->add_item(TTR("Node From Scene"), FILE_IMPORT_SUBSCENE);
p->add_separator();
//p->add_item(TTR("Node From Scene"), FILE_IMPORT_SUBSCENE);
//p->add_separator();
for (int i = 0; i < editor_import_export->get_import_plugin_count(); i++) {
p->add_item(editor_import_export->get_import_plugin(i)->get_visible_name(), IMPORT_PLUGIN_BASE + i);
}
p->add_separator();
p->add_item(TTR("Re-Import.."), SETTINGS_IMPORT);
//p->add_separator();
//p->add_item(TTR("Re-Import.."), SETTINGS_IMPORT);
}
void EditorNode::_node_renamed() {
@ -2858,6 +2898,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
} break;
default: {
if (p_option>=OBJECT_METHOD_BASE) {
@ -4899,6 +4940,7 @@ Variant EditorNode::drag_resource(const Ref<Resource>& p_res,Control* p_from) {
TextureFrame *drag_preview = memnew( TextureFrame );
Label* label=memnew( Label );
waiting_for_sources_changed=true; //
Ref<Texture> preview;
{
@ -5000,6 +5042,15 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String>& p_files, Control *
}
void EditorNode::_dropped_files(const Vector<String>& p_files,int p_screen) {
String cur_path = scenes_dock->get_current_path();
for(int i=0;i<EditorImportExport::get_singleton()->get_import_plugin_count();i++) {
EditorImportExport::get_singleton()->get_import_plugin(i)->import_from_drop(p_files,cur_path);
}
}
void EditorNode::_bind_methods() {
@ -5067,6 +5118,9 @@ void EditorNode::_bind_methods() {
ObjectTypeDB::bind_method("_toggle_search_bar",&EditorNode::_toggle_search_bar);
ObjectTypeDB::bind_method("_clear_search_box",&EditorNode::_clear_search_box);
ObjectTypeDB::bind_method("_clear_undo_history",&EditorNode::_clear_undo_history);
ObjectTypeDB::bind_method("_dropped_files",&EditorNode::_dropped_files);
ObjectTypeDB::bind_method(_MD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin);
ObjectTypeDB::bind_method(_MD("remove_editor_import_plugin", "plugin"), &EditorNode::remove_editor_import_plugin);
@ -6185,10 +6239,7 @@ EditorNode::EditorNode() {
file_server = memnew( EditorFileServer );
editor_import_export->add_import_plugin( Ref<EditorTextureImportPlugin>( memnew(EditorTextureImportPlugin(this,EditorTextureImportPlugin::MODE_TEXTURE_2D) )));
editor_import_export->add_import_plugin( Ref<EditorTextureImportPlugin>( memnew(EditorTextureImportPlugin(this,EditorTextureImportPlugin::MODE_ATLAS) )));
editor_import_export->add_import_plugin( Ref<EditorTextureImportPlugin>( memnew(EditorTextureImportPlugin(this,EditorTextureImportPlugin::MODE_LARGE) )));
editor_import_export->add_import_plugin( Ref<EditorTextureImportPlugin>( memnew(EditorTextureImportPlugin(this,EditorTextureImportPlugin::MODE_TEXTURE_3D) )));
editor_import_export->add_import_plugin( Ref<EditorTextureImportPlugin>( memnew(EditorTextureImportPlugin(this) )));
Ref<EditorSceneImportPlugin> _scene_import = memnew(EditorSceneImportPlugin(this) );
Ref<EditorSceneImporterCollada> _collada_import = memnew( EditorSceneImporterCollada);
_scene_import->add_importer(_collada_import);
@ -6401,6 +6452,7 @@ EditorNode::EditorNode() {
_load_docks();
}

View File

@ -366,6 +366,8 @@ private:
String open_navigate;
bool changing_scene;
bool waiting_for_sources_changed;
uint32_t circle_step_msec;
uint64_t circle_step_frame;
int circle_step;
@ -464,6 +466,7 @@ private:
void _add_to_recent_scenes(const String& p_scene);
void _update_recent_scenes();
void _open_recent_scene(int p_idx);
void _dropped_files(const Vector<String>& p_files,int p_screen);
//void _open_recent_scene_confirm();
String _recent_scene;
@ -607,6 +610,8 @@ public:
void save_resource(const Ref<Resource>& p_resource);
void save_resource_as(const Ref<Resource>& p_resource, const String &p_at_path=String());
void merge_from_scene() { _menu_option_confirm(FILE_IMPORT_SUBSCENE,false); }
static bool has_unsaved_changes() { return singleton->unsaved_cache; }
static HBoxContainer *get_menu_hb() { return singleton->menu_hb; }

View File

@ -36,14 +36,24 @@ void EditorResourcePreview::_preview_ready(const String& p_str,const Ref<Texture
//print_line("preview is ready");
preview_mutex->lock();
String path = p_str;
uint32_t hash=0;
if (p_str.begins_with("ID:")) {
hash=p_str.get_slicec(':',2).to_int();
path="ID:"+p_str.get_slicec(':',1);
}
Item item;
item.order=order++;
item.preview=p_texture;
cache[p_str]=item;
item.last_hash=hash;
cache[path]=item;
Object *recv = ObjectDB::get_instance(id);
if (recv) {
recv->call_deferred(p_func,p_str,p_texture,p_ud);
recv->call_deferred(p_func,path,p_texture,p_ud);
}
preview_mutex->unlock();
@ -51,7 +61,12 @@ void EditorResourcePreview::_preview_ready(const String& p_str,const Ref<Texture
Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem& p_item,const String& cache_base) {
String type = ResourceLoader::get_resource_type(p_item.path);
String type;
if (p_item.resource.is_valid())
type=p_item.resource->get_type();
else
type=ResourceLoader::get_resource_type(p_item.path);
//print_line("resource type is: "+type);
if (type=="")
@ -62,11 +77,17 @@ Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem& p_item,co
for(int i=0;i<preview_generators.size();i++) {
if (!preview_generators[i]->handles(type))
continue;
if (p_item.resource.is_valid()) {
generated = preview_generators[i]->generate(p_item.resource);
} else {
generated = preview_generators[i]->generate_from_path(p_item.path);
}
break;
}
if (!p_item.resource.is_valid()) {
// cache the preview in case it's a resource on disk
if (generated.is_valid()) {
//print_line("was generated");
int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
@ -81,6 +102,7 @@ Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem& p_item,co
//print_line("was not generated");
}
}
return generated;
}
@ -113,8 +135,17 @@ void EditorResourcePreview::_thread() {
if (cache.has(item.path)) {
//already has it because someone loaded it, just let it know it's ready
if (item.resource.is_valid()) {
item.path+=":"+itos(cache[item.path].last_hash); //keep last hash (see description of what this is in condition below)
}
call_deferred("_preview_ready",item.path,cache[item.path].preview,item.id,item.function,item.userdata);
} else if (item.resource.is_valid()){
texture=_generate_preview(item,String());
//adding hash to the end of path (should be ID:<objid>:<hash>) because of 5 argument limit to call_deferred
call_deferred("_preview_ready",item.path+":"+itos(item.resource->hash_edited_version()),texture,item.id,item.function,item.userdata);
} else {
@ -194,6 +225,35 @@ void EditorResourcePreview::_thread() {
void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource>& p_res, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata) {
ERR_FAIL_NULL(p_receiver);
ERR_FAIL_COND(!p_res.is_valid());
preview_mutex->lock();
String path_id = "ID:"+itos(p_res->get_instance_ID());
if (cache.has(path_id) && cache[path_id].last_hash==p_res->hash_edited_version()) {
cache[path_id].order=order++;
p_receiver->call_deferred(p_receiver_func,path_id,cache[path_id].preview,p_userdata);
preview_mutex->unlock();
return;
}
//print_line("send to thread "+p_path);
QueueItem item;
item.function=p_receiver_func;
item.id=p_receiver->get_instance_ID();
item.resource=p_res;
item.path=path_id;
item.userdata=p_userdata;
queue.push_back(item);
preview_mutex->unlock();
preview_sem->post();
}
void EditorResourcePreview::queue_resource_preview(const String& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata) {
@ -204,7 +264,6 @@ void EditorResourcePreview::queue_resource_preview(const String& p_path, Object*
p_receiver->call_deferred(p_receiver_func,p_path,cache[p_path].preview,p_userdata);
preview_mutex->unlock();
return;
}
//print_line("send to thread "+p_path);

View File

@ -47,6 +47,7 @@ class EditorResourcePreview : public Node {
static EditorResourcePreview* singleton;
struct QueueItem {
Ref<Resource> resource;
String path;
ObjectID id;
StringName function;
@ -63,6 +64,7 @@ class EditorResourcePreview : public Node {
struct Item {
Ref<Texture> preview;
int order;
uint32_t last_hash;
};
int order;
@ -84,7 +86,8 @@ public:
static EditorResourcePreview* get_singleton();
//callback funtion is callback(String p_path,Ref<Texture> preview,Variant udata) preview null if could not load
void queue_resource_preview(const String& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata);
void queue_resource_preview(const String& p_res, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata);
void queue_edited_resource_preview(const Ref<Resource>& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata);
void add_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator);

View File

@ -507,6 +507,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
set("resources/save_compressed_resources",true);
set("resources/auto_reload_modified_images",true);
set("import/automatic_reimport_on_sources_changed",true);
if (p_extra_config.is_valid()) {
if (p_extra_config->has_section("init_projects") && p_extra_config->has_section_key("init_projects", "list")) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 B

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 685 B

After

Width:  |  Height:  |  Size: 707 B

View File

@ -601,6 +601,13 @@ public:
}
}
void set_source_and_dest(const String& p_font,const String& p_dest) {
source->get_line_edit()->set_text(p_font);
dest->get_line_edit()->set_text(p_dest);
_prop_changed();
}
EditorFontImportDialog(EditorFontImportPlugin *p_plugin) {
plugin=p_plugin;
VBoxContainer *vbc = memnew( VBoxContainer );
@ -1629,6 +1636,20 @@ Error EditorFontImportPlugin::import(const String& p_path, const Ref<ResourceImp
}
void EditorFontImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
for(int i=0;i<p_drop.size();i++) {
String ext = p_drop[i].extension().to_lower();
String file = p_drop[i].get_file();
if (ext=="ttf" || ext=="otf" || ext=="fnt") {
import_dialog();
dialog->set_source_and_dest(p_drop[i],p_dest_path.plus_file(file.basename()+".fnt"));
break;
}
}
}
EditorFontImportPlugin::EditorFontImportPlugin(EditorNode* p_editor) {

View File

@ -48,6 +48,7 @@ public:
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
EditorFontImportPlugin(EditorNode* p_editor);

View File

@ -331,7 +331,7 @@ String EditorMeshImportPlugin::get_name() const {
}
String EditorMeshImportPlugin::get_visible_name() const{
return "3D Mesh";
return "Mesh";
}
void EditorMeshImportPlugin::import_dialog(const String& p_from){
@ -536,6 +536,26 @@ Error EditorMeshImportPlugin::import(const String& p_path, const Ref<ResourceImp
}
void EditorMeshImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
Vector<String> files;
for(int i=0;i<p_drop.size();i++) {
String ext = p_drop[i].extension().to_lower();
String file = p_drop[i].get_file();
if (ext=="obj") {
files.push_back(p_drop[i]);
}
}
if (files.size()) {
import_dialog();
dialog->_choose_files(files);
dialog->_choose_save_dir(p_dest_path);
}
}
EditorMeshImportPlugin::EditorMeshImportPlugin(EditorNode* p_editor) {
dialog = memnew( EditorMeshImportDialog(this));

View File

@ -21,6 +21,7 @@ public:
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
EditorMeshImportPlugin(EditorNode* p_editor);

View File

@ -823,6 +823,58 @@ void EditorSampleImportPlugin::_compress_ima_adpcm(const Vector<float>& p_data,D
EditorSampleImportPlugin* EditorSampleImportPlugin::singleton=NULL;
void EditorSampleImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
Vector<String> files;
for(int i=0;i<p_drop.size();i++) {
String ext = p_drop[i].extension().to_lower();
if (ext=="wav") {
files.push_back(p_drop[i]);
}
}
if (files.size()) {
import_dialog();
dialog->_choose_files(files);
dialog->_choose_save_dir(p_dest_path);
}
}
void EditorSampleImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
if (p_list.size()==0)
return;
Vector<String> sources;
for(int i=0;i<p_list.size();i++) {
int idx;
EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(p_list[i],&idx);
if (efsd) {
for(int j=0;j<efsd->get_source_count(idx);j++) {
String file = expand_source_path(efsd->get_source_file(idx,j));
if (sources.find(file)==-1) {
sources.push_back(file);
}
}
}
}
if (sources.size()) {
dialog->popup_import(p_list[0]);
dialog->_choose_files(sources);
dialog->_choose_save_dir(p_list[0].get_base_dir());
}
}
bool EditorSampleImportPlugin::can_reimport_multiple_files() const {
return true;
}
EditorSampleImportPlugin::EditorSampleImportPlugin(EditorNode* p_editor) {
@ -865,6 +917,7 @@ Vector<uint8_t> EditorSampleExportPlugin::custom_export(String& p_path,const Ref
}
EditorSampleExportPlugin::EditorSampleExportPlugin() {
}

View File

@ -49,6 +49,9 @@ public:
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
virtual void reimport_multiple_files(const Vector<String>& p_list);
virtual bool can_reimport_multiple_files() const;
EditorSampleImportPlugin(EditorNode* p_editor);

View File

@ -41,6 +41,7 @@
#include "scene/3d/physics_body.h"
#include "scene/3d/portal.h"
#include "scene/3d/vehicle_body.h"
#include "tools/editor/create_dialog.h"
#include "os/os.h"
@ -95,6 +96,7 @@ class EditorImportAnimationOptions : public VBoxContainer {
Tree *optimization_tree;
Vector<TreeItem*> items;
bool updating;
bool validating;
@ -167,6 +169,7 @@ class EditorSceneImportDialog : public ConfirmationDialog {
EditorFileDialog *script_select;
EditorDirDialog *save_select;
OptionButton *texture_action;
CreateDialog *root_type_choose;
ConfirmationDialog *confirm_open;
@ -178,8 +181,13 @@ class EditorSceneImportDialog : public ConfirmationDialog {
Map<Ref<Mesh>,Ref<Shape> > collision_map;
ConfirmationDialog *error_dialog;
OptionButton *this_import;
OptionButton *next_import;
Button *root_type;
CheckBox *root_default;
void _root_default_pressed();
void _root_type_pressed();
void _set_root_type();
void _choose_file(const String& p_path);
void _choose_save_file(const String& p_path);
@ -206,6 +214,11 @@ protected:
static void _bind_methods();
public:
void setup_popup(const String& p_from,const String& p_to_path) {
_choose_file(p_from);
_choose_save_file(p_to_path);
}
Error import(const String& p_from, const String& p_to, const String& p_preset);
void popup_import(const String& p_from);
EditorSceneImportDialog(EditorNode *p_editor,EditorSceneImportPlugin *p_plugin);
@ -764,9 +777,10 @@ void EditorSceneImportDialog::_import(bool p_and_open) {
rim->set_option("animation_filters",animation_options->get_filter());
rim->set_option("animation_clips",animation_options->get_clips());
rim->set_option("post_import_script",script_path->get_text());
rim->set_option("import_this_time",this_import->get_selected());
rim->set_option("import_next_time",next_import->get_selected());
rim->set_option("reimport",true);
if (!root_default->is_pressed()) {
rim->set_option("root_type",root_type->get_text());
}
List<String> missing;
Error err = plugin->import1(rim,&scene,&missing);
@ -909,12 +923,24 @@ void EditorSceneImportDialog::popup_import(const String &p_from) {
if (rimd->has_option("animation_optimizer_max_angle"))
animation_options->set_optimize_max_angle(rimd->get_option("animation_optimizer_max_angle"));
if (rimd->has_option("root_type")) {
root_default->set_pressed(false);
String type = rimd->get_option("root_type");
root_type->set_text(type);
root_type->set_disabled(false);
if (has_icon(type,"EditorIcons")) {
root_type->set_icon(get_icon(type,"EditorIcons"));
} else {
root_type->set_icon(get_icon("Object","EditorIcons"));
}
} else {
root_default->set_pressed(true);
root_type->set_disabled(true);
}
script_path->set_text(rimd->get_option("post_import_script"));
if (rimd->has_option("import_this_time"))
this_import->select(rimd->get_option("import_this_time"));
if (rimd->has_option("import_next_time"))
next_import->select(rimd->get_option("import_next_time"));
save_path->set_text(p_from.get_base_dir());
import_path->set_text(EditorImportPlugin::expand_source_path(rimd->get_source_path(0)));
@ -931,6 +957,9 @@ void EditorSceneImportDialog::_notification(int p_what) {
List<String> extensions;
file_select->clear_filters();
root_type->set_icon(get_icon("Spatial","EditorIcons"));
root_type->set_text("Spatial");
root_type->set_disabled(true);
for(int i=0;i<plugin->get_importers().size();i++) {
plugin->get_importers()[i]->get_extensions(&extensions);
@ -981,7 +1010,30 @@ void EditorSceneImportDialog::_dialog_hid() {
wip_rimd=Ref<ResourceImportMetadata>();
}
}
void EditorSceneImportDialog::_root_default_pressed() {
root_type->set_disabled(root_default->is_pressed());
}
void EditorSceneImportDialog::_root_type_pressed() {
root_type_choose->popup(false);
}
void EditorSceneImportDialog::_set_root_type() {
String type = root_type_choose->get_selected_type();
if (type==String())
return;
root_type->set_text(type);
if (has_icon(type,"EditorIcons")) {
root_type->set_icon(get_icon(type,"EditorIcons"));
} else {
root_type->set_icon(get_icon("Object","EditorIcons"));
}
}
void EditorSceneImportDialog::_bind_methods() {
@ -996,13 +1048,16 @@ void EditorSceneImportDialog::_bind_methods() {
ObjectTypeDB::bind_method("_dialog_hid",&EditorSceneImportDialog::_dialog_hid);
ObjectTypeDB::bind_method("_import_confirm",&EditorSceneImportDialog::_import_confirm);
ObjectTypeDB::bind_method("_open_and_import",&EditorSceneImportDialog::_open_and_import);
ObjectTypeDB::bind_method("_root_default_pressed",&EditorSceneImportDialog::_root_default_pressed);
ObjectTypeDB::bind_method("_root_type_pressed",&EditorSceneImportDialog::_root_type_pressed);
ObjectTypeDB::bind_method("_set_root_type",&EditorSceneImportDialog::_set_root_type);
ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
}
const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_names[]={
{EditorSceneImportPlugin::SCENE_FLAG_REMOVE_NOIMP,("Actions"),"Remove Nodes (-noimp)",true},
@ -1162,6 +1217,23 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce
error_dialog->get_ok()->set_text(TTR("Accept"));
// error_dialog->get_cancel()->hide();
HBoxContainer *custom_root_hb = memnew( HBoxContainer );
vbc->add_margin_child(TTR("Custom Root Node Type:"),custom_root_hb);
root_type = memnew(Button);
root_type->set_h_size_flags(SIZE_EXPAND_FILL);
root_type->set_text_align(Button::ALIGN_LEFT);
root_type->connect("pressed",this,"_root_type_pressed");
custom_root_hb->add_child(root_type);
root_default = memnew(CheckBox);
root_default->set_text("Auto");
root_default->set_pressed(true);
root_default->connect("pressed",this,"_root_default_pressed");
custom_root_hb->add_child(root_default);
/*
this_import = memnew( OptionButton );
this_import->add_item(TTR("Overwrite Existing Scene"));
this_import->add_item(TTR("Overwrite Existing, Keep Materials"));
@ -1175,7 +1247,7 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce
next_import->add_item(TTR("Keep Existing, Merge with New"));
next_import->add_item(TTR("Keep Existing, Ignore New"));
vbc->add_margin_child(TTR("Next Time:"),next_import);
*/
set_hide_on_ok(false);
GLOBAL_DEF("import/shared_textures","res://");
@ -1183,6 +1255,7 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce
import_hb->add_constant_override("separation",30);
VBoxContainer *ovb = memnew( VBoxContainer);
ovb->set_h_size_flags(SIZE_EXPAND_FILL);
import_hb->add_child(ovb);
@ -1232,6 +1305,10 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce
wip_open=false;
//texture_options->set_format(EditorImport::IMAGE_FORMAT_C);
root_type_choose = memnew( CreateDialog );
add_child(root_type_choose);
root_type_choose->set_base_type("Node");
root_type_choose->connect("create",this,"_set_root_type");
}
@ -1247,7 +1324,7 @@ String EditorSceneImportPlugin::get_name() const {
String EditorSceneImportPlugin::get_visible_name() const{
return "3D Scene";
return "Scene";
}
void EditorSceneImportPlugin::import_dialog(const String& p_from){
@ -1906,398 +1983,8 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
}
void EditorSceneImportPlugin::_merge_existing_node(Node *p_node,Node *p_imported_scene,Set<Ref<Resource> >& checked_resources,Set<Node*> &checked_nodes) {
NodePath path = p_node->get_import_path();
if (!path.is_empty() && p_imported_scene->has_node(path)) {
Node *imported_node = p_imported_scene->get_node(path);
if (imported_node->get_type()==p_node->get_type()) {
//same thing, check what it is
if (p_node->get_type()=="MeshInstance") {
//merge mesh instance, this is a special case!
MeshInstance *mi_imported=imported_node->cast_to<MeshInstance>();
MeshInstance *mi_node=p_node->cast_to<MeshInstance>();
Ref<Mesh> mesh_imported = mi_imported->get_mesh();
Ref<Mesh> mesh_node = mi_node->get_mesh();
if (mesh_node.is_null() && mesh_imported.is_valid()) {
mi_node->set_mesh(mesh_imported);
} else if (mesh_node.is_valid() && mesh_imported.is_valid()) {
if (checked_resources.has(mesh_imported)) {
mi_node->set_mesh(mesh_imported);
} else {
//mix up meshes
//import new geometry but keep materials
for(int i=0;i<mesh_imported->get_surface_count();i++) {
String name = mesh_imported->surface_get_name(i);
for(int j=0;j<mesh_node->get_surface_count();j++) {
Ref<Material> mat = mesh_node->surface_get_material(j);
if (mat.is_valid() && mesh_node->surface_get_name(j)==name ) {
mesh_imported->surface_set_material(i,mat);
break;
}
}
}
// was imported, do nothing further
checked_resources.insert(mesh_imported);
mi_node->set_mesh(mesh_imported);
}
}
} else if (p_node->get_type()=="Path") {
//for paths, overwrite path
Path *path_imported =imported_node->cast_to<Path>();
Path *path_node =p_node->cast_to<Path>();
if (path_imported->get_curve().is_valid()) {
path_node->set_curve(path_imported->get_curve());
}
} else if (p_node->get_type()=="Portal") {
//for paths, overwrite path
Portal *portal_imported =imported_node->cast_to<Portal>();
Portal *portal_node =p_node->cast_to<Portal>();
portal_node->set_shape( portal_imported->get_shape() );
} else if (p_node->get_type()=="Room") {
//for paths, overwrite path
Room *room_imported =imported_node->cast_to<Room>();
Room *room_node =p_node->cast_to<Room>();
room_node->set_room( room_imported->get_room() );
} else if (p_node->get_type()=="Skeleton") {
//for paths, overwrite path
Skeleton *skeleton_imported =imported_node->cast_to<Skeleton>();
Skeleton *skeleton_node =p_node->cast_to<Skeleton>();
//use imported bones, obviously
skeleton_node->clear_bones();
for(int i=0;i<skeleton_imported->get_bone_count();i++) {
skeleton_node->add_bone(skeleton_imported->get_bone_name(i));
skeleton_node->set_bone_parent(i,skeleton_imported->get_bone_parent(i));
skeleton_node->set_bone_rest(i,skeleton_imported->get_bone_rest(i));
//skeleton_node->set_bone_pose(i,skeleton_imported->get_bone_pose(i)); // not in a scene, will throw errors
}
}
else if (p_node->get_type() == "AnimationPlayer") {
//for paths, overwrite path
AnimationPlayer *aplayer_imported = imported_node->cast_to<AnimationPlayer>();
AnimationPlayer *aplayer_node = p_node->cast_to<AnimationPlayer>();
//use imported bones, obviously
List<StringName> anims;
List<StringName> existing_anims;
aplayer_imported->get_animation_list(&anims);
aplayer_node->get_animation_list(&existing_anims);
//use imported animations
for (List<StringName>::Element *N = anims.front(); N; N = N->next()) {
Ref<Animation> candidate = aplayer_imported->get_animation(N->get());
if (aplayer_node->has_animation(N->get())) {
Ref<Animation> found = aplayer_node->get_animation(N->get());
candidate->set_loop(found->has_loop());
candidate->set_step(found->get_step());
//For each track candidate
for (int i = 0; i < candidate->get_track_count(); i++) {
NodePath track_path = candidate->track_get_path(i);
// For each track existing
for (int x = 0; x < found->get_track_count(); x++) {
NodePath path_to_compare = found->track_get_path(x);
if (track_path.hash() == path_to_compare.hash() && candidate->track_get_type(x) == found->track_get_type(i)) {
//Tracks matches
if (candidate->track_get_interpolation_type(i) != found->track_get_interpolation_type(x))
candidate->track_set_interpolation_type(i, found->track_get_interpolation_type(x));
if (candidate->track_get_type(i) == Animation::TYPE_VALUE && candidate->value_track_is_continuous(i) != found->value_track_is_continuous(x))
candidate->value_track_set_continuous(i, found->value_track_is_continuous(x));
//Key transitions might have changed, but the animation remained unchanged
if (candidate->track_get_key_count(i) == found->track_get_key_count(x)) {
for (int k = 0; k < candidate->track_get_key_count(i); k++) {
if (candidate->track_get_key_transition(i, k) != found->track_get_key_transition(x, k))
candidate->track_set_key_transition(i, k, found->track_get_key_transition(x, k));
}
}
}
}
}
// Append function callbacks and values
for (int x = 0; x < found->get_track_count(); x++) {
if (found->track_get_type(x) == Animation::TYPE_METHOD || found->track_get_type(x) == Animation::TYPE_VALUE)
candidate->add_track(found->track_get_type(x), candidate->get_track_count());
for (int k = 0; k < found->track_get_key_count(x); k++)
candidate->track_insert_key(x, found->track_get_key_time(x, k), found->track_get_key_value(x, k), found->track_get_key_transition(x, k));
}
}
aplayer_node->add_animation(N->get(), candidate);
}
} else if (p_node->get_type()=="CollisionShape") {
//for paths, overwrite path
CollisionShape *collision_imported =imported_node->cast_to<CollisionShape>();
CollisionShape *collision_node =p_node->cast_to<CollisionShape>();
collision_node->set_shape( collision_imported->get_shape() );
}
}
if (p_node->cast_to<Spatial>() && imported_node->cast_to<Spatial>()) {
//apply transform if changed
Spatial *snode = p_node->cast_to<Spatial>();
Spatial *simp = imported_node->cast_to<Spatial>();
if (snode->get_import_transform() == snode->get_transform()) {
//not moved, apply new
snode->set_import_transform(simp->get_transform());
snode->set_transform(simp->get_transform());
} else if (snode->get_import_transform() == simp->get_import_transform()) {
//do nothing, nothing changed keep local changes
} else {
//changed both, imported and edited, merge
Transform local_xform = snode->get_import_transform().affine_inverse() * snode->get_transform();
snode->set_import_transform(simp->get_import_transform());
snode->set_transform(simp->get_import_transform() * local_xform);
}
}
checked_nodes.insert(imported_node);
}
#if 0
else {
if (p_node!=p_root && p_existing->has_node(p_root->get_path_to(p_node->get_parent()))) {
Node *parent = p_existing->get_node(p_root->get_path_to(p_node->get_parent()));
NodePath path = p_root->get_path_to(p_node);
//add it.. because not existing in existing scene
Object *o = ObjectTypeDB::instance(p_existing->get_type());
Node *n=NULL;
if (o)
n=o->cast_to<Node>();
if (n) {
List<PropertyInfo> pl;
p_existing->get_property_list(&pl);
for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
continue;
n->set( E->get().name, p_existing->get(E->get().name) );
}
parent->add_child(n);
valid=true;
}
}
}
#endif
for(int i=0;i<p_node->get_child_count();i++) {
_merge_existing_node(p_node->get_child(i),p_imported_scene,checked_resources,checked_nodes);
}
}
void EditorSceneImportPlugin::_add_new_nodes(Node *p_node,Node *p_imported,Node *p_imported_scene,Node *p_existing_scene,Set<Node*> &checked_nodes) {
for(int i=0;i<p_imported->get_child_count();i++) {
Node *imported_node = p_imported->get_child(i);
if (imported_node->get_owner()!=p_imported_scene) {
// print_line("skipping because not imported at "+String(imported_node->get_name()));
continue; //end of the road
}
Vector<StringName> nn;
nn.push_back(imported_node->get_name());
NodePath imported_path(nn,false);
//print_line("check for: "+String(imported_path));
if (!p_node->has_node(imported_path) && !checked_nodes.has(imported_node)) {
//not there, re-add it
//add it.. because not existing in existing scene
Object *o = ObjectTypeDB::instance(imported_node->get_type());
Node *n=NULL;
if (o)
n=o->cast_to<Node>();
//print_line("creating node of same type..");
if (n) {
//print_line("copy props and add");
List<PropertyInfo> pl;
imported_node->get_property_list(&pl);
for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
continue;
n->set( E->get().name, imported_node->get(E->get().name) );
}
p_node->add_child(n);
n->set_owner(p_existing_scene);
}
} else {
//print_line("already exists");
}
if (p_node->has_node(imported_path)) {
Node *other_node = p_node->get_node(imported_path);
_add_new_nodes(other_node,imported_node,p_imported_scene,p_existing_scene,checked_nodes);
}
}
}
void EditorSceneImportPlugin::_merge_scenes(Node *p_node,Node *p_imported) {
Set<Ref<Resource> > checked_resources;
Set<Node*> checked_nodes;
_merge_existing_node(p_node,p_imported,checked_resources,checked_nodes);
_add_new_nodes(p_node,p_imported,p_imported,p_node,checked_nodes);
//add existing.. ?
}
void EditorSceneImportPlugin::_scan_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials) {
if (!p_base && p_node->get_owner()!=p_base)
return;
MeshInstance *mi=p_node->cast_to<MeshInstance>();
if (mi) {
if (mi->get_material_override().is_valid()) {
String path = p_base->get_path_to(p_node);
override_materials[path]=mi->get_material_override();
}
Ref<Mesh> mesh = mi->get_mesh();
if (mesh.is_valid()) {
for(int i=0;i<mesh->get_surface_count();i++) {
String name = mesh->get_name()+":"+mesh->surface_get_name(i);
if (!mesh_materials.has(name)) {
mesh_materials[name]=mesh->surface_get_material(i);
}
}
}
}
for(int i=0;i<p_node->get_child_count();i++) {
_scan_materials(p_base,p_node->get_child(i),mesh_materials,override_materials);
}
}
void EditorSceneImportPlugin::_apply_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials,Set<Ref<Mesh> >& meshes_processed) {
if (p_node!=p_base && p_node->get_owner()!=p_base)
return;
MeshInstance *mi=p_node->cast_to<MeshInstance>();
if (mi) {
print_line("is mesh "+String(p_node->get_name()));
String path = p_base->get_path_to(p_node);
if (override_materials.has(path)) {
print_line("is in material overrides");
mi->set_material_override(override_materials[path]);
}
Ref<Mesh> mesh = mi->get_mesh();
if (mesh.is_valid() && !meshes_processed.has(mesh)) {
print_line("mesh was not processed");
meshes_processed.insert(mesh);
for(int i=0;i<mesh->get_surface_count();i++) {
String name = mesh->get_name()+":"+mesh->surface_get_name(i);
print_line("name for surface "+itos(i)+": "+name);
if (mesh_materials.has(name)) {
Ref<Material> mat = mesh_materials[name];
mesh->surface_set_material(i,mat);
print_line("overriding!");
}
}
}
}
for(int i=0;i<p_node->get_child_count();i++) {
_apply_materials(p_base,p_node->get_child(i),mesh_materials,override_materials,meshes_processed);
}
}
void EditorSceneImportPlugin::_merge_materials(Node *p_node,Node *p_imported) {
Map<String,Ref<Material> > mesh_materials;
Map<String,Ref<Material> > override_materials;
_scan_materials(p_node,p_node,mesh_materials,override_materials);
for (Map<String,Ref<Material> >::Element *E=mesh_materials.front();E;E=E->next()) {
print_line("Mats: "+String(E->key()));
}
for (Map<String,Ref<Material> >::Element *E=override_materials.front();E;E=E->next()) {
print_line("Overrides: "+String(E->key()));
}
Set<Ref<Mesh> > mp;
_apply_materials(p_imported,p_imported,mesh_materials,override_materials,mp);
}
#if 0
Error EditorImport::import_scene(const String& p_path,const String& p_dest_path,const String& p_resource_path,uint32_t p_flags,ImageFormat p_image_format,ImageCompression p_image_compression,uint32_t p_image_flags,float p_quality,uint32_t animation_flags,Node **r_scene,Ref<EditorPostImport> p_post_import) {
@ -2397,6 +2084,21 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from
return err;
}
if (from->has_option("root_type")) {
String type = from->get_option("root_type");
Object *base = ObjectTypeDB::instance(type);
Node *base_node = NULL;
if (base)
base_node=base->cast_to<Node>();
if (base_node) {
scene->replace_by(base_node);
memdelete(scene);
scene=base_node;
}
}
_tag_import_paths(scene,scene);
*r_node=scene;
@ -2839,66 +2541,12 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
}
}
Error err = EditorTextureImportPlugin::get_singleton(EditorTextureImportPlugin::MODE_TEXTURE_3D)->import(target_path,imd);
Error err = EditorTextureImportPlugin::get_singleton()->import(target_path,imd);
}
}
/// BEFORE SAVING - MERGE
if (import_action!=SCENE_UPDATE_REPLACE_WITH_NEW) {
progress.step(TTR("Merging.."),103);
FileAccess *fa = FileAccess::create(FileAccess::ACCESS_RESOURCES);
if (fa->file_exists(p_dest_path)) {
//try to merge
Ref<PackedScene> s = ResourceLoader::load(p_dest_path);
if (s.is_valid()) {
Node *existing = s->instance(true);
if (existing) {
switch(import_action) {
case SCENE_UPDATE_REPLACE_WITH_NEW: break;
case SCENE_UPDATE_REPLACE_WITH_NEW_KEEP_MATERIALS: {
_merge_materials(existing,scene);
memdelete(existing);
} break;
case SCENE_UPDATE_KEEP_OLD_MERGE_CHANGES: {
_merge_scenes(existing,scene);
memdelete(scene);
scene=existing;
} break;
case SCENE_UPDATE_KEEP_OLD: {
memdelete(scene);
scene=existing;
} break;
}
}
}
}
memdelete(fa);
}
progress.step(TTR("Saving.."),104);
@ -2957,6 +2605,30 @@ void EditorSceneImportPlugin::add_importer(const Ref<EditorSceneImporter>& p_imp
importers.push_back(p_importer);
}
void EditorSceneImportPlugin::import_from_drop(const Vector<String>& p_drop,const String& p_dest_path) {
List<String> extensions;
for(int i=0;i<importers.size();i++) {
importers[i]->get_extensions(&extensions);
}
//bool warn_compatible=false;
for(int i=0;i<p_drop.size();i++) {
String extension = p_drop[i].extension().to_lower();
for(List<String>::Element *E=extensions.front();E;E=E->next()) {
if (E->get()==extension) {
dialog->popup_import(String());
dialog->setup_popup(p_drop[i],p_dest_path);
return;
}
}
}
}
EditorSceneImportPlugin::EditorSceneImportPlugin(EditorNode* p_editor) {

View File

@ -45,6 +45,7 @@
#include "tools/editor/io_plugins/editor_texture_import_plugin.h"
#include "scene/resources/animation.h"
class EditorNode;
class EditorSceneImportDialog;
@ -111,16 +112,8 @@ class EditorSceneImportPlugin : public EditorImportPlugin {
void _create_clips(Node *scene, const Array& p_clips, bool p_bake_all);
void _filter_anim_tracks(Ref<Animation> anim,Set<String> &keep);
void _filter_tracks(Node *scene, const String& p_text);
void _merge_existing_node(Node *p_node,Node *p_imported_scene,Set<Ref<Resource> >& checked_resources,Set<Node*> &checked_nodes);
void _add_new_nodes(Node *p_node,Node *p_imported,Node *p_imported_scene,Node *p_existing_scene,Set<Node*> &checked_nodes);
void _optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle);
void _merge_scenes(Node *p_node, Node *p_imported);
void _scan_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials);
void _apply_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials,Set<Ref<Mesh> >& meshes_processed);
void _merge_materials(Node *p_node,Node *p_imported);
void _tag_import_paths(Node *p_scene,Node *p_node);
public:
@ -150,13 +143,6 @@ public:
SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY=1<<30,
};
enum SceneUpdate {
SCENE_UPDATE_REPLACE_WITH_NEW,
SCENE_UPDATE_REPLACE_WITH_NEW_KEEP_MATERIALS,
SCENE_UPDATE_KEEP_OLD_MERGE_CHANGES,
SCENE_UPDATE_KEEP_OLD,
};
virtual String get_name() const;
virtual String get_visible_name() const;
@ -169,6 +155,8 @@ public:
void add_importer(const Ref<EditorSceneImporter>& p_importer);
const Vector<Ref<EditorSceneImporter> >& get_importers() { return importers; }
virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
EditorSceneImportPlugin(EditorNode* p_editor=NULL);

View File

@ -35,6 +35,9 @@
#include "io/md5.h"
#include "io/marshalls.h"
#include "globals.h"
#include "scene/gui/check_button.h"
#include "scene/gui/button_group.h"
#include "scene/gui/margin_container.h"
static const char *flag_names[]={
("Streaming Format"),
@ -164,12 +167,13 @@ void EditorImportTextureOptions::_notification(int p_what) {
void EditorImportTextureOptions::show_2d_notice() {
notice_for_2d->show();
//notice_for_2d->show();
}
EditorImportTextureOptions::EditorImportTextureOptions() {
add_constant_override("separation",3);
updating=false;
format = memnew( OptionButton );
@ -223,12 +227,6 @@ EditorImportTextureOptions::EditorImportTextureOptions() {
add_margin_child(TTR("Texture Options"),flags,true);
notice_for_2d = memnew( Label );
notice_for_2d->set_text(TTR("NOTICE: You are not forced to import textures for 2D projects. Just copy your .jpg or .png files to your project, and change export options later. Atlases can be generated on export too."));
notice_for_2d->set_custom_minimum_size(Size2(0,50));
notice_for_2d->set_autowrap(true);
add_child(notice_for_2d);
notice_for_2d->hide();
}
@ -242,8 +240,13 @@ class EditorTextureImportDialog : public ConfirmationDialog {
OBJ_TYPE(EditorTextureImportDialog,ConfirmationDialog);
HBoxContainer *mode_hb;
CheckBox *mode_check[EditorTextureImportPlugin::MODE_MAX];
EditorImportTextureOptions *texture_options;
EditorTextureImportPlugin::Mode mode;
//EditorNode *editor;
LineEdit *import_path;
@ -255,11 +258,16 @@ class EditorTextureImportDialog : public ConfirmationDialog {
ConfirmationDialog *error_dialog;
CheckButton *crop_source;
SpinBox *size;
bool atlas;
bool large;
MarginContainer *size_mc;
Label* size_label;
Label* source_label;
Label *notice_for_2d;
EditorTextureImportPlugin *plugin;
void _mode_changed(int p_mode);
void _choose_files(const Vector<String>& p_path);
void _choose_file(const String& p_path);
void _choose_save_dir(const String& p_path);
@ -274,9 +282,23 @@ protected:
static void _bind_methods();
public:
void setup_multiple_import_3d(const Vector<String>& p_path,const String& p_dest) {
_mode_changed(EditorTextureImportPlugin::MODE_TEXTURE_3D);
_choose_files(p_path);
_choose_save_dir(p_dest);
}
void add_sources_and_dest(const Vector<String>& p_path,const String& p_dest) {
_choose_files(p_path);
_choose_save_dir(p_dest);
}
Error import(const String& p_from, const String& p_to, const String& p_preset);
void popup_import(const String &p_from=String());
EditorTextureImportDialog(EditorTextureImportPlugin *p_plugin=NULL,bool p_2d=false,bool p_atlas=false,bool p_large=false);
EditorTextureImportDialog(EditorTextureImportPlugin *p_plugin=NULL);
};
@ -349,13 +371,13 @@ void EditorTextureImportDialog::_import() {
}
if (!atlas && !large && !DirAccess::exists(save_path->get_text())) {
if (mode!=EditorTextureImportPlugin::MODE_ATLAS && mode!=EditorTextureImportPlugin::MODE_LARGE && !DirAccess::exists(save_path->get_text())) {
error_dialog->set_text(TTR("Target path must exist."));
error_dialog->popup_centered_minsize();
return;
}
if (atlas) { //atlas
if (mode==EditorTextureImportPlugin::MODE_ATLAS) { //atlas
if (files.size()==0) {
@ -378,6 +400,7 @@ void EditorTextureImportDialog::_import() {
imd->set_option("atlas_size",int(size->get_val()));
imd->set_option("large",false);
imd->set_option("crop",crop_source->is_pressed());
imd->set_option("mode",mode);
Error err = plugin->import(dst_file,imd);
if (err) {
@ -387,7 +410,7 @@ void EditorTextureImportDialog::_import() {
return;
}
} else if (large) { //atlas
} else if (mode==EditorTextureImportPlugin::MODE_LARGE) { //large
if (files.size()!=1) {
@ -410,6 +433,7 @@ void EditorTextureImportDialog::_import() {
imd->set_option("large",true);
imd->set_option("large_cell_size",int(size->get_val()));
imd->set_option("crop",crop_source->is_pressed());
imd->set_option("mode",mode);
Error err = plugin->import(dst_file,imd);
if (err) {
@ -434,6 +458,7 @@ void EditorTextureImportDialog::_import() {
imd->set_option("quality",texture_options->get_quality());
imd->set_option("atlas",false);
imd->set_option("large",false);
imd->set_option("mode",mode);
Error err = plugin->import(dst_file,imd);
if (err) {
@ -456,7 +481,7 @@ void EditorTextureImportDialog::_browse() {
void EditorTextureImportDialog::_browse_target() {
if (atlas || large) {
if (mode==EditorTextureImportPlugin::MODE_ATLAS || mode==EditorTextureImportPlugin::MODE_LARGE) {
save_file_select->popup_centered_ratio();
} else {
save_select->popup_centered_ratio();
@ -467,12 +492,28 @@ void EditorTextureImportDialog::_browse_target() {
void EditorTextureImportDialog::popup_import(const String& p_from) {
popup_centered(Size2(400,400));
popup_centered(Size2(600,500));
if (p_from!="") {
Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
ERR_FAIL_COND(!rimd.is_valid());
if (plugin->get_mode()==EditorTextureImportPlugin::MODE_ATLAS || plugin->get_mode()==EditorTextureImportPlugin::MODE_LARGE)
if (rimd->has_option("mode")) {
//new imported stuff uses this option
_mode_changed(rimd->get_option("mode"));
} else {
//this one is for compatibility, will have to guess it
if (rimd->has_option("atlas") && rimd->get_option("atlas")) {
_mode_changed(EditorTextureImportPlugin::MODE_ATLAS);
} else if (rimd->has_option("large") && rimd->get_option("large")) {
_mode_changed(EditorTextureImportPlugin::MODE_LARGE);
} else {
//guess by usage of mipmaps..?
_mode_changed(EditorTextureImportPlugin::MODE_TEXTURE_2D);
}
}
if (mode==EditorTextureImportPlugin::MODE_ATLAS || mode==EditorTextureImportPlugin::MODE_LARGE)
save_path->set_text(p_from);
else
save_path->set_text(p_from.get_base_dir());
@ -518,6 +559,81 @@ Error EditorTextureImportDialog::import(const String& p_from, const String& p_to
return OK;
}
void EditorTextureImportDialog::_mode_changed(int p_mode) {
mode = EditorTextureImportPlugin::Mode(p_mode);
for(int i=0;i<EditorTextureImportPlugin::MODE_MAX;i++) {
mode_check[i]->set_pressed(i==mode);
}
if (p_mode==EditorTextureImportPlugin::MODE_ATLAS) {
size_label->set_text(TTR("Max Texture Size:"));
size->set_val(2048);
crop_source->show();
size_label->show();
size->show();
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
texture_options->set_quality(0.7);
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
set_title(TTR("Import Textures for Atlas (2D)"));
} else {
crop_source->hide();
}
if (p_mode==EditorTextureImportPlugin::MODE_LARGE) {
size_label->set_text(TTR("Cell Size:"));
size->set_val(256);
size_label->show();
size->show();
file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
save_file_select->add_filter("*.ltex;"+TTR("Large Texture"));
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
texture_options->set_quality(0.7);
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS);
set_title(TTR("Import Large Textures (2D)"));
source_label->set_text(TTR("Source Texture"));
} else {
file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
save_file_select->add_filter("*.tex;"+TTR("Base Atlas Texture"));
source_label->set_text(TTR("Source Texture(s)"));
}
if (p_mode==EditorTextureImportPlugin::MODE_TEXTURE_2D) {
size_label->hide();
size->hide();
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
texture_options->set_quality(0.7);
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
notice_for_2d->show();
set_title(TTR("Import Textures for 2D"));
} else {
notice_for_2d->hide();
}
if (p_mode==EditorTextureImportPlugin::MODE_TEXTURE_3D) {
size_label->hide();
size->hide();
//texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_);
//texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS);
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_FILTER|EditorTextureImportPlugin::IMAGE_FLAG_REPEAT);
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM);
set_title(TTR("Import Textures for 3D"));
}
}
void EditorTextureImportDialog::_bind_methods() {
@ -527,28 +643,64 @@ void EditorTextureImportDialog::_bind_methods() {
ObjectTypeDB::bind_method("_import",&EditorTextureImportDialog::_import);
ObjectTypeDB::bind_method("_browse",&EditorTextureImportDialog::_browse);
ObjectTypeDB::bind_method("_browse_target",&EditorTextureImportDialog::_browse_target);
ObjectTypeDB::bind_method("_mode_changed",&EditorTextureImportDialog::_mode_changed);
// ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
}
EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* p_plugin, bool p_2d, bool p_atlas,bool p_large) {
EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* p_plugin) {
atlas=p_atlas;
large=p_large;
plugin=p_plugin;
set_title(TTR("Import Textures"));
mode_hb = memnew( HBoxContainer );
add_child(mode_hb);
set_child_rect(mode_hb);
VBoxContainer *vbcg = memnew( VBoxContainer);
mode_hb->add_child(vbcg);
mode_hb->add_constant_override("separation",15);
ButtonGroup *bg = memnew( ButtonGroup );
vbcg->add_margin_child("Import Mode",bg);
for(int i=0;i<EditorTextureImportPlugin::MODE_MAX;i++) {
String mode_name[EditorTextureImportPlugin::MODE_MAX]={
TTR("2D Texture"),
TTR("3D Texture"),
TTR("Atlas Texture"),
TTR("Large Texture")
};
mode_check[i]=memnew(CheckBox);
bg->add_child(mode_check[i]);
mode_check[i]->set_text(mode_name[i]);
mode_check[i]->connect("pressed",this,"_mode_changed",varray(i));
}
VBoxContainer *vbc = memnew(VBoxContainer);
add_child(vbc);
set_child_rect(vbc);
mode_hb->add_child(vbc);
vbc->set_h_size_flags(SIZE_EXPAND_FILL);
vbc->add_constant_override("separation",4);
notice_for_2d = memnew( Label );
notice_for_2d->set_text(TTR("NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to the project."));
//notice_for_2d->set_custom_minimum_size(Size2(0,50));
notice_for_2d->set_autowrap(true);
notice_for_2d->hide();
vbcg->add_child(notice_for_2d);
notice_for_2d->set_v_size_flags(SIZE_EXPAND_FILL);
notice_for_2d->set_valign(Label::VALIGN_BOTTOM);
VBoxContainer *source_vb=memnew(VBoxContainer);
if (large)
vbc->add_margin_child(TTR("Source Texture:"),source_vb);
else
vbc->add_margin_child(TTR("Source Texture(s):"),source_vb);
MarginContainer *source_mc = vbc->add_margin_child(TTR("Source Texture(s):"),source_vb);
source_label = vbc->get_child(source_mc->get_index()-1)->cast_to<Label>();
HBoxContainer *hbc = memnew( HBoxContainer );
source_vb->add_child(hbc);
@ -560,8 +712,6 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin*
crop_source->set_pressed(true);
source_vb->add_child(crop_source);
crop_source->set_text(TTR("Crop empty space."));
if (!p_atlas)
crop_source->hide();
Button * import_choose = memnew( Button );
@ -577,13 +727,10 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin*
size->set_min(128);
size->set_max(16384);
if (p_atlas) {
size->set_val(2048);
vbc->add_margin_child(TTR("Max Texture Size:"),size);
} else {
size->set_val(256);
vbc->add_margin_child(TTR("Cell Size:"),size);
}
size_mc=vbc->add_margin_child(TTR("Cell Size:"),size);
size_label=vbc->get_child(size_mc->get_index()-1)->cast_to<Label>();
save_path = memnew( LineEdit );
@ -599,10 +746,7 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin*
file_select = memnew(EditorFileDialog);
file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
add_child(file_select);
if (!large)
file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
else
file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
file_select->connect("files_selected", this,"_choose_files");
file_select->connect("file_selected", this,"_choose_file");
@ -611,10 +755,7 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin*
add_child(save_file_select);
save_file_select->set_mode(EditorFileDialog::MODE_SAVE_FILE);
save_file_select->clear_filters();
if (large)
save_file_select->add_filter("*.ltex;"+TTR("Large Texture"));
else
save_file_select->add_filter("*.tex;"+TTR("Base Atlas Texture"));
save_file_select->connect("file_selected", this,"_choose_save_dir");
save_select = memnew( EditorDirDialog );
@ -641,36 +782,7 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin*
vbc->add_child(texture_options);
texture_options->set_v_size_flags(SIZE_EXPAND_FILL);
if (atlas) {
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
texture_options->set_quality(0.7);
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
//texture_options->show_2d_notice();
set_title(TTR("Import Textures for Atlas (2D)"));
} else if (large) {
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
texture_options->set_quality(0.7);
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS);
texture_options->show_2d_notice();
set_title(TTR("Import Large Textures (2D)"));
} else if (p_2d) {
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
texture_options->set_quality(0.7);
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
texture_options->show_2d_notice();
set_title(TTR("Import Textures for 2D"));
} else {
//texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_);
//texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS);
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_FILTER|EditorTextureImportPlugin::IMAGE_FLAG_REPEAT);
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM);
set_title(TTR("Import Textures for 3D"));
}
_mode_changed(EditorTextureImportPlugin::MODE_TEXTURE_3D);
// GLOBAL_DEF("import/shared_textures","res://");
@ -686,6 +798,8 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin*
String EditorTextureImportPlugin::get_name() const {
return "texture";
#if 0 //old names, kept for compatibility reference
switch(mode) {
case MODE_TEXTURE_2D: {
@ -707,34 +821,14 @@ String EditorTextureImportPlugin::get_name() const {
}
return "";
return "";
#endif
}
String EditorTextureImportPlugin::get_visible_name() const {
switch(mode) {
case MODE_TEXTURE_2D: {
return "2D Texture";
} break;
case MODE_TEXTURE_3D: {
return "3D Texture";
} break;
case MODE_ATLAS: {
return "2D Atlas Texture";
} break;
case MODE_LARGE: {
return "2D Large Texture";
} break;
}
return "";
return "Texture";
}
void EditorTextureImportPlugin::import_dialog(const String& p_from) {
@ -1626,15 +1720,93 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c
return ret;
}
void EditorTextureImportPlugin::import_from_drop(const Vector<String>& p_drop,const String& p_dest_path) {
EditorTextureImportPlugin *EditorTextureImportPlugin::singleton[EditorTextureImportPlugin::MODE_MAX]={NULL,NULL,NULL,NULL};
Vector<String> valid;
EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor, Mode p_mode) {
List<String> valid_extensions;
ImageLoader::get_recognized_extensions(&valid_extensions);
for(int i=0;i<p_drop.size();i++) {
singleton[p_mode]=this;
String extension=p_drop[i].extension().to_lower();
for (List<String>::Element *E=valid_extensions.front();E;E=E->next()) {
if (E->get()==extension) {
valid.push_back(p_drop[i]);
break;
}
}
}
if (valid.size()) {
dialog->popup_import();
dialog->setup_multiple_import_3d(valid,p_dest_path);
}
}
void EditorTextureImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
Vector<String> valid;
bool warning=false;
for(int i=0;i<p_list.size();i++) {
Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_list[i]);
String type = rimd->get_editor();
if (type=="texture" || type.begins_with("texture_")) {
if ((rimd->has_option("atlas") && rimd->get_option("atlas")) || (rimd->has_option("large") && rimd->get_option("large"))) {
warning=true;
continue;
}
valid.push_back(p_list[i]);
}
}
if (valid.size()) {
dialog->popup_import(valid[0]);
Vector<String> sources;
for(int i=0;i<valid.size();i++) {
int idx;
EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(valid[i],&idx);
if (efsd) {
for(int j=0;j<efsd->get_source_count(idx);j++) {
String file = expand_source_path(efsd->get_source_file(idx,j));
if (sources.find(file)==-1) {
sources.push_back(file);
}
}
}
}
if (sources.size()) {
dialog->add_sources_and_dest(sources,valid[0].get_base_dir());
}
}
}
bool EditorTextureImportPlugin::can_reimport_multiple_files() const {
return true;
}
EditorTextureImportPlugin *EditorTextureImportPlugin::singleton=NULL;
EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor) {
singleton=this;
editor=p_editor;
mode=p_mode;
dialog = memnew( EditorTextureImportDialog(this,p_mode==MODE_TEXTURE_2D || p_mode==MODE_ATLAS || p_mode==MODE_LARGE,p_mode==MODE_ATLAS,p_mode==MODE_LARGE) );
dialog = memnew( EditorTextureImportDialog(this) );
editor->get_gui_base()->add_child(dialog);
}

View File

@ -64,10 +64,10 @@ public:
private:
Mode mode;
EditorNode *editor;
EditorTextureImportDialog *dialog;
static EditorTextureImportPlugin *singleton[MODE_MAX];
static EditorTextureImportPlugin *singleton;
//used by other importers such as mesh
Error _process_texture_data(Ref<ImageTexture> &texture, int format, float quality, int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink);
@ -75,7 +75,7 @@ private:
public:
static EditorTextureImportPlugin *get_singleton(Mode p_mode) { return singleton[p_mode]; }
static EditorTextureImportPlugin *get_singleton() { return singleton; }
enum ImageFormat {
@ -100,7 +100,6 @@ public:
IMAGE_FLAG_USE_ANISOTROPY=1024, //convert image to linear
};
Mode get_mode() const { return mode; }
virtual String get_name() const;
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
@ -108,8 +107,11 @@ public:
virtual Error import2(const String& p_path, const Ref<ResourceImportMetadata>& p_from,EditorExportPlatform::ImageCompression p_compr, bool p_external=false);
virtual Vector<uint8_t> custom_export(const String& p_path,const Ref<EditorExportPlatform> &p_platform);
virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
virtual void reimport_multiple_files(const Vector<String>& p_list);
virtual bool can_reimport_multiple_files() const;
EditorTextureImportPlugin(EditorNode* p_editor=NULL,Mode p_mode=MODE_TEXTURE_2D);
EditorTextureImportPlugin(EditorNode* p_editor=NULL);
};
@ -134,7 +136,7 @@ class EditorImportTextureOptions : public VBoxContainer {
HSlider *quality;
Tree *flags;
Vector<TreeItem*> items;
Label *notice_for_2d;
bool updating;

View File

@ -394,6 +394,26 @@ void EditorTranslationImportPlugin::import_dialog(const String& p_from) {
dialog->popup_import(p_from);
}
void EditorTranslationImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
for(int i=0;i<p_drop.size();i++) {
String ext = p_drop[i].extension().to_lower();
if (ext=="csv") {
import_dialog();
dialog->_choose_file(p_drop[i]);
dialog->_choose_save_dir(p_dest_path);
break;
}
}
}
Error EditorTranslationImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from) {
Ref<ResourceImportMetadata> from = p_from;

View File

@ -46,6 +46,7 @@ public:
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
EditorTranslationImportPlugin(EditorNode* p_editor);

View File

@ -71,6 +71,22 @@ void MeshEditor::edit(Ref<Mesh> p_mesh) {
rot_x=0;
rot_y=0;
_update_rotation();
AABB aabb= mesh->get_aabb();
Vector3 ofs = aabb.pos + aabb.size*0.5;
aabb.pos-=ofs;
float m = MAX(aabb.size.x,aabb.size.y)*0.5;
if (m!=0) {
m=1.0/m;
m*=0.5;
//print_line("scale: "+rtos(m));
Transform xform;
xform.basis.scale(Vector3(m,m,m));
xform.origin=-xform.basis.xform(ofs); //-ofs*m;
xform.origin.z-=aabb.size.z*2;
mesh_instance->set_transform(xform);
}
}
}

View File

@ -1673,6 +1673,7 @@ void CustomPropertyEditor::config_value_editors(int p_amount, int p_columns,int
}
void CustomPropertyEditor::_bind_methods() {
ObjectTypeDB::bind_method("_focus_enter", &CustomPropertyEditor::_focus_enter);
@ -1691,6 +1692,7 @@ void CustomPropertyEditor::_bind_methods() {
ObjectTypeDB::bind_method( "_menu_option",&CustomPropertyEditor::_menu_option);
ADD_SIGNAL( MethodInfo("variant_changed") );
ADD_SIGNAL( MethodInfo("resource_edit_request") );
}
@ -2180,6 +2182,11 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p
}
}
if (!res->is_type("Texture")) {
//texture already previews via itself
EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res,this,"_resource_preview_done",p_item->get_instance_ID());
}
}
@ -3357,6 +3364,10 @@ void PropertyEditor::update_tree() {
} else if (res.is_valid()) {
item->set_tooltip(1,res->get_name()+" ("+res->get_type()+")");
}
if (!res->is_type("Texture")) {
//texture already previews via itself
EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res,this,"_resource_preview_done",item->get_instance_ID());
}
}
@ -3870,6 +3881,29 @@ void PropertyEditor::_filter_changed(const String& p_text) {
update_tree();
}
void PropertyEditor::_resource_preview_done(const String& p_path,const Ref<Texture>& p_preview,Variant p_ud) {
if (p_preview.is_null())
return; //don't bother with empty preview
ObjectID id = p_ud;
Object *obj = ObjectDB::get_instance(id);
if (!obj)
return;
TreeItem *ti = obj->cast_to<TreeItem>();
ERR_FAIL_COND(!ti);
int tw = EditorSettings::get_singleton()->get("property_editor/texture_preview_width");
ti->set_icon(1,p_preview); //should be scaled I think?
ti->set_icon_max_width(1,tw);
ti->set_text(1,"");
}
void PropertyEditor::_bind_methods() {
ObjectTypeDB::bind_method( "_item_edited",&PropertyEditor::_item_edited);
@ -3884,6 +3918,7 @@ void PropertyEditor::_bind_methods() {
ObjectTypeDB::bind_method( "_set_range_def",&PropertyEditor::_set_range_def);
ObjectTypeDB::bind_method( "_filter_changed",&PropertyEditor::_filter_changed);
ObjectTypeDB::bind_method( "update_tree",&PropertyEditor::update_tree);
ObjectTypeDB::bind_method( "_resource_preview_done",&PropertyEditor::_resource_preview_done);
ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &PropertyEditor::get_drag_data_fw);
ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &PropertyEditor::can_drop_data_fw);

View File

@ -131,6 +131,7 @@ class CustomPropertyEditor : public Popup {
void config_value_editors(int p_amount, int p_columns,int p_label_w,const List<String>& p_strings);
void config_action_buttons(const List<String>& p_strings);
protected:
void _notification(int p_what);
@ -231,6 +232,7 @@ class PropertyEditor : public Control {
bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
void _resource_preview_done(const String& p_path,const Ref<Texture>& p_preview,Variant p_ud);
UndoRedo *undo_redo;
protected:

View File

@ -542,6 +542,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
} break;
case TOOL_MERGE_FROM_SCENE: {
EditorNode::get_singleton()->merge_from_scene();
} break;
case TOOL_NEW_SCENE_FROM: {
Node *scene = editor_data->get_edited_scene_root();
@ -1696,6 +1700,7 @@ void SceneTreeDock::_tree_rmb(const Vector2& p_menu_pos) {
if (selection.size()==1) {
menu->add_separator();
menu->add_item(TTR("Merge From Scene"),TOOL_MERGE_FROM_SCENE);
menu->add_item(TTR("Save Branch as Scene"),TOOL_NEW_SCENE_FROM);
}
menu->add_separator();

View File

@ -64,6 +64,7 @@ class SceneTreeDock : public VBoxContainer {
TOOL_DUPLICATE,
TOOL_REPARENT,
TOOL_NEW_SCENE_FROM,
TOOL_MERGE_FROM_SCENE,
TOOL_MULTI_EDIT,
TOOL_ERASE,
TOOL_BUTTON_MAX

View File

@ -326,6 +326,10 @@ String ScenesDock::get_selected_path() const {
return "res://"+path;
}
String ScenesDock::get_current_path() const {
return path;
}
void ScenesDock::_thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) {
@ -388,6 +392,25 @@ void ScenesDock::_search(EditorFileSystemDirectory *p_path,List<FileInfo>* match
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);
}
matches->push_back(fi);
if (matches->size()>p_max_items)
return;
@ -517,6 +540,27 @@ void ScenesDock::_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;
}
filelist.push_back(fi);
}
@ -533,11 +577,32 @@ void ScenesDock::_update_files(bool p_keep_selection) {
Ref<Texture> type_icon;
String tooltip=fname;
if (E->get().import_status==0) {
if (has_icon(type,ei)) {
type_icon=get_icon(type,ei);
} else {
type_icon=get_icon(oi,ei);
}
} else if (E->get().import_status==1) {
type_icon=get_icon("DependencyOk","EditorIcons");
} else if (E->get().import_status==2) {
type_icon=get_icon("DependencyChanged","EditorIcons");
tooltip+"\nStatus: Needs Re-Import";
} else if (E->get().import_status==3) {
type_icon=get_icon("ImportFail","EditorIcons");
tooltip+"\nStatus: Missing Dependencies";
}
if (E->get().sources.size()) {
for(int i=0;i<E->get().sources.size();i++) {
tooltip+="\nSource: "+E->get().sources[i];
}
}
if (use_thumbnails) {
files->add_item(fname,file_thumbnail,true);
@ -557,6 +622,9 @@ void ScenesDock::_update_files(bool p_keep_selection) {
if (cselection.has(fname))
files->select(files->get_item_count()-1,false);
files->set_item_tooltip(files->get_item_count()-1,tooltip);
}
@ -997,6 +1065,40 @@ void ScenesDock::_file_option(int p_option) {
case FILE_INFO: {
} break;
case FILE_REIMPORT: {
Vector<String> reimport;
for(int i=0;i<files->get_item_count();i++) {
if (!files->is_selected(i))
continue;
String path = files->get_item_metadata(i);
reimport.push_back(path);
}
ERR_FAIL_COND(reimport.size()==0);
Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(reimport[0]);
ERR_FAIL_COND(!rimd.is_valid());
String editor=rimd->get_editor();
if (editor.begins_with("texture_")) { //compatibility fix for old texture format
editor="texture";
}
Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(editor);
ERR_FAIL_COND(!rimp.is_valid());
if (reimport.size()==1) {
rimp->import_dialog(reimport[0]);
} else {
rimp->reimport_multiple_files(reimport);
}
} break;
}
}
@ -1362,6 +1464,8 @@ void ScenesDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) {
Vector<String> filenames;
bool all_scenes=true;
bool all_can_reimport=true;
Set<String> types;
for(int i=0;i<files->get_item_count();i++) {
@ -1381,6 +1485,38 @@ void ScenesDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) {
}
EditorFileSystemDirectory *efsd=NULL;
int pos;
efsd = EditorFileSystem::get_singleton()->find_file(path,&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;
}
filenames.push_back(path);
if (EditorFileSystem::get_singleton()->get_file_type(path)!="PackedScene")
all_scenes=false;
@ -1412,12 +1548,34 @@ void ScenesDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) {
file_options->add_item(TTR("Move To.."),FILE_MOVE);
}
file_options->add_item(TTR("Delete"),FILE_REMOVE);
//file_options->add_item(TTR("Info"),FILE_INFO);
file_options->add_separator();
file_options->add_item(TTR("Show In File Manager"),FILE_SHOW_IN_EXPLORER);
if (all_can_reimport && types.size()==1) { //all can reimport and are of the same type
bool valid=true;
Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(types.front()->get());
if (rimp.is_valid()) {
if (filenames.size()>1 && !rimp->can_reimport_multiple_files()) {
valid=false;
}
} else {
valid=false;
}
if (valid) {
file_options->add_separator();
file_options->add_item(TTR("Re-Import.."),FILE_REIMPORT);
}
}
file_options->set_pos(files->get_global_pos() + p_pos);
file_options->popup();

View File

@ -153,6 +153,8 @@ class ScenesDock : public VBoxContainer {
String name;
String path;
StringName type;
int import_status; //0 not imported, 1 - ok, 2- must reimport, 3- broken
Vector<String> sources;
bool operator<(const FileInfo& fi) const {
return name < fi.name;
@ -171,6 +173,8 @@ protected:
public:
String get_selected_path() const;
String get_current_path() const;
void focus_on_filter();
void fix_dependencies(const String& p_for_file);