diff --git a/projectfiles_vc9/blender/loader/BLO_loader.vcproj b/projectfiles_vc9/blender/loader/BLO_loader.vcproj index a8cec5ecf76..e8b155875d0 100644 --- a/projectfiles_vc9/blender/loader/BLO_loader.vcproj +++ b/projectfiles_vc9/blender/loader/BLO_loader.vcproj @@ -469,123 +469,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/release/io/export_ply.py b/release/io/export_ply.py index c293119d3c8..7a3253b2d16 100644 --- a/release/io/export_ply.py +++ b/release/io/export_ply.py @@ -242,7 +242,7 @@ class EXPORT_OT_ply(bpy.types.Operator): # to the class instance from the operator settings before calling. __props__ = [ - bpy.props.StringProperty(attr="filename", name="File Name", description="File name used for exporting the PLY file", maxlen= 1024, default= ""), + bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""), bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True), bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True), bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True), diff --git a/release/ui/space_info.py b/release/ui/space_info.py index 97243f857a6..6b2a457e89d 100644 --- a/release/ui/space_info.py +++ b/release/ui/space_info.py @@ -59,6 +59,9 @@ class INFO_MT_file(bpy.types.Menu): layout.itemO("wm.save_as_mainfile", text="Save As...") layout.itemO("screen.userpref_show", text="User Preferences...") + layout.itemS() + layout.operator_context = "INVOKE_AREA" + layout.itemO("wm.link_append", text="Append or Link") layout.itemS() layout.itemM("INFO_MT_file_import") diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 54722dac910..0e978128cf6 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -77,6 +77,7 @@ void IPOnames_to_pupstring(char **str, char *title, char *extraops, struct ListB void flag_listbase_ids(ListBase *lb, short flag, short value); void flag_all_listbases_ids(short flag, short value); +void recalc_all_library_objects(struct Main *main); void set_free_windowmanager_cb(void (*func)(struct bContext *, struct wmWindowManager *) ); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 02d92a62b59..da7692d0cdb 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -455,6 +455,17 @@ void flag_all_listbases_ids(short flag, short value) while(a--) flag_listbase_ids(lbarray[a], flag, value); } +void recalc_all_library_objects(struct Main *main) +{ + /* DISPLISTS? */ + Object *ob= main->object.first; + while(ob) { + if(ob->id.lib) { + ob->recalc |= OB_RECALC; + } + ob= ob->id.next; + } +} /* note: MAX_LIBARRAY define should match this code */ int set_listbasepointers(Main *main, ListBase **lb) diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 4fafac29a6f..6e2772efea4 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -36,7 +36,6 @@ extern "C" { struct bScreen; struct direntry; -struct FileList; struct LinkNode; struct Main; struct MemFile; @@ -45,6 +44,7 @@ struct Scene; struct SpaceFile; struct SpaceImaSel; struct UserDef; +struct bContext; typedef struct BlendHandle BlendHandle; @@ -197,12 +197,23 @@ BLO_blendhandle_close( /***/ -char *BLO_gethome(void); +#define GROUP_MAX 32 + int BLO_has_bfile_extension(char *str); -void BLO_library_append(BlendHandle **libfiledata, struct direntry* filelist, int totfile, - char *dir, char* file, short flag, int idcode, struct Main *mainvar, struct Scene *scene, struct ReportList *reports); +/* return ok when a blenderfile, in dir is the filename, + * in group the type of libdata + */ +int BLO_is_a_library(char *path, char *dir, char *group); + +struct Main* BLO_library_append_begin(const struct bContext *C, BlendHandle** bh, char *dir); +void BLO_library_append_named_part(const struct bContext *C, struct Main *mainl, BlendHandle** bh, char *name, int idcode, short flag); +void BLO_library_append_end(const struct bContext *C, struct Main *mainl, BlendHandle** bh, int idcode, short flag); + +/* deprecated */ +#if 0 void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Main *mainvar, struct Scene *scene, struct ReportList *reports); +#endif BlendFileData* blo_read_blendafterruntime(int file, char *name, int actualsize, struct ReportList *reports); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 99285fefb4d..83abd5c2b4d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -113,6 +113,7 @@ #include "BKE_cloth.h" #include "BKE_colortools.h" #include "BKE_constraint.h" +#include "BKE_context.h" #include "BKE_curve.h" #include "BKE_customdata.h" #include "BKE_deform.h" @@ -1065,6 +1066,46 @@ int BLO_has_bfile_extension(char *str) return (BLI_testextensie(str, ".ble") || BLI_testextensie(str, ".blend")||BLI_testextensie(str, ".blend.gz")); } +int BLO_is_a_library(char *path, char *dir, char *group) +{ + /* return ok when a blenderfile, in dir is the filename, + * in group the type of libdata + */ + int len; + char *fd; + + strcpy(dir, path); + len= strlen(dir); + if(len<7) return 0; + if( dir[len-1] != '/' && dir[len-1] != '\\') return 0; + + group[0]= 0; + dir[len-1]= 0; + + /* Find the last slash */ + fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\'); + + if(fd==0) return 0; + *fd= 0; + if(BLO_has_bfile_extension(fd+1)) { + /* the last part of the dir is a .blend file, no group follows */ + *fd= '/'; /* put back the removed slash separating the dir and the .blend file name */ + } + else { + char *gp = fd+1; // in case we have a .blend file, gp points to the group + + /* Find the last slash */ + fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\'); + if (!fd || !BLO_has_bfile_extension(fd+1)) return 0; + + /* now we know that we are in a blend file and it is safe to + assume that gp actually points to a group */ + if (BLI_streq("Screen", gp)==0) + BLI_strncpy(group, gp, GROUP_MAX); + } + return 1; +} + /* ************** OLD POINTERS ******************* */ static void *newdataadr(FileData *fd, void *adr) /* only direct databocks */ @@ -10729,8 +10770,9 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, int is } -static void append_named_part(FileData *fd, Main *mainvar, Scene *scene, char *name, int idcode, short flag) +static void append_named_part(const bContext *C, Main *mainl, FileData *fd, char *name, int idcode, short flag) { + Scene *scene= CTX_data_scene(C); Object *ob; Base *base; BHead *bhead; @@ -10746,9 +10788,9 @@ static void append_named_part(FileData *fd, Main *mainvar, Scene *scene, char *n if(strcmp(idname+2, name)==0) { - id= is_yet_read(fd, mainvar, bhead); + id= is_yet_read(fd, mainl, bhead); if(id==NULL) { - read_libblock(fd, mainvar, bhead, LIB_TESTEXT, NULL); + read_libblock(fd, mainl, bhead, LIB_TESTEXT, NULL); } else { printf("append: already linked\n"); @@ -10763,13 +10805,18 @@ static void append_named_part(FileData *fd, Main *mainvar, Scene *scene, char *n base= MEM_callocN( sizeof(Base), "app_nam_part"); BLI_addtail(&scene->base, base); - if(id==NULL) ob= mainvar->object.last; + if(id==NULL) ob= mainl->object.last; else ob= (Object *)id; - /* XXX use context to find view3d->lay */ - //if((flag & FILE_ACTIVELAY)) { - // scene->lay; - //} + /* link at active layer (view3d->lay if in context, else scene->lay */ + if((flag & FILE_ACTIVELAY)) { + View3D *v3d = CTX_wm_view3d(C); + if (v3d) { + ob->lay = v3d->layact; + } else { + ob->lay = scene->lay; + } + } base->lay= ob->lay; base->object= ob; ob->id.us++; @@ -10788,6 +10835,12 @@ static void append_named_part(FileData *fd, Main *mainvar, Scene *scene, char *n } } +void BLO_library_append_named_part(const bContext *C, Main *mainl, BlendHandle** bh, char *name, int idcode, short flag) +{ + FileData *fd= (FileData*)(*bh); + append_named_part(C, mainl, fd, name, idcode, flag); +} + static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r) { BHead *bhead; @@ -10810,11 +10863,10 @@ static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r) /* common routine to append/link something from a library */ -static Library* library_append(Main *mainvar, Scene *scene, char* file, char *dir, int idcode, - int totsel, FileData **fd, struct direntry* filelist, int totfile, short flag) +static Main* library_append_begin(const bContext *C, FileData **fd, char *dir) { + Main *mainvar= CTX_data_main(C); Main *mainl; - Library *curlib; /* make mains */ blo_split_main(&(*fd)->mainlist, mainvar); @@ -10824,19 +10876,69 @@ static Library* library_append(Main *mainvar, Scene *scene, char* file, char *di mainl->versionfile= (*fd)->fileversion; /* needed for do_version */ - curlib= mainl->curlib; + return mainl; +} + +Main* BLO_library_append_begin(const bContext *C, BlendHandle** bh, char *dir) +{ + FileData *fd= (FileData*)(*bh); + return library_append_begin(C, &fd, dir); +} + +static void append_do_cursor(Scene *scene, Library *curlib, short flag) +{ + Base *centerbase; + Object *ob; + float *curs, centerloc[3], vec[3], min[3], max[3]; + int count= 0; + + /* when not linking (appending)... */ + if(flag & FILE_LINK) + return; + + /* we're not appending at cursor */ + if((flag & FILE_ATCURSOR) == 0) + return; - if(totsel==0) { - append_named_part(*fd, mainl, scene, file, idcode, flag); - } - else { - int a; - for(a=0; abase.first); + while(centerbase) { + if(centerbase->object->id.lib==curlib && centerbase->object->parent==NULL) { + VECCOPY(vec, centerbase->object->loc); + DO_MINMAX(vec, min, max); + count++; } + centerbase= centerbase->next; } + /* we haven't found any objects to move to cursor */ + if(!count) + return; + + /* move from the center of the appended objects to cursor */ + centerloc[0]= (min[0]+max[0])/2; + centerloc[1]= (min[1]+max[1])/2; + centerloc[2]= (min[2]+max[2])/2; + curs = scene->cursor; + VECSUB(centerloc,curs,centerloc); + + /* now translate the center of the objects */ + centerbase= (scene->base.first); + while(centerbase) { + if(centerbase->object->id.lib==curlib && centerbase->object->parent==NULL) { + ob= centerbase->object; + ob->loc[0] += centerloc[0]; + ob->loc[1] += centerloc[1]; + ob->loc[2] += centerloc[2]; + } + centerbase= centerbase->next; + } +} + +static void library_append_end(const bContext *C, Main *mainl, FileData **fd, int idcode, short flag) +{ + Main *mainvar= CTX_data_main(C); + Scene *scene= CTX_data_scene(C); /* make main consistant */ expand_main(*fd, mainl); @@ -10844,6 +10946,7 @@ static Library* library_append(Main *mainvar, Scene *scene, char* file, char *di /* do this when expand found other libs */ read_libraries(*fd, &(*fd)->mainlist); + /* make the lib path relative if required */ if(flag & FILE_STRINGCODE) { /* use the full path, this could have been read by other library even */ @@ -10866,7 +10969,7 @@ static Library* library_append(Main *mainvar, Scene *scene, char* file, char *di if (flag & FILE_LINK) { give_base_to_objects(mainvar, scene, NULL, 0); } else { - give_base_to_objects(mainvar, scene, curlib, 1); + give_base_to_objects(mainvar, scene, mainl->curlib, 1); } } else { give_base_to_objects(mainvar, scene, NULL, 0); @@ -10882,14 +10985,23 @@ static Library* library_append(Main *mainvar, Scene *scene, char* file, char *di *fd = NULL; } - return curlib; + append_do_cursor(scene, mainl->curlib, flag); +} + +void BLO_library_append_end(const bContext *C, struct Main *mainl, BlendHandle** bh, int idcode, short flag) +{ + FileData *fd= (FileData*)(*bh); + library_append_end(C, mainl, &fd, idcode, flag); + *bh= (BlendHandle*)fd; } /* this is a version of BLO_library_append needed by the BPython API, so * scripts can load data from .blend files -- see Blender.Library module.*/ /* append to scene */ /* this should probably be moved into the Python code anyway */ - +/* tentatively removed, Python should be able to use the split functions too: */ +/* BLO_library_append_begin, BLO_library_append_end, BLO_library_append_named_part */ +#if 0 void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, Main *mainvar, Scene *scene, ReportList *reports) { @@ -10906,88 +11018,7 @@ void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, *bh= (BlendHandle*)fd; } - -/* append to scene */ -void BLO_library_append(BlendHandle** bh, struct direntry* filelist, int totfile, - char *dir, char* file, short flag, int idcode, Main *mainvar, Scene *scene, ReportList *reports) -{ - FileData *fd= (FileData*)(*bh); - Library *curlib; - Base *centerbase; - Object *ob; - int a, totsel=0; - - /* are there files selected? */ - for(a=0; areports= reports; - curlib = library_append(mainvar, scene, file, dir, idcode, totsel, &fd, filelist, totfile,flag ); - if(fd) fd->reports= NULL; - - *bh= (BlendHandle*)fd; - - /* when not linking (appending)... */ - if((flag & FILE_LINK)==0) { - if(flag & FILE_ATCURSOR) { - float *curs, centerloc[3], vec[3], min[3], max[3]; - int count= 0; - - INIT_MINMAX(min, max); - - centerbase= (scene->base.first); - while(centerbase) { - if(centerbase->object->id.lib==curlib && centerbase->object->parent==NULL) { - VECCOPY(vec, centerbase->object->loc); - DO_MINMAX(vec, min, max); - count++; - } - centerbase= centerbase->next; - } - if(count) { - centerloc[0]= (min[0]+max[0])/2; - centerloc[1]= (min[1]+max[1])/2; - centerloc[2]= (min[2]+max[2])/2; - curs = scene->cursor; - VECSUB(centerloc,curs,centerloc); - - centerbase= (scene->base.first); - while(centerbase) { - if(centerbase->object->id.lib==curlib && centerbase->object->parent==NULL) { - ob= centerbase->object; - ob->loc[0] += centerloc[0]; - ob->loc[1] += centerloc[1]; - ob->loc[2] += centerloc[2]; - } - centerbase= centerbase->next; - } - } - } - } -} +#endif /* ************* READ LIBRARY ************** */ diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index a9736f3f88d..868c5902670 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -417,7 +417,7 @@ void FONT_OT_file_paste(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - WM_operator_properties_filesel(ot, FOLDERFILE|TEXTFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|TEXTFILE, FILE_SPECIAL); } /******************* paste buffer operator ********************/ diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 5ae1bdf84aa..fb3da4a5353 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -73,24 +73,24 @@ static int screenshot_exec(bContext *C, wmOperator *op) if(scd && scd->dumprect) { Scene *scene= CTX_data_scene(C); ImBuf *ibuf; - char filename[FILE_MAX]; + char path[FILE_MAX]; - RNA_string_get(op->ptr, "filename", filename); + RNA_string_get(op->ptr, "path", path); - strcpy(G.ima, filename); - BLI_convertstringcode(filename, G.sce); + strcpy(G.ima, path); + BLI_convertstringcode(path, G.sce); /* BKE_add_image_extension() checks for if extension was already set */ if(scene->r.scemode & R_EXTENSION) - if(strlen(filename)r.imtype); + if(strlen(path)r.imtype); ibuf= IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0, 0); ibuf->rect= scd->dumprect; if(scene->r.planes == 8) IMB_cspace(ibuf, rgb_to_bw); - BKE_write_ibuf(scene, ibuf, filename, scene->r.imtype, scene->r.subimtype, scene->r.quality); + BKE_write_ibuf(scene, ibuf, path, scene->r.imtype, scene->r.subimtype, scene->r.quality); IMB_freeImBuf(ibuf); @@ -149,10 +149,10 @@ static int screenshot_invoke(bContext *C, wmOperator *op, wmEvent *event) scd->dumprect= dumprect; op->customdata= scd; - if(RNA_property_is_set(op->ptr, "filename")) + if(RNA_property_is_set(op->ptr, "path")) return screenshot_exec(C, op); - RNA_string_set(op->ptr, "filename", G.ima); + RNA_string_set(op->ptr, "path", G.ima); WM_event_add_fileselect(C, op); @@ -173,7 +173,7 @@ void SCREEN_OT_screenshot(wmOperatorType *ot) ot->flag= 0; - WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE, FILE_SPECIAL); RNA_def_boolean(ot->srna, "full", 1, "Full Screen", ""); } @@ -327,7 +327,7 @@ void SCREEN_OT_screencast(wmOperatorType *ot) ot->flag= 0; - RNA_def_property(ot->srna, "filename", PROP_STRING, PROP_FILEPATH); + RNA_def_property(ot->srna, "path", PROP_STRING, PROP_FILEPATH); RNA_def_boolean(ot->srna, "full", 1, "Full Screen", ""); } diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 303ca0eaefd..1121a3bcbcd 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -66,13 +66,13 @@ static int open_exec(bContext *C, wmOperator *op) { - char filename[FILE_MAX]; + char path[FILE_MAX]; bSound *sound; AUD_SoundInfo info; - RNA_string_get(op->ptr, "filename", filename); + RNA_string_get(op->ptr, "path", path); - sound = sound_new_file(CTX_data_main(C), filename); + sound = sound_new_file(CTX_data_main(C), path); if (sound==NULL || sound->handle == NULL) { BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); @@ -114,7 +114,7 @@ void SOUND_OT_open(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - WM_operator_properties_filesel(ot, FOLDERFILE|SOUNDFILE|MOVIEFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|SOUNDFILE|MOVIEFILE, FILE_SPECIAL); RNA_def_boolean(ot->srna, "cache", FALSE, "Cache", "Cache the sound in memory."); } diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 481c2d6cfc3..9b335b86163 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -1069,10 +1069,10 @@ static int file_browse_exec(bContext *C, wmOperator *op) FileBrowseOp *fbo= op->customdata; char *str; - if (RNA_property_is_set(op->ptr, "filename")==0 || fbo==NULL) + if (RNA_property_is_set(op->ptr, "path")==0 || fbo==NULL) return OPERATOR_CANCELLED; - str= RNA_string_get_alloc(op->ptr, "filename", 0, 0); + str= RNA_string_get_alloc(op->ptr, "path", 0, 0); RNA_property_string_set(&fbo->ptr, fbo->prop, str); RNA_property_update(C, &fbo->ptr, fbo->prop); MEM_freeN(str); @@ -1128,6 +1128,6 @@ void BUTTONS_OT_file_browse(wmOperatorType *ot) ot->cancel= file_browse_cancel; /* properties */ - WM_operator_properties_filesel(ot, 0); + WM_operator_properties_filesel(ot, 0, FILE_SPECIAL); } diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index e1a6e346ce2..5d3c2c766a3 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -520,9 +520,11 @@ int file_exec(bContext *C, wmOperator *unused) wmOperator *op= sfile->op; sfile->op = NULL; + RNA_string_set(op->ptr, "filename", sfile->params->file); BLI_strncpy(name, sfile->params->dir, sizeof(name)); + RNA_string_set(op->ptr, "directory", name); strcat(name, sfile->params->file); - RNA_string_set(op->ptr, "filename", name); + RNA_string_set(op->ptr, "path", name); /* some ops have multiple files to select */ { @@ -872,11 +874,13 @@ void FILE_OT_bookmark_toggle(struct wmOperatorType *ot) int file_filenum_exec(bContext *C, wmOperator *op) { SpaceFile *sfile= CTX_wm_space_file(C); + ScrArea *sa= CTX_wm_area(C); int inc = RNA_int_get(op->ptr, "increment"); if(sfile->params && (inc != 0)) { BLI_newname(sfile->params->file, inc); - WM_event_add_notifier(C, NC_WINDOW, NULL); + ED_area_tag_redraw(sa); + // WM_event_add_notifier(C, NC_WINDOW, NULL); } return OPERATOR_FINISHED; @@ -916,6 +920,24 @@ int file_rename_exec(bContext *C, wmOperator *op) } +int file_rename_poll(bContext *C) +{ + int poll = ED_operator_file_active(C); + SpaceFile *sfile= CTX_wm_space_file(C); + + if (sfile && sfile->params) { + if (sfile->params->active_file < 0) { + poll= 0; + } else { + char dir[FILE_MAX], group[FILE_MAX]; + if (filelist_islibrary(sfile->files, dir, group)) poll= 0; + } + } + else + poll= 0; + return poll; +} + void FILE_OT_rename(struct wmOperatorType *ot) { /* identifiers */ @@ -924,7 +946,7 @@ void FILE_OT_rename(struct wmOperatorType *ot) /* api callbacks */ ot->exec= file_rename_exec; - ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ + ot->poll= file_rename_poll; } @@ -938,6 +960,8 @@ int file_delete_poll(bContext *C) if (sfile->params->active_file < 0) { poll= 0; } else { + char dir[FILE_MAX], group[FILE_MAX]; + if (filelist_islibrary(sfile->files, dir, group)) poll= 0; file = filelist_file(sfile->files, sfile->params->active_file); if (file && S_ISDIR(file->type)) poll= 0; } diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index 24c3f9b4ca1..2d351016893 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -181,6 +181,12 @@ static void file_panel_operator(const bContext *C, Panel *pa) RNA_STRUCT_BEGIN(op->ptr, prop) { if(strcmp(RNA_property_identifier(prop), "rna_type") == 0) continue; + if(strcmp(RNA_property_identifier(prop), "type") == 0) + continue; + if(strcmp(RNA_property_identifier(prop), "path") == 0) + continue; + if(strcmp(RNA_property_identifier(prop), "directory") == 0) + continue; if(strcmp(RNA_property_identifier(prop), "filename") == 0) continue; if(strcmp(RNA_property_identifier(prop), "display") == 0) diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 538c1e4fce7..23f24f26dc0 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -60,6 +60,7 @@ #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_report.h" #include "BLO_readfile.h" #include "DNA_space_types.h" @@ -109,7 +110,6 @@ typedef struct FileList { struct direntry *filelist; int *fidx; - int numfiles; int numfiltered; char dir[FILE_MAX]; @@ -118,6 +118,12 @@ typedef struct FileList short hide_dot; unsigned int filter; short changed; + + struct BlendHandle *libfiledata; + short hide_parent; + + void (*read)(struct FileList *); + ListBase loadimages; ListBase threads; } FileList; @@ -277,12 +283,20 @@ static int compare_extension(const void *a1, const void *a2) { void filelist_filter(FileList* filelist) { + /* char dir[FILE_MAX], group[GROUP_MAX]; XXXXX */ int num_filtered = 0; int i, j; if (!filelist->filelist) return; + /* XXXXX TODO: check if the filter can be handled outside the filelist + if ( ( (filelist->type == FILE_LOADLIB) && BIF_filelist_islibrary(filelist, dir, group)) + || (filelist->type == FILE_MAIN) ) { + filelist->filter = 0; + } + */ + if (!filelist->filter) { if (filelist->fidx) { MEM_freeN(filelist->fidx); @@ -438,22 +452,28 @@ void folderlist_free(ListBase* folderlist) folderlist= NULL; } +static void filelist_read_main(struct FileList* filelist); +static void filelist_read_library(struct FileList* filelist); +static void filelist_read_dir(struct FileList* filelist); + //------------------FILELIST------------------------// -struct FileList* filelist_new() +struct FileList* filelist_new(short type) { FileList* p = MEM_callocN( sizeof(FileList), "filelist" ); + switch(type) { + case FILE_MAIN: + p->read = filelist_read_main; + break; + case FILE_LOADLIB: + p->read = filelist_read_library; + break; + default: + p->read = filelist_read_dir; + + } return p; } -struct FileList* filelist_copy(struct FileList* filelist) -{ - FileList* p = filelist_new(); - BLI_strncpy(p->dir, filelist->dir, FILE_MAX); - p->filelist = NULL; - p->fidx = NULL; - - return p; -} void filelist_free(struct FileList* filelist) { @@ -493,6 +513,18 @@ void filelist_free(struct FileList* filelist) filelist->hide_dot =0; } +void filelist_freelib(struct FileList* filelist) +{ + if(filelist->libfiledata) + BLO_blendhandle_close(filelist->libfiledata); + filelist->libfiledata= 0; +} + +struct BlendHandle *filelist_lib(struct FileList* filelist) +{ + return filelist->libfiledata; +} + int filelist_numfiles(struct FileList* filelist) { return filelist->numfiltered; @@ -733,16 +765,16 @@ void filelist_setfilter(struct FileList* filelist, unsigned int filter) filelist->filter = filter; } -void filelist_readdir(struct FileList* filelist) +static void filelist_read_dir(struct FileList* filelist) { char wdir[FILE_MAX]; - if (!filelist) return; + filelist->fidx = 0; filelist->filelist = 0; BLI_getwdN(wdir); - + BLI_cleanup_dir(G.sce, filelist->dir); BLI_hide_dot_files(filelist->hide_dot); filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist)); @@ -750,12 +782,50 @@ void filelist_readdir(struct FileList* filelist) chdir(wdir); filelist_setfiletypes(filelist, G.have_quicktime); filelist_filter(filelist); - + if (!filelist->threads.first) { BLI_init_threads(&filelist->threads, exec_loadimages, 2); } } +static void filelist_read_main(struct FileList* filelist) +{ + if (!filelist) return; + filelist_from_main(filelist); +} + +static void filelist_read_library(struct FileList* filelist) +{ + if (!filelist) return; + BLI_cleanup_dir(G.sce, filelist->dir); + filelist_from_library(filelist); + if(!filelist->libfiledata) { + int num; + struct direntry *file; + filelist_read_dir(filelist); + file = filelist->filelist; + for(num=0; numnumfiles; num++, file++) { + if(BLO_has_bfile_extension(file->relname)) { + char name[FILE_MAXDIR+FILE_MAXFILE]; + + BLI_strncpy(name, filelist->dir, sizeof(name)); + strcat(name, file->relname); + + /* prevent current file being used as acceptable dir */ + if (BLI_streq(G.main->name, name)==0) { + file->type &= ~S_IFMT; + file->type |= S_IFDIR; + } + } + } + } +} + +void filelist_readdir(struct FileList* filelist) +{ + filelist->read(filelist); +} + int filelist_empty(struct FileList* filelist) { return filelist->filelist == 0; @@ -937,3 +1007,272 @@ void filelist_sort(struct FileList* filelist, short sort) filelist_filter(filelist); } + + +int filelist_islibrary(struct FileList* filelist, char* dir, char* group) +{ + return BLO_is_a_library(filelist->dir, dir, group); +} + +static int groupname_to_code(char *group) +{ + char buf[32]; + char *lslash; + + BLI_strncpy(buf, group, 31); + lslash= BLI_last_slash(buf); + if (lslash) + lslash[0]= '\0'; + + return BLO_idcode_from_name(buf); +} + +void filelist_from_library(struct FileList* filelist) +{ + LinkNode *l, *names, *previews; + struct ImBuf* ima; + int ok, i, nnames, idcode; + char filename[FILE_MAXDIR+FILE_MAXFILE]; + char dir[FILE_MAX], group[GROUP_MAX]; + + /* name test */ + ok= filelist_islibrary(filelist, dir, group); + if (!ok) { + /* free */ + if(filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata); + filelist->libfiledata= 0; + return; + } + + BLI_strncpy(filename, G.sce, sizeof(filename)); // G.sce = last file loaded, for UI + + /* there we go */ + /* for the time being only read filedata when libfiledata==0 */ + if (filelist->libfiledata==0) { + filelist->libfiledata= BLO_blendhandle_from_file(dir); + if(filelist->libfiledata==0) return; + } + + idcode= groupname_to_code(group); + + // memory for strings is passed into filelist[i].relname + // and free'd in freefilelist + previews = NULL; + if (idcode) { + previews= BLO_blendhandle_get_previews(filelist->libfiledata, idcode); + names= BLO_blendhandle_get_datablock_names(filelist->libfiledata, idcode); + /* ugh, no rewind, need to reopen */ + BLO_blendhandle_close(filelist->libfiledata); + filelist->libfiledata= BLO_blendhandle_from_file(dir); + + } else { + names= BLO_blendhandle_get_linkable_groups(filelist->libfiledata); + } + + nnames= BLI_linklist_length(names); + + filelist->numfiles= nnames + 1; + filelist->filelist= malloc(filelist->numfiles * sizeof(*filelist->filelist)); + memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist)); + + filelist->filelist[0].relname= BLI_strdup(".."); + filelist->filelist[0].type |= S_IFDIR; + + for (i=0, l= names; inext) { + char *blockname= l->link; + + filelist->filelist[i + 1].relname= BLI_strdup(blockname); + if (!idcode) + filelist->filelist[i + 1].type |= S_IFDIR; + } + + if(previews) { + for (i=0, l= previews; inext) { + PreviewImage *img= l->link; + + if (img) { + unsigned int w = img->w[PREVIEW_MIPMAP_LARGE]; + unsigned int h = img->h[PREVIEW_MIPMAP_LARGE]; + unsigned int *rect = img->rect[PREVIEW_MIPMAP_LARGE]; + + /* first allocate imbuf for copying preview into it */ + if (w > 0 && h > 0 && rect) { + ima = IMB_allocImBuf(w, h, 32, IB_rect, 0); + memcpy(ima->rect, rect, w*h*sizeof(unsigned int)); + filelist->filelist[i + 1].image = ima; + filelist->filelist[i + 1].flags = IMAGEFILE; + } + } + } + } + + BLI_linklist_free(names, free); + if (previews) BLI_linklist_free(previews, (void(*)(void*)) MEM_freeN); + + filelist_sort(filelist, FILE_SORT_ALPHA); + + BLI_strncpy(G.sce, filename, sizeof(filename)); // prevent G.sce to change + + filelist->filter = 0; + filelist_filter(filelist); +} + +void filelist_hideparent(struct FileList* filelist, short hide) +{ + filelist->hide_parent = hide; +} + +void filelist_from_main(struct FileList *filelist) +{ + ID *id; + struct direntry *files, *firstlib = NULL; + ListBase *lb; + int a, fake, idcode, ok, totlib, totbl; + + // filelist->type = FILE_MAIN; // XXXXX TODO: add modes to filebrowser + + if(filelist->dir[0]=='/') filelist->dir[0]= 0; + + if(filelist->dir[0]) { + idcode= groupname_to_code(filelist->dir); + if(idcode==0) filelist->dir[0]= 0; + } + + if( filelist->dir[0]==0) { + + /* make directories */ + filelist->numfiles= 23; + filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry)); + + for(a=0; anumfiles; a++) { + memset( &(filelist->filelist[a]), 0 , sizeof(struct direntry)); + filelist->filelist[a].type |= S_IFDIR; + } + + filelist->filelist[0].relname= BLI_strdup(".."); + filelist->filelist[2].relname= BLI_strdup("Scene"); + filelist->filelist[3].relname= BLI_strdup("Object"); + filelist->filelist[4].relname= BLI_strdup("Mesh"); + filelist->filelist[5].relname= BLI_strdup("Curve"); + filelist->filelist[6].relname= BLI_strdup("Metaball"); + filelist->filelist[7].relname= BLI_strdup("Material"); + filelist->filelist[8].relname= BLI_strdup("Texture"); + filelist->filelist[9].relname= BLI_strdup("Image"); + filelist->filelist[10].relname= BLI_strdup("Ika"); + filelist->filelist[11].relname= BLI_strdup("Wave"); + filelist->filelist[12].relname= BLI_strdup("Lattice"); + filelist->filelist[13].relname= BLI_strdup("Lamp"); + filelist->filelist[14].relname= BLI_strdup("Camera"); + filelist->filelist[15].relname= BLI_strdup("Ipo"); + filelist->filelist[16].relname= BLI_strdup("World"); + filelist->filelist[17].relname= BLI_strdup("Screen"); + filelist->filelist[18].relname= BLI_strdup("VFont"); + filelist->filelist[19].relname= BLI_strdup("Text"); + filelist->filelist[20].relname= BLI_strdup("Armature"); + filelist->filelist[21].relname= BLI_strdup("Action"); + filelist->filelist[22].relname= BLI_strdup("NodeTree"); + filelist_sort(filelist, FILE_SORT_ALPHA); + } + else { + + /* make files */ + idcode= groupname_to_code(filelist->dir); + + lb= wich_libbase(G.main, idcode ); + if(lb==0) return; + + id= lb->first; + filelist->numfiles= 0; + while(id) { + /* XXXXX TODO: the selection of the ipo blocktype might go somewhere else? + if(filelist->has_func && idcode==ID_IP) { + if(filelist->ipotype== ((Ipo *)id)->blocktype) filelist->numfiles++; + } + else */ + if (!filelist->hide_dot || id->name[2] != '.') { + filelist->numfiles++; + } + + id= id->next; + } + + /* XXXXX TODO: if databrowse F4 or append/link filelist->hide_parent has to be set */ + if (!filelist->hide_parent) filelist->numfiles+= 1; + filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry)); + + files = filelist->filelist; + + if (!filelist->hide_parent) { + memset( &(filelist->filelist[0]), 0 , sizeof(struct direntry)); + filelist->filelist[0].relname= BLI_strdup(".."); + filelist->filelist[0].type |= S_IFDIR; + + files++; + } + + id= lb->first; + totlib= totbl= 0; + + while(id) { +#if 0 + // XXXXX TODO: this is deprecated, checks for correct IPO block? + ok= 0; + if(filelist->has_func && idcode==ID_IP) { + if(filelist->ipotype== ((Ipo *)id)->blocktype) ok= 1; + } + else ok= 1; +#endif + ok = 1; + if(ok) { + if (!filelist->hide_dot || id->name[2] != '.') { + memset( files, 0 , sizeof(struct direntry)); + if(id->lib==NULL) + files->relname= BLI_strdup(id->name+2); + else { + files->relname= MEM_mallocN(FILE_MAXDIR+FILE_MAXFILE+32, "filename for lib"); + sprintf(files->relname, "%s | %s", id->lib->name, id->name+2); + } + /* files->type |= S_IFDIR; */ +#if 0 // XXXXX TODO show the selection status of the objects + if(!filelist->has_func) { /* F4 DATA BROWSE */ + if(idcode==ID_OB) { + if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE; + } + else if(idcode==ID_SCE) { + if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->flags |= ACTIVE; + } + } +#endif + files->nr= totbl+1; + files->poin= id; + fake= id->flag & LIB_FAKEUSER; + if(idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) { + files->flags |= IMAGEFILE; + } + if(id->lib && fake) sprintf(files->extra, "LF %d", id->us); + else if(id->lib) sprintf(files->extra, "L %d", id->us); + else if(fake) sprintf(files->extra, "F %d", id->us); + else sprintf(files->extra, " %d", id->us); + + if(id->lib) { + if(totlib==0) firstlib= files; + totlib++; + } + + files++; + } + totbl++; + } + + id= id->next; + } + + /* only qsort of library blocks */ + if(totlib>1) { + qsort(firstlib, totlib, sizeof(struct direntry), compare_name); + } + } + filelist->filter = 0; + filelist_filter(filelist); +} + diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index dd3c2c766c1..a8d909f899e 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -42,12 +42,13 @@ struct FolderList; struct direntry; struct BlendHandle; struct Scene; +struct Main; struct rcti; +struct ReportList; -struct FileList * filelist_new(); +struct FileList * filelist_new(short type); void filelist_init_icons(); void filelist_free_icons(); -struct FileList * filelist_copy(struct FileList* filelist); int filelist_find(struct FileList* filelist, char *file); void filelist_free(struct FileList* filelist); void filelist_sort(struct FileList* filelist, short sort); @@ -71,6 +72,13 @@ int filelist_empty(struct FileList* filelist); void filelist_parent(struct FileList* filelist); void filelist_setfiletypes(struct FileList* filelist, short has_quicktime); + +int filelist_islibrary (struct FileList* filelist, char* dir, char* group); +void filelist_from_main(struct FileList* filelist); +void filelist_from_library(struct FileList* filelist); +void filelist_freelib(struct FileList* filelist); +void filelist_hideparent(struct FileList* filelist, short hide); + struct ListBase * folderlist_new(); void folderlist_free(struct ListBase* folderlist); void folderlist_popdir(struct ListBase* folderlist, char *dir); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index f300505933f..b0bd3a9a5e7 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -123,6 +123,22 @@ short ED_fileselect_set_params(SpaceFile *sfile) /* set the parameters from the operator, if it exists */ if (op) { BLI_strncpy(params->title, op->type->name, sizeof(params->title)); + + params->type = RNA_int_get(op->ptr, "type"); + + if (RNA_property_is_set(op->ptr, "path")) { + RNA_string_get(op->ptr, "path", name); + if (params->type == FILE_LOADLIB) { + BLI_strncpy(params->dir, name, sizeof(params->dir)); + BLI_cleanup_dir(G.sce, params->dir); + } else { + /* if operator has path set, use it, otherwise keep the last */ + BLI_convertstringcode(name, G.sce); + BLI_split_dirfile(name, dir, file); + BLI_strncpy(params->file, file, sizeof(params->file)); + BLI_make_file_string(G.sce, params->dir, dir, ""); /* XXX needed ? - also solve G.sce */ + } + } params->filter = 0; params->filter |= RNA_boolean_get(op->ptr, "filter_blender") ? BLENDERFILE : 0; params->filter |= RNA_boolean_get(op->ptr, "filter_image") ? IMAGEFILE : 0; @@ -136,21 +152,18 @@ short ED_fileselect_set_params(SpaceFile *sfile) if (params->filter != 0) params->flag |= FILE_FILTER; - params->flag |= FILE_HIDE_DOT; - + if (params->type == FILE_LOADLIB) { + params->flag |= FILE_HIDE_DOT; + params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0; + params->flag |= RNA_boolean_get(op->ptr, "autoselect") ? FILE_AUTOSELECT : 0; + params->flag |= RNA_boolean_get(op->ptr, "active_layer") ? FILE_ACTIVELAY : 0; + } + if(params->filter & (IMAGEFILE|MOVIEFILE)) params->display= FILE_IMGDISPLAY; else params->display= FILE_SHORTDISPLAY; - /* if operator has path set, use it, otherwise keep the last */ - if (RNA_property_is_set(op->ptr, "filename")) { - RNA_string_get(op->ptr, "filename", name); - BLI_convertstringcode(name, G.sce); - BLI_split_dirfile(name, dir, file); - BLI_strncpy(params->file, file, sizeof(params->file)); - BLI_make_file_string(G.sce, params->dir, dir, ""); /* XXX needed ? - also solve G.sce */ - } } else { /* default values, if no operator */ params->flag |= FILE_HIDE_DOT; @@ -357,19 +370,15 @@ FileLayout* ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *ar void file_change_dir(struct SpaceFile *sfile) { if (sfile->params) { - if (BLI_exists(sfile->params->dir)) { - filelist_setdir(sfile->files, sfile->params->dir); + filelist_setdir(sfile->files, sfile->params->dir); - if(folderlist_clear_next(sfile)) - folderlist_free(sfile->folders_next); + if(folderlist_clear_next(sfile)) + folderlist_free(sfile->folders_next); - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); + folderlist_pushdir(sfile->folders_prev, sfile->params->dir); - filelist_free(sfile->files); - sfile->params->active_file = -1; - } else { - BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), FILE_MAX); - } + filelist_free(sfile->files); + sfile->params->active_file = -1; } } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 722fa475727..f71defe3949 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -119,6 +119,7 @@ static void file_free(SpaceLink *sl) SpaceFile *sfile= (SpaceFile *) sl; if(sfile->files) { + filelist_freelib(sfile->files); filelist_free(sfile->files); MEM_freeN(sfile->files); sfile->files= NULL; @@ -165,7 +166,7 @@ static SpaceLink *file_duplicate(SpaceLink *sl) /* clear or remove stuff from old */ sfilen->op = NULL; /* file window doesn't own operators */ - sfilen->files = filelist_new(); + sfilen->files = filelist_new(sfileo->params->type); if(sfileo->folders_prev) sfilen->folders_prev = MEM_dupallocN(sfileo->folders_prev); @@ -190,7 +191,7 @@ static void file_refresh(const bContext *C, ScrArea *sa) if (!sfile->folders_prev) sfile->folders_prev = folderlist_new(); if (!sfile->files) { - sfile->files = filelist_new(); + sfile->files = filelist_new(params->type); file_change_dir(sfile); params->active_file = -1; // added this so it opens nicer (ton) } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index bee06e6892f..806d0d7ce52 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -609,7 +609,7 @@ static const EnumPropertyItem image_file_type_items[] = { static void image_filesel(bContext *C, wmOperator *op, const char *path) { - RNA_string_set(op->ptr, "filename", path); + RNA_string_set(op->ptr, "path", path); WM_event_add_fileselect(C, op); } @@ -623,7 +623,7 @@ static int open_exec(bContext *C, wmOperator *op) Image *ima= NULL; char str[FILE_MAX]; - RNA_string_get(op->ptr, "filename", str); + RNA_string_get(op->ptr, "path", str); ima= BKE_add_image_file(str, scene->r.cfra); if(!ima) @@ -640,7 +640,7 @@ static int open_invoke(bContext *C, wmOperator *op, wmEvent *event) SpaceImage *sima= CTX_wm_space_image(C); char *path= (sima->image)? sima->image->name: U.textudir; - if(RNA_property_is_set(op->ptr, "filename")) + if(RNA_property_is_set(op->ptr, "path")) return open_exec(C, op); image_filesel(C, op, path); @@ -663,7 +663,7 @@ void IMAGE_OT_open(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_SPECIAL); } /******************** replace image operator ********************/ @@ -676,7 +676,7 @@ static int replace_exec(bContext *C, wmOperator *op) if(!sima->image) return OPERATOR_CANCELLED; - RNA_string_get(op->ptr, "filename", str); + RNA_string_get(op->ptr, "path", str); BLI_strncpy(sima->image->name, str, sizeof(sima->image->name)-1); /* we cant do much if the str is longer then 240 :/ */ BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD); @@ -693,7 +693,7 @@ static int replace_invoke(bContext *C, wmOperator *op, wmEvent *event) if(!sima->image) return OPERATOR_CANCELLED; - if(RNA_property_is_set(op->ptr, "filename")) + if(RNA_property_is_set(op->ptr, "path")) return replace_exec(C, op); image_filesel(C, op, path); @@ -716,7 +716,7 @@ void IMAGE_OT_replace(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_SPECIAL); } /******************** save image as operator ********************/ @@ -801,7 +801,7 @@ static int save_as_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; sima->imtypenr= RNA_enum_get(op->ptr, "file_type"); - RNA_string_get(op->ptr, "filename", str); + RNA_string_get(op->ptr, "path", str); save_image_doit(C, sima, scene, op, str); @@ -815,7 +815,7 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event) ImBuf *ibuf= ED_space_image_buffer(sima); Scene *scene= CTX_data_scene(C); - if(RNA_property_is_set(op->ptr, "filename")) + if(RNA_property_is_set(op->ptr, "path")) return save_as_exec(C, op); if(!ima) @@ -861,7 +861,7 @@ void IMAGE_OT_save_as(wmOperatorType *ot) /* properties */ RNA_def_enum(ot->srna, "file_type", image_file_type_items, R_PNG, "File Type", "File type to save image as."); - WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_SPECIAL); } /******************** save image operator ********************/ diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 640c968742c..f4d8682b8ea 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -300,11 +300,11 @@ void FILE_OT_report_missing_files(wmOperatorType *ot) static int find_missing_files_exec(bContext *C, wmOperator *op) { - char *filename; + char *path; - filename= RNA_string_get_alloc(op->ptr, "filename", NULL, 0); - findMissingFiles(filename); - MEM_freeN(filename); + path= RNA_string_get_alloc(op->ptr, "path", NULL, 0); + findMissingFiles(path); + MEM_freeN(path); return OPERATOR_FINISHED; } @@ -330,7 +330,7 @@ void FILE_OT_find_missing_files(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - WM_operator_properties_filesel(ot, 0); + WM_operator_properties_filesel(ot, 0, FILE_SPECIAL); } #if 0 diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c index 88b8dccc6c9..c17793b28f8 100644 --- a/source/blender/editors/space_script/script_edit.c +++ b/source/blender/editors/space_script/script_edit.c @@ -64,10 +64,10 @@ static int run_pyfile_exec(bContext *C, wmOperator *op) ARegion *ar= CTX_wm_region(C); - char filename[512]; - RNA_string_get(op->ptr, "filename", filename); + char path[512]; + RNA_string_get(op->ptr, "path", path); #ifndef DISABLE_PYTHON - if(BPY_run_python_script(C, filename, NULL, op->reports)) { + if(BPY_run_python_script(C, path, NULL, op->reports)) { ED_region_tag_redraw(ar); return OPERATOR_FINISHED; } @@ -85,7 +85,7 @@ void SCRIPT_OT_python_file_run(wmOperatorType *ot) ot->exec= run_pyfile_exec; ot->poll= ED_operator_areaactive; - RNA_def_string_file_path(ot->srna, "filename", "", 512, "Filename", ""); + RNA_def_string_file_path(ot->srna, "path", "", 512, "Path", ""); } static int run_ui_scripts_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/space_script/script_ops.c b/source/blender/editors/space_script/script_ops.c index aa35ba54b7f..270cc1ffd8f 100644 --- a/source/blender/editors/space_script/script_ops.c +++ b/source/blender/editors/space_script/script_ops.c @@ -68,7 +68,7 @@ void script_keymap(wmWindowManager *wm) ListBase *keymap= WM_keymap_listbase(wm, "Script", SPACE_SCRIPT, 0); /* TODO - this is just while we have no way to load a text datablock */ - RNA_string_set(WM_keymap_add_item(keymap, "SCRIPT_OT_python_file_run", PKEY, KM_PRESS, KM_CTRL|KM_SHIFT|KM_ALT, 0)->ptr, "filename", "test.py"); + RNA_string_set(WM_keymap_add_item(keymap, "SCRIPT_OT_python_file_run", PKEY, KM_PRESS, KM_CTRL|KM_SHIFT|KM_ALT, 0)->ptr, "path", "test.py"); WM_keymap_add_item(keymap, "SCRIPT_OT_python_run_ui_scripts", PKEY, KM_PRESS, KM_SHIFT, 0); } diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 8a1b3bf3465..bd5259ddb52 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -289,7 +289,7 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op) Editing *ed= seq_give_editing(scene, TRUE); struct anim *an; - char filename[FILE_MAX]; + char path[FILE_MAX]; Sequence *seq, *soundseq=NULL; /* generic strip vars */ Strip *strip; @@ -301,12 +301,12 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op) channel= RNA_int_get(op->ptr, "channel"); sound = RNA_boolean_get(op->ptr, "sound"); - RNA_string_get(op->ptr, "filename", filename); + RNA_string_get(op->ptr, "path", path); - an = openanim(filename, IB_rect); + an = openanim(path, IB_rect); if (an==NULL) { - BKE_reportf(op->reports, RPT_ERROR, "Filename \"%s\" could not be loaded as a movie", filename); + BKE_reportf(op->reports, RPT_ERROR, "File \"%s\" could not be loaded as a movie", path); return OPERATOR_CANCELLED; } @@ -323,7 +323,7 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op) strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - BLI_split_dirfile_basic(filename, strip->dir, se->name); + BLI_split_dirfile_basic(path, strip->dir, se->name); RNA_string_get(op->ptr, "name", seq->name); @@ -332,7 +332,7 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op) if(sound) { - soundseq = sequencer_add_sound_strip(C, NULL, start_frame, channel+1, filename); + soundseq = sequencer_add_sound_strip(C, NULL, start_frame, channel+1, path); if(soundseq != NULL) RNA_string_get(op->ptr, "name", soundseq->name); } @@ -376,7 +376,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - WM_operator_properties_filesel(ot, FOLDERFILE|MOVIEFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|MOVIEFILE, FILE_SPECIAL); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); RNA_def_boolean(ot->srna, "sound", TRUE, "Sound", "Load sound with the movie"); } @@ -384,7 +384,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot) /* add sound operator */ static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op) { - char filename[FILE_MAX]; + char path[FILE_MAX]; Scene *scene= CTX_data_scene(C); Sequence *seq; /* generic strip vars */ int start_frame, channel; /* operator props */ @@ -392,9 +392,9 @@ static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op) start_frame= RNA_int_get(op->ptr, "start_frame"); channel= RNA_int_get(op->ptr, "channel"); - RNA_string_get(op->ptr, "filename", filename); + RNA_string_get(op->ptr, "path", path); - seq = sequencer_add_sound_strip(C, op, start_frame, channel, filename); + seq = sequencer_add_sound_strip(C, op, start_frame, channel, path); if(seq == NULL) return OPERATOR_CANCELLED; @@ -442,7 +442,7 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - WM_operator_properties_filesel(ot, FOLDERFILE|SOUNDFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|SOUNDFILE, FILE_SPECIAL); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); RNA_def_boolean(ot->srna, "cache", FALSE, "Cache", "Cache the sound in memory."); } @@ -455,7 +455,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) int tot_images; - char filename[FILE_MAX]; + char path[FILE_MAX]; Sequence *seq; /* generic strip vars */ Strip *strip; @@ -466,14 +466,14 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) start_frame= RNA_int_get(op->ptr, "start_frame"); channel= RNA_int_get(op->ptr, "channel"); - RNA_string_get(op->ptr, "filename", filename); + RNA_string_get(op->ptr, "path", path); seq = alloc_sequence(ed->seqbasep, start_frame, channel); seq->type= SEQ_IMAGE; /* basic defaults */ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - BLI_split_dirfile_basic(filename, strip->dir, NULL); + BLI_split_dirfile_basic(path, strip->dir, NULL); tot_images= RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); @@ -490,7 +490,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) RNA_END; } else { - BLI_split_dirfile_basic(filename, NULL, se->name); + BLI_split_dirfile_basic(path, NULL, se->name); } RNA_string_get(op->ptr, "name", seq->name); @@ -538,7 +538,7 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE, FILE_SPECIAL); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", ""); @@ -606,15 +606,15 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); if (seq->type==SEQ_PLUGIN) { - char filename[FILE_MAX]; - RNA_string_get(op->ptr, "filename", filename); + char path[FILE_MAX]; + RNA_string_get(op->ptr, "path", path); - sh.init_plugin(seq, filename); + sh.init_plugin(seq, path); if(seq->plugin==NULL) { BLI_remlink(ed->seqbasep, seq); seq_free_sequence(scene, seq); - BKE_reportf(op->reports, RPT_ERROR, "Sequencer plugin \"%s\" could not load.", filename); + BKE_reportf(op->reports, RPT_ERROR, "Sequencer plugin \"%s\" could not load.", path); return OPERATOR_CANCELLED; } } @@ -673,7 +673,7 @@ void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - WM_operator_properties_filesel(ot, 0); + WM_operator_properties_filesel(ot, 0, FILE_SPECIAL); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_ENDFRAME); RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_CROSS, "Type", "Sequencer effect type"); RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color", "Initialize the strip with this color (only used when type='COLOR')", 0.0f, 1.0f); diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 3411d9114df..3568f50dfe1 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -192,7 +192,7 @@ static int open_exec(bContext *C, wmOperator *op) Text *text; char str[FILE_MAX]; - RNA_string_get(op->ptr, "filename", str); + RNA_string_get(op->ptr, "path", str); text= add_text(str, G.sce); @@ -211,10 +211,10 @@ static int open_invoke(bContext *C, wmOperator *op, wmEvent *event) Text *text= CTX_data_edit_text(C); char *path= (text && text->name)? text->name: G.sce; - if(RNA_property_is_set(op->ptr, "filename")) + if(RNA_property_is_set(op->ptr, "path")) return open_exec(C, op); - RNA_string_set(op->ptr, "filename", path); + RNA_string_set(op->ptr, "path", path); WM_event_add_fileselect(C, op); return OPERATOR_RUNNING_MODAL; @@ -233,7 +233,7 @@ void TEXT_OT_open(wmOperatorType *ot) ot->poll= text_new_poll; /* properties */ - WM_operator_properties_filesel(ot, FOLDERFILE|TEXTFILE|PYSCRIPTFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|TEXTFILE|PYSCRIPTFILE, FILE_SPECIAL); } /******************* reload operator *********************/ @@ -420,7 +420,7 @@ static int save_as_exec(bContext *C, wmOperator *op) if(!text) return OPERATOR_CANCELLED; - RNA_string_get(op->ptr, "filename", str); + RNA_string_get(op->ptr, "path", str); if(text->name) MEM_freeN(text->name); text->name= BLI_strdup(str); @@ -438,7 +438,7 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event) Text *text= CTX_data_edit_text(C); char *str; - if(RNA_property_is_set(op->ptr, "filename")) + if(RNA_property_is_set(op->ptr, "path")) return save_as_exec(C, op); if(text->name) @@ -448,7 +448,7 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event) else str= G.sce; - RNA_string_set(op->ptr, "filename", str); + RNA_string_set(op->ptr, "path", str); WM_event_add_fileselect(C, op); return OPERATOR_RUNNING_MODAL; @@ -467,7 +467,7 @@ void TEXT_OT_save_as(wmOperatorType *ot) ot->poll= text_edit_poll; /* properties */ - WM_operator_properties_filesel(ot, FOLDERFILE|TEXTFILE|PYSCRIPTFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|TEXTFILE|PYSCRIPTFILE, FILE_SPECIAL); } /******************* run script operator *********************/ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 6fdc3a7787b..5c1b363aa39 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -154,24 +154,23 @@ typedef struct FileSelectParams { char dir[240]; /* directory */ char file[80]; /* file */ - short flag; /* settings for filter, hiding files and display mode */ + short type; /* XXXXX for now store type here, should be moved to the operator */ + short flag; /* settings for filter, hiding dots files,... */ short sort; /* sort order */ short display; /* display mode flag */ short filter; /* filter when (flags & FILE_FILTER) is true */ /* XXX - temporary, better move to filelist */ short active_bookmark; - short pad; int active_file; int selstate; + /* short /* XXX --- still unused -- */ short f_fp; /* show font preview */ short menu; /* currently selected option in pupmenu */ char fp_str[8]; /* string to use for font preview */ - char *pupmenu; /* allows menu for save options - result stored in menup */ - /* XXX --- end unused -- */ } FileSelectParams; diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index 42c5343dbff..595562503aa 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -83,6 +83,7 @@ PropertyRNA *RNA_def_int_array(StructOrFunctionRNA *cont, const char *identifier PropertyRNA *RNA_def_string(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description); PropertyRNA *RNA_def_string_file_path(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description); PropertyRNA *RNA_def_string_dir_path(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description); +PropertyRNA *RNA_def_string_file_name(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description); PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description); void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc); diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index c6fed5cd8e6..e7fe86afd03 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -89,6 +89,7 @@ typedef enum PropertySubType { /* strings */ PROP_FILEPATH = 1, PROP_DIRPATH = 2, + PROP_FILENAME = 3, /* numbers */ PROP_UNSIGNED = 13, diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 8d05cbde74c..6bca237e02f 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -2113,6 +2113,20 @@ PropertyRNA *RNA_def_string_dir_path(StructOrFunctionRNA *cont_, const char *ide return prop; } +PropertyRNA *RNA_def_string_file_name(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, int maxlen, + const char *ui_name, const char *ui_description) +{ + ContainerRNA *cont= cont_; + PropertyRNA *prop; + + prop= RNA_def_property(cont, identifier, PROP_STRING, PROP_FILENAME); + if(maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen); + if(default_value) RNA_def_property_string_default(prop, default_value); + RNA_def_property_ui_text(prop, ui_name, ui_description); + + return prop; +} + PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description) { diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 544804b26d6..6610c5d8931 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -139,7 +139,7 @@ void WM_event_window_timer_sleep(struct wmWindow *win, struct wmTimer *timer, i int WM_menu_invoke (struct bContext *C, struct wmOperator *op, struct wmEvent *event); /* invoke callback, confirm menu + exec */ int WM_operator_confirm (struct bContext *C, struct wmOperator *op, struct wmEvent *event); - /* invoke callback, file selector "filename" unset + exec */ + /* invoke callback, file selector "path" unset + exec */ int WM_operator_filesel (struct bContext *C, struct wmOperator *op, struct wmEvent *event); /* poll callback, context checks */ int WM_operator_winactive (struct bContext *C); @@ -169,7 +169,7 @@ int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, int con void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring); void WM_operator_properties_free(struct PointerRNA *ptr); -void WM_operator_properties_filesel(struct wmOperatorType *ot, int filter); +void WM_operator_properties_filesel(struct wmOperatorType *ot, int filter, short type); /* operator as a python command (resultuing string must be free'd) */ char *WM_operator_pystring(struct bContext *C, struct wmOperatorType *ot, struct PointerRNA *opptr, int all_args); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 3c03d24ca93..79441f33610 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -895,9 +895,7 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa switch(event->val) { case EVT_FILESELECT_OPEN: case EVT_FILESELECT_FULL_OPEN: - { - char *dir= NULL; char *path= RNA_string_get_alloc(handler->op->ptr, "filename", NULL, 0); - + { if(event->val==EVT_FILESELECT_OPEN) ED_area_newspace(C, handler->op_area, SPACE_FILE); else @@ -908,8 +906,6 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa sfile->op= handler->op; ED_fileselect_set_params(sfile); - dir = NULL; - MEM_freeN(path); action= WM_HANDLER_BREAK; } @@ -920,7 +916,7 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa { /* XXX validate area and region? */ bScreen *screen= CTX_wm_screen(C); - char *path= RNA_string_get_alloc(handler->op->ptr, "filename", NULL, 0); + char *path= RNA_string_get_alloc(handler->op->ptr, "path", NULL, 0); if(screen != handler->filescreen) ED_screen_full_prevspace(C); @@ -1250,7 +1246,7 @@ void WM_event_fileselect_event(bContext *C, void *ophandle, int eventval) } } -/* operator is supposed to have a filled "filename" property */ +/* operator is supposed to have a filled "path" property */ /* optional property: filetype (XXX enum?) */ /* Idea is to keep a handler alive on window queue, owning the operator. diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 37cd424ac18..66724b57ff8 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -46,12 +46,16 @@ #include "BLI_blenlib.h" #include "BLI_dynstr.h" /*for WM_operator_pystring */ +#include "BLO_readfile.h" + #include "BKE_blender.h" #include "BKE_context.h" +#include "BKE_depsgraph.h" #include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_report.h" #include "BKE_scene.h" #include "BKE_utildefines.h" @@ -496,10 +500,10 @@ int WM_operator_confirm(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_CANCELLED; } -/* op->invoke, opens fileselect if filename property not set, otherwise executes */ +/* op->invoke, opens fileselect if path property not set, otherwise executes */ int WM_operator_filesel(bContext *C, wmOperator *op, wmEvent *event) { - if (RNA_property_is_set(op->ptr, "filename")) { + if (RNA_property_is_set(op->ptr, "path")) { return WM_operator_call(C, op); } else { @@ -509,9 +513,11 @@ int WM_operator_filesel(bContext *C, wmOperator *op, wmEvent *event) } /* default properties for fileselect */ -void WM_operator_properties_filesel(wmOperatorType *ot, int filter) +void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type) { - RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "Path to file."); + RNA_def_string_file_path(ot->srna, "path", "", FILE_MAX, "FilePath", "Path to file."); + RNA_def_string_file_name(ot->srna, "filename", "", FILE_MAX, "FileName", "Name of the file."); + RNA_def_string_dir_path(ot->srna, "directory", "", FILE_MAX, "Directory", "Directory of the file."); RNA_def_boolean(ot->srna, "filter_blender", (filter & BLENDERFILE), "Filter .blend files", ""); RNA_def_boolean(ot->srna, "filter_image", (filter & IMAGEFILE), "Filter image files", ""); @@ -521,6 +527,10 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter) RNA_def_boolean(ot->srna, "filter_sound", (filter & SOUNDFILE), "Filter sound files", ""); RNA_def_boolean(ot->srna, "filter_text", (filter & TEXTFILE), "Filter text files", ""); RNA_def_boolean(ot->srna, "filter_folder", (filter & FOLDERFILE), "Filter folders", ""); + + RNA_def_int(ot->srna, "type", type, FILE_LOADLIB, FILE_SPECIAL, + "File Browser Mode", "The setting for the file browser mode to load a .blend file, a library or a special file.", + FILE_LOADLIB, FILE_SPECIAL); } /* op->poll */ @@ -891,7 +901,7 @@ static void load_set_load_ui(wmOperator *op) static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event) { - RNA_string_set(op->ptr, "filename", G.sce); + RNA_string_set(op->ptr, "path", G.sce); load_set_load_ui(op); WM_event_add_fileselect(C, op); @@ -901,9 +911,9 @@ static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event) static int wm_open_mainfile_exec(bContext *C, wmOperator *op) { - char filename[FILE_MAX]; + char path[FILE_MAX]; - RNA_string_get(op->ptr, "filename", filename); + RNA_string_get(op->ptr, "path", path); load_set_load_ui(op); if(RNA_boolean_get(op->ptr, "load_ui")) @@ -915,7 +925,7 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op) // do it before for now, but is this correct with multiple windows? WM_event_add_notifier(C, NC_WINDOW, NULL); - WM_read_file(C, filename, op->reports); + WM_read_file(C, path, op->reports); return 0; } @@ -930,11 +940,168 @@ static void WM_OT_open_mainfile(wmOperatorType *ot) ot->exec= wm_open_mainfile_exec; ot->poll= WM_operator_winactive; - WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER); RNA_def_boolean(ot->srna, "load_ui", 1, "Load UI", "Load user interface setup in the .blend file."); } +static int wm_link_append_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + if (RNA_property_is_set(op->ptr, "path")) { + return WM_operator_call(C, op); + } + else { + /* XXX solve where to get last linked library from */ + RNA_string_set(op->ptr, "path", G.lib); + WM_event_add_fileselect(C, op); + return OPERATOR_RUNNING_MODAL; + } +} + +static short wm_link_append_flag(wmOperator *op) +{ + short flag = 0; + if (RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT; + if (RNA_boolean_get(op->ptr, "active_layer")) flag |= FILE_ACTIVELAY; + if (RNA_boolean_get(op->ptr, "relative_paths")) flag |= FILE_STRINGCODE; + if (RNA_boolean_get(op->ptr, "link")) flag |= FILE_LINK; + return flag; +} + +#define GROUP_MAX 32 + + +static void make_library_local(const char *libname, Main *main) +{ + struct Library *lib; + + /* and now find the latest append lib file */ + lib= main->library.first; + while(lib) { + if (BLI_streq(libname, lib->filename)) break; + lib= lib->id.next; + } + + /* make local */ + if(lib) { + all_local(lib, 1); + /* important we unset, otherwise these object wont + * link into other scenes from this blend file */ + flag_all_listbases_ids(LIB_APPEND_TAG, 0); + } +} + +static int wm_link_append_exec(bContext *C, wmOperator *op) +{ + char name[FILE_MAX], dir[FILE_MAX], libname[FILE_MAX], group[GROUP_MAX]; + int idcode; + BlendHandle *bh; + struct Main *main= CTX_data_main(C); + struct Scene *scene= CTX_data_scene(C); + struct Main *mainl= 0; + + struct ScrArea *sa= CTX_wm_area(C); + PropertyRNA *prop; + int totfiles=0; + short flag; + + name[0] = '\0'; + RNA_string_get(op->ptr, "filename", name); + RNA_string_get(op->ptr, "directory", dir); + + if ( BLO_is_a_library(dir, libname, group)==0 ) { + BKE_report(op->reports, RPT_ERROR, "Not a library"); + return OPERATOR_FINISHED; + } else if (group[0]==0) { + BKE_report(op->reports, RPT_ERROR, "Nothing indicated"); + return OPERATOR_FINISHED; + } else if (BLI_streq(main->name, libname)) { + BKE_report(op->reports, RPT_ERROR, "Cannot use current file as library"); + return OPERATOR_FINISHED; + } + + /* check if something is indicated for append/link */ + prop = RNA_struct_find_property(op->ptr, "files"); + if (prop) { + totfiles= RNA_property_collection_length(op->ptr, prop); + if (totfiles == 0) { + if (name[0] == '\0') { + BKE_report(op->reports, RPT_ERROR, "Nothing indicated"); + return OPERATOR_FINISHED; + } + } + } else if (name[0] == '\0') { + BKE_report(op->reports, RPT_ERROR, "Nothing indicated"); + return OPERATOR_FINISHED; + } + + /* now we have or selected, or an indicated file */ + if (RNA_boolean_get(op->ptr, "autoselect")) + scene_deselect_all(scene); + + bh = BLO_blendhandle_from_file(libname); + idcode = BLO_idcode_from_name(group); + + flag = wm_link_append_flag(op); + + if((flag & FILE_LINK)==0) { + /* tag everything, all untagged data can be made local */ + flag_all_listbases_ids(LIB_APPEND_TAG, 1); + } + + /* here appending/linking starts */ + mainl = BLO_library_append_begin(C, &bh, libname); + if (totfiles == 0) { + BLO_library_append_named_part(C, mainl, &bh, name, idcode, flag); + } else { + RNA_BEGIN(op->ptr, itemptr, "files") { + RNA_string_get(&itemptr, "name", name); + BLO_library_append_named_part(C, mainl, &bh, name, idcode, flag); + } + RNA_END; + } + BLO_library_append_end(C, mainl, &bh, idcode, flag); + + /* DISPLISTS? */ + recalc_all_library_objects(main); + + /* Append, rather than linking */ + if ((flag & FILE_LINK)==0) { + make_library_local(main, libname); + } + + /* do we need to do this? */ + if(scene) + DAG_scene_sort(scene); + + BLO_blendhandle_close(bh); + BLI_strncpy(G.lib, dir, FILE_MAX); + + WM_event_add_notifier(C, NC_WINDOW, NULL); + + return OPERATOR_FINISHED; +} + +static void WM_OT_link_append(wmOperatorType *ot) +{ + ot->name= "Link/Append from Library"; + ot->idname= "WM_OT_link_append"; + ot->description= "Link or Append from a Library .blend file"; + + ot->invoke= wm_link_append_invoke; + ot->exec= wm_link_append_exec; + ot->poll= WM_operator_winactive; + + WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_LOADLIB); + + RNA_def_boolean(ot->srna, "link", 1, "Link", "Link the objects or datablocks rather than appending."); + RNA_def_boolean(ot->srna, "autoselect", 1, "Select", "Select the linked objects."); + RNA_def_boolean(ot->srna, "active_layer", 1, "Active Layer", "Put the linked objects on the active layer."); + RNA_def_boolean(ot->srna, "relative_paths", 1, "Relative Paths", "Store the library path as a relative path to current .blend file."); + + RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", ""); +} + static int wm_recover_last_session_exec(bContext *C, wmOperator *op) { char scestr[FILE_MAX], filename[FILE_MAX]; @@ -987,7 +1154,7 @@ static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *even BLI_strncpy(name, G.sce, FILE_MAX); untitled(name); - RNA_string_set(op->ptr, "filename", name); + RNA_string_set(op->ptr, "path", name); WM_event_add_fileselect(C, op); @@ -997,20 +1164,20 @@ static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *even /* function used for WM_OT_save_mainfile too */ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) { - char filename[FILE_MAX]; + char path[FILE_MAX]; int compress; save_set_compress(op); compress= RNA_boolean_get(op->ptr, "compress"); - if(RNA_property_is_set(op->ptr, "filename")) - RNA_string_get(op->ptr, "filename", filename); + if(RNA_property_is_set(op->ptr, "path")) + RNA_string_get(op->ptr, "path", path); else { - BLI_strncpy(filename, G.sce, FILE_MAX); - untitled(filename); + BLI_strncpy(path, G.sce, FILE_MAX); + untitled(path); } - WM_write_file(C, filename, compress, op->reports); + WM_write_file(C, path, compress, op->reports); WM_event_add_notifier(C, NC_WM|ND_FILESAVE, NULL); @@ -1027,7 +1194,7 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot) ot->exec= wm_save_as_mainfile_exec; ot->poll= WM_operator_winactive; - WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER); RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file."); } @@ -1041,7 +1208,7 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event) BLI_strncpy(name, G.sce, FILE_MAX); untitled(name); - RNA_string_set(op->ptr, "filename", name); + RNA_string_set(op->ptr, "path", name); uiPupMenuSaveOver(C, op, name); return OPERATOR_RUNNING_MODAL; @@ -1057,7 +1224,7 @@ static void WM_OT_save_mainfile(wmOperatorType *ot) ot->exec= wm_save_as_mainfile_exec; ot->poll= WM_operator_winactive; - WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE); + WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER); RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file."); } @@ -1913,6 +2080,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_exit_blender); WM_operatortype_append(WM_OT_open_recentfile); WM_operatortype_append(WM_OT_open_mainfile); + WM_operatortype_append(WM_OT_link_append); WM_operatortype_append(WM_OT_recover_last_session); WM_operatortype_append(WM_OT_jobs_timer); WM_operatortype_append(WM_OT_save_as_mainfile); @@ -1944,6 +2112,7 @@ void wm_window_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "WM_OT_save_homefile", UKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "WM_OT_open_recentfile", OKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0); WM_keymap_add_item(keymap, "WM_OT_open_mainfile", OKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "WM_OT_link_append", OKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "WM_OT_save_mainfile", SKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "WM_OT_save_as_mainfile", SKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);