This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/src/filesel.c

2567 lines
59 KiB
C
Raw Normal View History

2002-10-12 11:37:38 +00:00
/**
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
2002-10-12 11:37:38 +00:00
#ifdef WIN32
#include <io.h>
#include <direct.h>
#include "BLI_winstuff.h"
#else
#include <unistd.h>
#include <sys/times.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include "MEM_guardedalloc.h"
#include "BMF_Api.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_linklist.h"
#include "BLI_storage_types.h"
#include "BLI_dynstr.h"
#include "IMB_imbuf.h"
#include "DNA_curve_types.h"
#include "DNA_image_types.h"
#include "DNA_ipo_types.h"
#include "DNA_vfont_types.h"
Biiig commit! Thanks to 2-3 weeks of cvs freeze... Render: - New; support for dual CPU render (SDL thread) Currently only works with alternating scanlines, but gives excellent performance. For both normal render as unified implemented. Note the "mutex" locks on z-transp buffer render and imbuf loads. - This has been made possible by major cleanups in render code, especially getting rid of globals (example Tin Tr Tg Tb Ta for textures) or struct OSA or using Materials or Texture data to write to. - Made normal render fully 4x32 floats too, and removed all old optimizes with chars or shorts. - Made normal render and unified render use same code for sky and halo render, giving equal (and better) results for halo render. Old render now also uses PostProcess options (brightness, mul, gamma) - Added option ("FBuf") in F10 Output Panel, this keeps a 4x32 bits buffer after render. Using PostProcess menu you will note an immediate re- display of image too (32 bits RGBA) - Added "Hue" and "Saturation" sliders to PostProcess options - Render module is still not having a "nice" API, but amount of dependencies went down a lot. Next todo: remove abusive "previewrender" code. The last main global in Render (struct Render) now can be re-used for fully controlling a render, to allow multiple "instances" of render to open. - Renderwindow now displays a smal bar on top with the stats, and keeps the stats after render too. Including "spare" page support. Not only easier visible that way, but also to remove the awkward code that was drawing stats in the Info header (extreme slow on some ATIs too) - Cleaned up blendef.h and BKE_utildefines.h, these two had overlapping defines. - I might have forgotten stuff... and will write a nice doc on the architecture!
2004-12-27 19:28:52 +00:00
#include "DNA_material_types.h"
2002-10-12 11:37:38 +00:00
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_texture_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "DNA_userdef_types.h"
#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_displist.h"
#include "BKE_library.h"
#include "BKE_curve.h"
#include "BKE_font.h"
#include "BKE_material.h"
#include "BIF_gl.h"
#include "BIF_interface.h"
#include "BIF_toolbox.h"
#include "BIF_mywindow.h"
#include "BIF_editview.h"
#include "BIF_space.h"
#include "BIF_screen.h"
#include "BIF_resources.h"
2002-10-12 11:37:38 +00:00
#include "BLO_readfile.h"
#include "BDR_editcurve.h"
#include "BPI_script.h"
2002-10-12 11:37:38 +00:00
#include "BSE_filesel.h"
#include "BSE_view.h"
#include "mydevice.h"
#include "blendef.h"
#include "nla.h"
#include "BIF_fsmenu.h" /* include ourselves */
2002-10-12 11:37:38 +00:00
#if defined WIN32 || defined __BeOS
int fnmatch(){return 0;}
#else
#include <fnmatch.h>
#endif
#ifndef WIN32
#include <sys/param.h>
#endif
#define FILESELHEAD 60
#define FILESEL_DY 16
/* for events */
2002-10-12 11:37:38 +00:00
#define NOTACTIVE 0
#define ACTIVATE 1
#define INACTIVATE 2
/* for state of file */
#define ACTIVE 2
2002-10-12 11:37:38 +00:00
#define STARTSWITH(x, y) (strncmp(x, y, sizeof(x) - 1) == 0)
static int is_a_library(SpaceFile *sfile, char *dir, char *group);
static void do_library_append(SpaceFile *sfile);
static void library_to_filelist(SpaceFile *sfile);
static void filesel_select_objects(struct SpaceFile *sfile);
static void active_file_object(struct SpaceFile *sfile);
static int groupname_to_code(char *group);
extern void countall(void);
2002-10-12 11:37:38 +00:00
/* local globals */
static rcti scrollrct, textrct, bar;
static int filebuty1, filebuty2, page_ofs, collumwidth, selecting=0;
static int filetoname= 0;
static float pixels_to_ofs;
static char otherdir[FILE_MAXDIR];
static ScrArea *otherarea;
/* FSMENU HANDLING */
/* FSMenuEntry's without paths indicate seperators */
typedef struct _FSMenuEntry FSMenuEntry;
struct _FSMenuEntry {
FSMenuEntry *next;
char *path;
};
static FSMenuEntry *fsmenu= 0;
2002-10-12 11:37:38 +00:00
int fsmenu_get_nentries(void)
{
FSMenuEntry *fsme;
int count= 0;
for (fsme= fsmenu; fsme; fsme= fsme->next)
count++;
return count;
}
int fsmenu_is_entry_a_seperator(int idx)
{
FSMenuEntry *fsme;
for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
idx--;
return (fsme && !fsme->path)?1:0;
}
char *fsmenu_get_entry(int idx)
{
FSMenuEntry *fsme;
for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
idx--;
return fsme?fsme->path:NULL;
}
char *fsmenu_build_menu(void)
{
DynStr *ds= BLI_dynstr_new();
FSMenuEntry *fsme;
char *menustr;
for (fsme= fsmenu; fsme; fsme= fsme->next) {
if (!fsme->path) {
/* clean consecutive seperators and ignore trailing ones */
if (fsme->next) {
if (fsme->next->path) {
BLI_dynstr_append(ds, "%l|");
} else {
FSMenuEntry *next= fsme->next;
fsme->next= next->next;
MEM_freeN(next);
}
}
2002-10-12 11:37:38 +00:00
} else {
BLI_dynstr_append(ds, fsme->path);
if (fsme->next) BLI_dynstr_append(ds, "|");
}
}
menustr= BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
return menustr;
}
static FSMenuEntry *fsmenu_get_last_separator(void)
{
FSMenuEntry *fsme, *lsep=NULL;
for (fsme= fsmenu; fsme; fsme= fsme->next)
if (!fsme->path)
lsep= fsme;
return lsep;
}
2002-10-12 11:37:38 +00:00
void fsmenu_insert_entry(char *path, int sorted)
{
FSMenuEntry *prev= fsmenu_get_last_separator();
FSMenuEntry *fsme= prev?prev->next:fsmenu;
2002-10-12 11:37:38 +00:00
for (; fsme; prev= fsme, fsme= fsme->next) {
if (fsme->path) {
if (BLI_streq(path, fsme->path)) {
return;
} else if (sorted && strcmp(path, fsme->path)<0) {
break;
}
}
}
fsme= MEM_mallocN(sizeof(*fsme), "fsme");
fsme->path= BLI_strdup(path);
if (prev) {
fsme->next= prev->next;
prev->next= fsme;
} else {
fsme->next= fsmenu;
fsmenu= fsme;
}
}
void fsmenu_append_seperator(void)
{
if (fsmenu) {
FSMenuEntry *fsme= fsmenu;
while (fsme->next) fsme= fsme->next;
fsme->next= MEM_mallocN(sizeof(*fsme), "fsme");
fsme->next->next= NULL;
fsme->next->path= NULL;
2002-10-12 11:37:38 +00:00
}
}
void fsmenu_remove_entry(int idx)
{
FSMenuEntry *prev= NULL, *fsme= fsmenu;
for (fsme= fsmenu; fsme && idx; prev= fsme, fsme= fsme->next)
if (fsme->path)
idx--;
if (fsme) {
if (prev) {
prev->next= fsme->next;
} else {
fsmenu= fsme->next;
}
MEM_freeN(fsme->path);
MEM_freeN(fsme);
}
}
void fsmenu_free(void)
{
FSMenuEntry *fsme= fsmenu;
while (fsme) {
FSMenuEntry *n= fsme->next;
if (fsme->path) MEM_freeN(fsme->path);
MEM_freeN(fsme);
fsme= n;
}
}
/* ******************* SORT ******************* */
static int compare_name(const void *a1, const void *a2)
{
const struct direntry *entry1=a1, *entry2=a2;
/* type is is equal to stat.st_mode */
2002-10-12 11:37:38 +00:00
if (S_ISDIR(entry1->type)){
if (S_ISDIR(entry2->type)==0) return (-1);
} else{
if (S_ISDIR(entry2->type)) return (1);
}
if (S_ISREG(entry1->type)){
if (S_ISREG(entry2->type)==0) return (-1);
} else{
if (S_ISREG(entry2->type)) return (1);
}
if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
/* make sure "." and ".." are always first */
if( strcmp(entry1->relname, ".")==0 ) return (-1);
if( strcmp(entry2->relname, ".")==0 ) return (1);
if( strcmp(entry1->relname, "..")==0 ) return (-1);
return (BLI_strcasecmp(entry1->relname,entry2->relname));
2002-10-12 11:37:38 +00:00
}
static int compare_date(const void *a1, const void *a2)
{
const struct direntry *entry1=a1, *entry2=a2;
/* type is equal to stat.st_mode */
2002-10-12 11:37:38 +00:00
if (S_ISDIR(entry1->type)){
if (S_ISDIR(entry2->type)==0) return (-1);
} else{
if (S_ISDIR(entry2->type)) return (1);
}
if (S_ISREG(entry1->type)){
if (S_ISREG(entry2->type)==0) return (-1);
} else{
if (S_ISREG(entry2->type)) return (1);
}
if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
/* make sure "." and ".." are always first */
if( strcmp(entry1->relname, ".")==0 ) return (-1);
if( strcmp(entry2->relname, ".")==0 ) return (1);
if( strcmp(entry1->relname, "..")==0 ) return (-1);
2002-10-12 11:37:38 +00:00
if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1;
if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1;
else return BLI_strcasecmp(entry1->relname,entry2->relname);
2002-10-12 11:37:38 +00:00
}
static int compare_size(const void *a1, const void *a2)
{
const struct direntry *entry1=a1, *entry2=a2;
/* type is equal to stat.st_mode */
2002-10-12 11:37:38 +00:00
if (S_ISDIR(entry1->type)){
if (S_ISDIR(entry2->type)==0) return (-1);
} else{
if (S_ISDIR(entry2->type)) return (1);
}
if (S_ISREG(entry1->type)){
if (S_ISREG(entry2->type)==0) return (-1);
} else{
if (S_ISREG(entry2->type)) return (1);
}
if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
/* make sure "." and ".." are always first */
if( strcmp(entry1->relname, ".")==0 ) return (-1);
if( strcmp(entry2->relname, ".")==0 ) return (1);
if( strcmp(entry1->relname, "..")==0 ) return (-1);
2002-10-12 11:37:38 +00:00
if ( entry1->s.st_size < entry2->s.st_size) return 1;
if ( entry1->s.st_size > entry2->s.st_size) return -1;
else return BLI_strcasecmp(entry1->relname,entry2->relname);
2002-10-12 11:37:38 +00:00
}
/* **************************************** */
void clear_global_filesel_vars()
{
selecting= 0;
}
void filesel_statistics(SpaceFile *sfile, int *totfile, int *selfile, float *totlen, float *sellen)
{
double len;
int a;
2002-10-12 11:37:38 +00:00
*totfile= *selfile= 0;
*totlen= *sellen= 0;
if(sfile->filelist==0) return;
for(a=0; a<sfile->totfile; a++) {
if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
(*totfile) ++;
len = sfile->filelist[a].s.st_size;
(*totlen) += (len/1048576.0);
if(sfile->filelist[a].flags & ACTIVE) {
(*selfile) ++;
(*sellen) += (len/1048576.0);
}
}
}
}
/* *************** HELP FUNCTIONS ******************* */
2002-10-12 11:37:38 +00:00
/* This is a really ugly function... its purpose is to
* take the space file name and clean it up, replacing
* excess file entry stuff (like /tmp/../tmp/../)
*/
void checkdir(char *dir)
{
short a;
char *start, *eind;
char tmp[FILE_MAXDIR+FILE_MAXFILE];
BLI_make_file_string(G.sce, tmp, dir, "");
strcpy(dir, tmp);
#ifdef WIN32
if(dir[0]=='.') { /* happens for example in FILE_MAIN */
2002-10-12 11:37:38 +00:00
dir[0]= '\\';
dir[1]= 0;
return;
}
while (start = strstr(dir, "\\..\\")) {
eind = start + strlen("\\..\\") - 1;
a = start-dir-1;
while (a>0) {
if (dir[a] == '\\') break;
a--;
}
strcpy(dir+a,eind);
}
while (start = strstr(dir,"\\.\\")){
eind = start + strlen("\\.\\") - 1;
strcpy(start,eind);
}
while (start = strstr(dir,"\\\\" )){
eind = start + strlen("\\\\") - 1;
strcpy(start,eind);
}
if(a = strlen(dir)){ /* remove the '\\' at the end */
2002-10-12 11:37:38 +00:00
while(a>0 && dir[a-1] == '\\'){
a--;
dir[a] = 0;
}
}
strcat(dir, "\\");
#else
if(dir[0]=='.') { /* happens, for example in FILE_MAIN */
2002-10-12 11:37:38 +00:00
dir[0]= '/';
dir[1]= 0;
return;
}
while ( (start = strstr(dir, "/../")) ) {
eind = start + strlen("/../") - 1;
a = start-dir-1;
while (a>0) {
if (dir[a] == '/') break;
a--;
}
strcpy(dir+a,eind);
}
while ( (start = strstr(dir,"/./")) ){
eind = start + strlen("/./") - 1;
strcpy(start,eind);
}
while ( (start = strstr(dir,"//" )) ){
eind = start + strlen("//") - 1;
strcpy(start,eind);
}
if( (a = strlen(dir)) ){ /* remove all '/' at the end */
2002-10-12 11:37:38 +00:00
while(dir[a-1] == '/'){
a--;
dir[a] = 0;
if (a<=0) break;
}
}
strcat(dir, "/");
#endif
}
/* not called when browsing .blend itself */
2002-10-12 11:37:38 +00:00
void test_flags_file(SpaceFile *sfile)
{
struct direntry *file;
int num;
file= sfile->filelist;
for(num=0; num<sfile->totfile; num++, file++) {
file->flags= 0;
file->type= file->s.st_mode; /* restore the mess below */
2002-10-12 11:37:38 +00:00
/* Don't check extensions for directories */
if (file->type & S_IFDIR)
2002-10-12 11:37:38 +00:00
continue;
if(sfile->type==FILE_BLENDER || sfile->type==FILE_LOADLIB) {
if(BLO_has_bfile_extension(file->relname)) {
file->flags |= BLENDERFILE;
2002-10-12 11:37:38 +00:00
if(sfile->type==FILE_LOADLIB) {
char name[FILE_MAXDIR+FILE_MAXFILE];
strcpy(name, sfile->dir);
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;
}
2002-10-12 11:37:38 +00:00
}
}
} else if (sfile->type==FILE_SPECIAL){
if(BLI_testextensie(file->relname, ".py")) {
file->flags |= PYSCRIPTFILE;
} else if( BLI_testextensie(file->relname, ".ttf")
|| BLI_testextensie(file->relname, ".ttc")
|| BLI_testextensie(file->relname, ".pfb")
|| BLI_testextensie(file->relname, ".otf")
|| BLI_testextensie(file->relname, ".otc")) {
file->flags |= FTFONTFILE;
} else if (G.have_quicktime){
if( BLI_testextensie(file->relname, ".jpg")
|| BLI_testextensie(file->relname, ".jpeg")
|| BLI_testextensie(file->relname, ".tga")
|| BLI_testextensie(file->relname, ".rgb")
|| BLI_testextensie(file->relname, ".bmp")
|| BLI_testextensie(file->relname, ".png")
|| BLI_testextensie(file->relname, ".iff")
|| BLI_testextensie(file->relname, ".lbm")
|| BLI_testextensie(file->relname, ".gif")
|| BLI_testextensie(file->relname, ".psd")
|| BLI_testextensie(file->relname, ".tif")
|| BLI_testextensie(file->relname, ".tiff")
|| BLI_testextensie(file->relname, ".pct")
|| BLI_testextensie(file->relname, ".pict")
|| BLI_testextensie(file->relname, ".pntg") //macpaint
|| BLI_testextensie(file->relname, ".qtif")
|| BLI_testextensie(file->relname, ".sgi")) {
file->flags |= IMAGEFILE;
}
else if(BLI_testextensie(file->relname, ".avi")
|| BLI_testextensie(file->relname, ".flc")
|| BLI_testextensie(file->relname, ".mov")
|| BLI_testextensie(file->relname, ".movie")
|| BLI_testextensie(file->relname, ".mv")) {
file->flags |= MOVIEFILE;
}
} else { // no quicktime
if(BLI_testextensie(file->relname, ".jpg")
|| BLI_testextensie(file->relname, ".tga")
|| BLI_testextensie(file->relname, ".rgb")
|| BLI_testextensie(file->relname, ".bmp")
|| BLI_testextensie(file->relname, ".png")
|| BLI_testextensie(file->relname, ".iff")
|| BLI_testextensie(file->relname, ".lbm")
|| BLI_testextensie(file->relname, ".sgi")) {
file->flags |= IMAGEFILE;
}
else if(BLI_testextensie(file->relname, ".avi")
|| BLI_testextensie(file->relname, ".mv")) {
file->flags |= MOVIEFILE;
}
Commit message and the brunt of the code courtesy of intrr, apologies for the size of this; Finally, the Sequencer audio support and global audio/animation sync stuff! (See http://intrr.org/blender/audiosequencer.html) Stuff that has been done: ./source/blender/blenloader/intern/writefile.c ./source/blender/blenloader/intern/readfile.c Added code to make it handle sounds used by audio strips, and to convert Scene data from older (<2.28) versions to init Scene global audio settings (Scene->audio) to defaults. ./source/blender/include/BSE_seqaudio.h ./source/blender/src/seqaudio.c The main audio routines that start/stop/scrub the audio stream at a certain frame position, provide the frame reference for the current stream position, mix the audio, convert the audio, mixdown the audio into a file. ./source/blender/makesdna/DNA_sound_types.h Introduced new variables in the bSound struct to accomodate the sample data after converted to the scene's global mixing format (stream, streamlen). Also added a new flag SOUND_FLAGS_SEQUENCE that gets set if the Sound belongs to a sequence strip. ./source/blender/makesdna/DNA_scene_types.h Added AudioData struct, which holds scene-global audio settings. ./source/blender/makesdna/DNA_sequence_types.h Added support for audio strips. Some variables to hold Panning/Attenuation information, position information, reference to the sample, and some flags. ./source/blender/makesdna/DNA_userdef_types.h ./source/blender/src/usiblender.c Added a "Mixing buffer size" userpref. Made the versions stuff initialize it to a default for versions <2.28. ./source/blender/makesdna/DNA_space_types.h ./source/blender/src/filesel.c Added a Cyan dot to .WAV files. Any other suggestions on a better color? :) ./source/blender/src/editsound.c Changes (fixes) to the WAV file loader, re-enabled some gameengine code that is needed for dealing with bSounds and bSamples. ./source/blender/src/editipo.c ./source/blender/src/drawseq.c ./source/blender/src/editnla.c ./source/blender/src/space.c ./source/blender/src/drawview.c ./source/blender/src/renderwin.c ./source/blender/src/headerbuttons.c - Created two different wrappers for update_for_newframe(), one which scrubs the audio, one which doesn't. - Replaced some of the occurences of update_for_newframe() with update_for_newframe_muted(), which doesn't scrub the audio. - In drawview.c: Changed the synchronization scheme to get the current audio position from the audio engine, and use that as a reference for setting CFRA. Implements a/v sync and framedrop. - In editipo.c: Changed handling of Fac IPOs to be usable for audio strips as volume envelopes. - In space.c: Added the mixing buffer size Userpref, enabled audio scrubbing (update_for_newframe()) for moving the sequence editor framebar. ./source/blender/src/editseq.c Added support for audio strips and a default directory for WAV files which gets saved from the last Shift-A operation. ./source/blender/src/buttons.c Added Scene-global audio sequencer settings in Sound buttons. ./source/blender/src/sequence.c Various stuff that deals with handling audio strips differently than usual strips.
2003-07-13 20:16:56 +00:00
else if(BLI_testextensie(file->relname, ".wav")) {
file->flags |= SOUNDFILE;
}
}
2002-10-12 11:37:38 +00:00
}
}
}
void sort_filelist(SpaceFile *sfile)
{
struct direntry *file;
int num;/* , act= 0; */
switch(sfile->sort) {
case FILE_SORTALPHA:
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
break;
case FILE_SORTDATE:
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_date);
break;
case FILE_SORTSIZE:
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_size);
break;
case FILE_SORTEXTENS:
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
break;
}
sfile->act= -1;
file= sfile->filelist;
for(num=0; num<sfile->totfile; num++, file++) {
file->flags &= ~HILITE;
}
}
void read_dir(SpaceFile *sfile)
{
int num, len;
char wdir[FILE_MAXDIR];
/* sfile->act is used for example in databrowse: double names of library objects */
2002-10-12 11:37:38 +00:00
sfile->act= -1;
if(sfile->type==FILE_MAIN) {
main_to_filelist(sfile);
return;
}
else if(sfile->type==FILE_LOADLIB) {
library_to_filelist(sfile);
if(sfile->libfiledata) return;
}
BLI_hide_dot_files(sfile->flag & FILE_HIDE_DOT);
BLI_getwdN(wdir);
sfile->totfile= BLI_getdir(sfile->dir, &(sfile->filelist));
chdir(wdir);
if(sfile->sort!=FILE_SORTALPHA) sort_filelist(sfile);
sfile->maxnamelen= 0;
for (num=0; num<sfile->totfile; num++) {
len = BMF_GetStringWidth(G.font, sfile->filelist[num].relname);
if (len > sfile->maxnamelen) sfile->maxnamelen = len;
if(filetoname) {
if(strcmp(sfile->file, sfile->filelist[num].relname)==0) {
sfile->ofs= num-( sfile->collums*(curarea->winy-FILESELHEAD-20)/(2*FILESEL_DY));
filetoname= 0;
}
}
}
test_flags_file(sfile);
filetoname= 0;
}
void freefilelist(SpaceFile *sfile)
{
int num;
num= sfile->totfile-1;
if (sfile->filelist==0) return;
for(; num>=0; num--){
MEM_freeN(sfile->filelist[num].relname);
2002-10-12 11:37:38 +00:00
if (sfile->filelist[num].string) MEM_freeN(sfile->filelist[num].string);
2002-10-12 11:37:38 +00:00
}
free(sfile->filelist);
sfile->filelist= 0;
}
static void split_sfile(SpaceFile *sfile, char *s1)
{
char string[FILE_MAXDIR+FILE_MAXFILE], dir[FILE_MAXDIR], file[FILE_MAXFILE];
strcpy(string, s1);
BLI_split_dirfile(string, dir, file);
if(sfile->filelist) {
if(strcmp(dir, sfile->dir)!=0) {
freefilelist(sfile);
}
else test_flags_file(sfile);
}
strcpy(sfile->file, file);
BLI_make_file_string(G.sce, sfile->dir, dir, "");
}
void parent(SpaceFile *sfile)
{
short a;
char *dir;
/* if databrowse: no parent */
2002-10-12 11:37:38 +00:00
if(sfile->type==FILE_MAIN && sfile->returnfunc) return;
dir= sfile->dir;
#ifdef WIN32
if(a = strlen(dir)) { /* remove all '/' at the end */
2002-10-12 11:37:38 +00:00
while(dir[a-1] == '\\') {
a--;
dir[a] = 0;
if (a<=0) break;
}
}
if(a = strlen(dir)) { /* then remove all until '/' */
2002-10-12 11:37:38 +00:00
while(dir[a-1] != '\\') {
a--;
dir[a] = 0;
if (a<=0) break;
}
}
if (a = strlen(dir)) {
if (dir[a-1] != '\\') strcat(dir,"\\");
}
else if(sfile->type!=FILE_MAIN) strcpy(dir,"\\");
#else
if( (a = strlen(dir)) ) { /* remove all '/' at the end */
2002-10-12 11:37:38 +00:00
while(dir[a-1] == '/') {
a--;
dir[a] = 0;
if (a<=0) break;
}
}
if( (a = strlen(dir)) ) { /* then remove until '/' */
2002-10-12 11:37:38 +00:00
while(dir[a-1] != '/') {
a--;
dir[a] = 0;
if (a<=0) break;
}
}
if ( (a = strlen(dir)) ) {
if (dir[a-1] != '/') strcat(dir,"/");
}
else if(sfile->type!=FILE_MAIN) strcpy(dir,"/");
#endif
/* to be sure */
BLI_make_exist(sfile->dir);
freefilelist(sfile);
sfile->ofs= 0;
scrarea_queue_winredraw(curarea);
}
void swapselect_file(SpaceFile *sfile)
{
struct direntry *file;
int num, act= 0;
file= sfile->filelist;
for(num=0; num<sfile->totfile; num++, file++) {
if(file->flags & ACTIVE) {
act= 1;
break;
}
}
file= sfile->filelist+2;
for(num=2; num<sfile->totfile; num++, file++) {
if(act) file->flags &= ~ACTIVE;
else file->flags |= ACTIVE;
}
}
static int find_active_file(SpaceFile *sfile, short x, short y)
{
int ofs;
if(y > textrct.ymax) y= textrct.ymax;
if(y <= textrct.ymin) y= textrct.ymin+1;
ofs= (x-textrct.xmin)/collumwidth;
if(ofs<0) ofs= 0;
ofs*= (textrct.ymax-textrct.ymin);
return sfile->ofs+ (ofs+textrct.ymax-y)/FILESEL_DY;
}
/* ********************** DRAW ******************************* */
static void calc_file_rcts(SpaceFile *sfile)
{
int tot, h, len;
float fac, start, totfile;
scrollrct.xmin= 15;
scrollrct.xmax= 35;
scrollrct.ymin= 10;
scrollrct.ymax= curarea->winy-10-FILESELHEAD;
textrct.xmin= scrollrct.xmax+10;
textrct.xmax= curarea->winx-10;
textrct.ymin= scrollrct.ymin;
textrct.ymax= scrollrct.ymax;
if(textrct.xmax-textrct.xmin <60) textrct.xmax= textrct.xmin+60;
len= (textrct.ymax-textrct.ymin) % FILESEL_DY;
textrct.ymin+= len;
scrollrct.ymin+= len;
filebuty1= curarea->winy-FILESELHEAD;
filebuty2= filebuty1+FILESELHEAD/2 -6;
/* amount of collums */
2002-10-12 11:37:38 +00:00
len= sfile->maxnamelen+25;
if(sfile->type==FILE_MAIN) len+= 100;
else if(sfile->flag & FILE_SHOWSHORT) len+= 100;
else len+= 380;
sfile->collums= (textrct.xmax-textrct.xmin)/len;
if(sfile->collums<1) sfile->collums= 1;
else if(sfile->collums>8) sfile->collums= 8;
/* this flag aint yet defined in user menu, needed? */
// if((U.flag & USER_FSCOLLUM)==0) sfile->collums= 1;
2002-10-12 11:37:38 +00:00
collumwidth= (textrct.xmax-textrct.xmin)/sfile->collums;
totfile= sfile->totfile + 0.5;
tot= FILESEL_DY*totfile;
if(tot) fac= ((float)sfile->collums*(scrollrct.ymax-scrollrct.ymin))/( (float)tot);
else fac= 1.0;
if(sfile->ofs<0) sfile->ofs= 0;
if(tot) start= ( (float)sfile->ofs)/(totfile);
else start= 0.0;
if(fac>1.0) fac= 1.0;
if(start+fac>1.0) {
sfile->ofs= ceil((1.0-fac)*totfile);
start= ( (float)sfile->ofs)/(totfile);
fac= 1.0-start;
}
bar.xmin= scrollrct.xmin+2;
bar.xmax= scrollrct.xmax-2;
h= (scrollrct.ymax-scrollrct.ymin)-4;
bar.ymax= scrollrct.ymax-2- start*h;
bar.ymin= bar.ymax- fac*h;
pixels_to_ofs= (totfile)/(float)(h+3);
page_ofs= fac*totfile;
}
int filescrollselect= 0;
static void draw_filescroll(SpaceFile *sfile)
{
if(scrollrct.ymin+10 >= scrollrct.ymax) return;
BIF_ThemeColor(TH_BACK);
2002-10-12 11:37:38 +00:00
glRecti(scrollrct.xmin, scrollrct.ymin, scrollrct.xmax, scrollrct.ymax);
uiEmboss(scrollrct.xmin, scrollrct.ymin, scrollrct.xmax, scrollrct.ymax, 1);
BIF_ThemeColor(TH_HEADER);
2002-10-12 11:37:38 +00:00
glRecti(bar.xmin+2, bar.ymin+2, bar.xmax-2, bar.ymax-2);
uiEmboss(bar.xmin+2, bar.ymin+2, bar.xmax-2, bar.ymax-2, filescrollselect);
}
static void linerect(int id, int x, int y)
2002-10-12 11:37:38 +00:00
{
if(id & ACTIVE) {
if(id & HILITE) BIF_ThemeColorShade(TH_HILITE, 20);
else BIF_ThemeColor(TH_HILITE);
}
else if(id & HILITE) BIF_ThemeColorShade(TH_BACK, 20);
else BIF_ThemeColor(TH_BACK);
2002-10-12 11:37:38 +00:00
glRects(x-17, y-3, x+collumwidth-21, y+11);
}
static void print_line(SpaceFile *sfile, struct direntry *files, int x, int y)
2002-10-12 11:37:38 +00:00
{
int boxcol=0;
2002-10-12 11:37:38 +00:00
char *s;
boxcol= files->flags & (HILITE + ACTIVE);
2002-10-12 11:37:38 +00:00
if(boxcol) {
linerect(boxcol, x, y);
2002-10-12 11:37:38 +00:00
}
if(files->flags & BLENDERFILE) {
cpack(0xA0A0);
glRects(x-14, y, x-8, y+7);
}
else if(files->flags & PSXFILE) {
cpack(0xA060B0);
glRects(x-14, y, x-8, y+7);
}
else if(files->flags & IMAGEFILE) {
cpack(0xF08040);
glRects(x-14, y, x-8, y+7);
}
else if(files->flags & MOVIEFILE) {
cpack(0x70A070);
glRects(x-14, y, x-8, y+7);
}
else if(files->flags & PYSCRIPTFILE) {
cpack(0x4477dd);
glRects(x-14, y, x-8, y+7);
}
Commit message and the brunt of the code courtesy of intrr, apologies for the size of this; Finally, the Sequencer audio support and global audio/animation sync stuff! (See http://intrr.org/blender/audiosequencer.html) Stuff that has been done: ./source/blender/blenloader/intern/writefile.c ./source/blender/blenloader/intern/readfile.c Added code to make it handle sounds used by audio strips, and to convert Scene data from older (<2.28) versions to init Scene global audio settings (Scene->audio) to defaults. ./source/blender/include/BSE_seqaudio.h ./source/blender/src/seqaudio.c The main audio routines that start/stop/scrub the audio stream at a certain frame position, provide the frame reference for the current stream position, mix the audio, convert the audio, mixdown the audio into a file. ./source/blender/makesdna/DNA_sound_types.h Introduced new variables in the bSound struct to accomodate the sample data after converted to the scene's global mixing format (stream, streamlen). Also added a new flag SOUND_FLAGS_SEQUENCE that gets set if the Sound belongs to a sequence strip. ./source/blender/makesdna/DNA_scene_types.h Added AudioData struct, which holds scene-global audio settings. ./source/blender/makesdna/DNA_sequence_types.h Added support for audio strips. Some variables to hold Panning/Attenuation information, position information, reference to the sample, and some flags. ./source/blender/makesdna/DNA_userdef_types.h ./source/blender/src/usiblender.c Added a "Mixing buffer size" userpref. Made the versions stuff initialize it to a default for versions <2.28. ./source/blender/makesdna/DNA_space_types.h ./source/blender/src/filesel.c Added a Cyan dot to .WAV files. Any other suggestions on a better color? :) ./source/blender/src/editsound.c Changes (fixes) to the WAV file loader, re-enabled some gameengine code that is needed for dealing with bSounds and bSamples. ./source/blender/src/editipo.c ./source/blender/src/drawseq.c ./source/blender/src/editnla.c ./source/blender/src/space.c ./source/blender/src/drawview.c ./source/blender/src/renderwin.c ./source/blender/src/headerbuttons.c - Created two different wrappers for update_for_newframe(), one which scrubs the audio, one which doesn't. - Replaced some of the occurences of update_for_newframe() with update_for_newframe_muted(), which doesn't scrub the audio. - In drawview.c: Changed the synchronization scheme to get the current audio position from the audio engine, and use that as a reference for setting CFRA. Implements a/v sync and framedrop. - In editipo.c: Changed handling of Fac IPOs to be usable for audio strips as volume envelopes. - In space.c: Added the mixing buffer size Userpref, enabled audio scrubbing (update_for_newframe()) for moving the sequence editor framebar. ./source/blender/src/editseq.c Added support for audio strips and a default directory for WAV files which gets saved from the last Shift-A operation. ./source/blender/src/buttons.c Added Scene-global audio sequencer settings in Sound buttons. ./source/blender/src/sequence.c Various stuff that deals with handling audio strips differently than usual strips.
2003-07-13 20:16:56 +00:00
else if(files->flags & SOUNDFILE) {
cpack(0xa0a000);
glRects(x-14, y, x-8, y+7);
}
else if(files->flags & FTFONTFILE) {
cpack(0xff2371);
glRects(x-14, y, x-8, y+7);
}
2002-10-12 11:37:38 +00:00
if(S_ISDIR(files->type)) BIF_ThemeColor(TH_TEXT_HI);
else BIF_ThemeColor(TH_TEXT);
2002-10-12 11:37:38 +00:00
s = files->string;
if(s) {
glRasterPos2i(x, y);
BMF_DrawString(G.font, files->relname);
x += sfile->maxnamelen + 100;
glRasterPos2i(x - BMF_GetStringWidth(G.font, files->size), y);
BMF_DrawString(G.font, files->size);
if(sfile->flag & FILE_SHOWSHORT) return;
#ifndef WIN32
/* rwx rwx rwx */
x += 20; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->mode1);
x += 30; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->mode2);
x += 30; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->mode3);
/* owner time date */
x += 30; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->owner);
#endif
x += 60; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->time);
x += 50; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->date);
}
else {
glRasterPos2i(x, y);
BMF_DrawString(G.font, files->relname);
if(files->nr) { /* extra info */
x+= sfile->maxnamelen+20;
glRasterPos2i(x, y);
BMF_DrawString(G.font, files->extra);
}
}
}
static int calc_filesel_line(SpaceFile *sfile, int nr, int *valx, int *valy)
2002-10-12 11:37:38 +00:00
{
/* get screen coordinate of a line */
2002-10-12 11:37:38 +00:00
int val, coll;
nr-= sfile->ofs;
/* amount of lines */
2002-10-12 11:37:38 +00:00
val= (textrct.ymax-textrct.ymin)/FILESEL_DY;
if (val == 0) coll = 0;
else coll= nr/val;
2002-10-12 11:37:38 +00:00
nr -= coll*val;
*valy= textrct.ymax-FILESEL_DY+3 - nr*FILESEL_DY;
*valx= coll*collumwidth + textrct.xmin+20;
if(nr<0 || coll > sfile->collums) return 0;
return 1;
}
static void set_active_file(SpaceFile *sfile, int act)
{
struct direntry *file;
int num, redraw= 0;
unsigned int newflag;
2002-10-12 11:37:38 +00:00
int old=0, newi=0;
file= sfile->filelist;
if(file==0) return;
for(num=0; num<sfile->totfile; num++, file++) {
if(num==act) {
if(selecting && num>1) {
newflag= HILITE | (file->flags & ~ACTIVE);
if(selecting==ACTIVATE) newflag |= ACTIVE;
if(file->flags != newflag) redraw|= 1;
file->flags= newflag;
}
else {
if(file->flags & HILITE);
else {
file->flags |= HILITE;
redraw|= 2;
newi= num;
}
}
}
else {
if(file->flags & HILITE) {
file->flags &= ~HILITE;
redraw|= 2;
old= num;
}
}
}
// removed frontbuffer draw here
if(redraw) {
2002-10-12 11:37:38 +00:00
scrarea_queue_winredraw(curarea);
}
}
static void draw_filetext(SpaceFile *sfile)
{
struct direntry *files;
int a, x, y;
short mval[2];
if(textrct.ymin+10 >= textrct.ymax) return;
/* box */
BIF_ThemeColor(TH_BACK);
2002-10-12 11:37:38 +00:00
glRecti(textrct.xmin, textrct.ymin, textrct.xmax, textrct.ymax);
/* collums */
2002-10-12 11:37:38 +00:00
x= textrct.xmin+collumwidth;
for(a=1; a<sfile->collums; a++, x+= collumwidth) {
cpack(0x303030);
sdrawline(x, textrct.ymin, x, textrct.ymax);
cpack(0xB0B0B0);
sdrawline(x+1, textrct.ymin, x+1, textrct.ymax);
}
if(sfile->filelist==0) return;
/* test: if mouse is not in area: clear HILITE */
2002-10-12 11:37:38 +00:00
getmouseco_areawin(mval);
if(mval[0]<0 || mval[0]>curarea->winx) {
files= sfile->filelist+sfile->ofs;
for(a= sfile->ofs; a<sfile->totfile; a++, files++) files->flags &= ~HILITE;
}
files= sfile->filelist+sfile->ofs;
for(a= sfile->ofs; a<sfile->totfile; a++, files++) {
if( calc_filesel_line(sfile, a, &x, &y)==0 ) break;
2002-10-12 11:37:38 +00:00
print_line(sfile, files, x, y);
2002-10-12 11:37:38 +00:00
}
/* clear drawing errors, with text at the right hand side: */
BIF_ThemeColor(TH_HEADER);
glRecti(textrct.xmax, textrct.ymin, textrct.xmax+10, textrct.ymax);
uiEmboss(textrct.xmin, textrct.ymin, textrct.xmax, textrct.ymax, 1);
2002-10-12 11:37:38 +00:00
}
void drawfilespace(ScrArea *sa, void *spacedata)
2002-10-12 11:37:38 +00:00
{
SpaceFile *sfile;
uiBlock *block;
float col[3];
2002-10-12 11:37:38 +00:00
int act, loadbutton;
short mval[2];
char name[20];
char *menu;
myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
2002-10-12 11:37:38 +00:00
BIF_GetThemeColor3fv(TH_HEADER, col); // basic undrawn color is border
glClearColor(col[0], col[1], col[2], 0.0);
2002-10-12 11:37:38 +00:00
glClear(GL_COLOR_BUFFER_BIT);
sfile= sa->spacedata.first;
if(sfile->filelist==NULL) {
2002-10-12 11:37:38 +00:00
read_dir(sfile);
calc_file_rcts(sfile);
/* calculate act */
2002-10-12 11:37:38 +00:00
getmouseco_areawin(mval);
act= find_active_file(sfile, mval[0], mval[1]);
if(act>=0 && act<sfile->totfile)
sfile->filelist[act].flags |= HILITE;
}
else calc_file_rcts(sfile);
/* HEADER */
sprintf(name, "win %d", sa->win);
block= uiNewBlock(&sa->uiblocks, name, UI_EMBOSS, UI_HELV, sa->win);
2002-10-12 11:37:38 +00:00
uiSetButLock( sfile->type==FILE_MAIN && sfile->returnfunc, NULL);
/* space available for load/save buttons? */
loadbutton= MAX2(80, 20+BMF_GetStringWidth(G.font, sfile->title));
if(textrct.xmax-textrct.xmin > loadbutton+20) {
if(sfile->title[0]==0) loadbutton= 0;
}
else loadbutton= 0;
uiDefBut(block, TEX, 1,"", textrct.xmin, filebuty1, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
uiDefBut(block, TEX, 2,"", textrct.xmin, filebuty2, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
if(loadbutton) {
uiSetCurFont(block, UI_HELV);
uiDefBut(block, BUT, 5, sfile->title, textrct.xmax-loadbutton, filebuty2, loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
uiDefBut(block, BUT, 6, "Cancel", textrct.xmax-loadbutton, filebuty1, loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
}
menu= fsmenu_build_menu();
if(menu[0]) // happens when no .Bfs is there, and first time browse
uiDefButS(block, MENU, 3, menu, scrollrct.xmin, filebuty1, scrollrct.xmax-scrollrct.xmin, 21, &sfile->menu, 0, 0, 0, 0, "");
2002-10-12 11:37:38 +00:00
MEM_freeN(menu);
uiDefBut(block, BUT, 4, "P", scrollrct.xmin, filebuty2, scrollrct.xmax-scrollrct.xmin, 21, 0, 0, 0, 0, 0, "Move to the parent directory (PKEY)");
uiDrawBlock(block);
2002-10-12 11:37:38 +00:00
draw_filescroll(sfile);
draw_filetext(sfile);
/* others diskfree etc ? */
scrarea_queue_headredraw(sa);
2002-10-12 11:37:38 +00:00
myortho2(-0.375, (float)(sa->winx)-0.375, -0.375, (float)(sa->winy)-0.375);
draw_area_emboss(sa);
2002-10-12 11:37:38 +00:00
sa->win_swap= WIN_BACK_OK;
2002-10-12 11:37:38 +00:00
}
static void do_filescroll(SpaceFile *sfile)
{
short mval[2], oldy, yo;
calc_file_rcts(sfile);
filescrollselect= 1;
/* for beauty */
scrarea_do_windraw(curarea);
screen_swapbuffers();
2002-10-12 11:37:38 +00:00
getmouseco_areawin(mval);
oldy= yo= mval[1];
while(get_mbut()&L_MOUSE) {
getmouseco_areawin(mval);
if(yo!=mval[1]) {
int dy= floor(0.5+((float)(oldy-mval[1]))*pixels_to_ofs);
if(dy) {
sfile->ofs+= dy;
if(sfile->ofs<0) {
sfile->ofs= 0;
oldy= mval[1];
}
else oldy= floor(0.5+ (float)oldy - (float)dy/pixels_to_ofs);
scrarea_do_windraw(curarea);
screen_swapbuffers();
}
yo= mval[1];
}
else BIF_wait_for_statechange();
}
filescrollselect= 0;
/* for beauty */
scrarea_do_windraw(curarea);
screen_swapbuffers();
2002-10-12 11:37:38 +00:00
}
2003-01-27 23:57:43 +00:00
static void do_filescrollwheel(SpaceFile *sfile, int move)
{
// by phase
int lines, rt;
calc_file_rcts(sfile);
lines = (int)(textrct.ymax-textrct.ymin)/FILESEL_DY;
rt = lines * sfile->collums;
if(sfile->totfile > rt) {
sfile->ofs+= move;
if( sfile->ofs + rt > sfile->totfile + 1)
sfile->ofs = sfile->totfile - rt + 1;
}
if(sfile->ofs<0) {
sfile->ofs= 0;
}
}
2002-10-12 11:37:38 +00:00
void activate_fileselect(int type, char *title, char *file, void (*func)(char *))
{
SpaceFile *sfile;
char group[24], name[FILE_MAXDIR], temp[FILE_MAXDIR];
if(curarea==0) return;
if(curarea->win==0) return;
newspace(curarea, SPACE_FILE);
scrarea_queue_winredraw(curarea);
/* sometime double, when area already is SPACE_FILE with a different file name */
2002-10-12 11:37:38 +00:00
addqueue(curarea->headwin, CHANGED, 1);
name[2]= 0;
strcpy(name, file);
sfile= curarea->spacedata.first;
/* sfile wants a (*)(short), but get (*)(char*) */
sfile->returnfunc= func;
sfile->type= type;
sfile->ofs= 0;
/* sfile->act is used for databrowse: double names of library objects */
2002-10-12 11:37:38 +00:00
sfile->act= -1;
if(BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) sfile->flag |= FILE_STRINGCODE;
else sfile->flag &= ~FILE_STRINGCODE;
if(type==FILE_MAIN) {
char *groupname;
strcpy(sfile->file, name+2);
groupname = BLO_idcode_to_name( GS(name) );
if (groupname) {
strcpy(sfile->dir, groupname);
strcat(sfile->dir, "/");
}
/* free all */
2002-10-12 11:37:38 +00:00
if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
sfile->libfiledata= 0;
freefilelist(sfile);
}
else if(type==FILE_LOADLIB) {
strcpy(sfile->dir, name);
if( is_a_library(sfile, temp, group) ) {
/* force a reload of the library-filelist */
freefilelist(sfile);
2002-10-12 11:37:38 +00:00
}
else {
split_sfile(sfile, name);
if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
sfile->libfiledata= NULL;
2002-10-12 11:37:38 +00:00
}
}
else { /* FILE_BLENDER */
split_sfile(sfile, name); /* test filelist too */
2002-10-12 11:37:38 +00:00
/* free: filelist and libfiledata became incorrect */
2002-10-12 11:37:38 +00:00
if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
sfile->libfiledata= 0;
}
BLI_strncpy(sfile->title, title, sizeof(sfile->title));
filetoname= 1;
}
void activate_imageselect(int type, char *title, char *file, void (*func)(char *))
{
SpaceImaSel *simasel;
char dir[FILE_MAXDIR], name[FILE_MAXFILE];
if(curarea==0) return;
if(curarea->win==0) return;
newspace(curarea, SPACE_IMASEL);
/* sometimes double, when area is already SPACE_FILE with a different file name */
2002-10-12 11:37:38 +00:00
addqueue(curarea->headwin, CHANGED, 1);
addqueue(curarea->win, CHANGED, 1);
name[2]= 0;
strcpy(name, file);
simasel= curarea->spacedata.first;
simasel->returnfunc= func;
if(BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) simasel->mode |= IMS_STRINGCODE;
else simasel->mode &= ~IMS_STRINGCODE;
BLI_split_dirfile(name, dir, simasel->file);
if(strcmp(dir, simasel->dir)!=0) simasel->fase= 0;
strcpy(simasel->dir, dir);
BLI_strncpy(simasel->title, title, sizeof(simasel->title));
/* filetoname= 1; */
}
void activate_databrowse(ID *id, int idcode, int fromcode, int retval, short *menup, void (*func)(unsigned short))
{
ListBase *lb;
SpaceFile *sfile;
char str[32];
if(id==0) {
lb= wich_libbase(G.main, idcode);
id= lb->last;
2002-10-12 11:37:38 +00:00
}
if(id) strcpy(str, id->name);
else return;
activate_fileselect(FILE_MAIN, "SELECT DATABLOCK", str, (void (*) (char*))func);
sfile= curarea->spacedata.first;
sfile->retval= retval;
sfile->ipotype= fromcode;
sfile->menup= menup;
}
void filesel_prevspace()
{
SpaceFile *sfile;
sfile= curarea->spacedata.first;
if(sfile->next) {
BLI_remlink(&curarea->spacedata, sfile);
BLI_addtail(&curarea->spacedata, sfile);
sfile= curarea->spacedata.first;
if (sfile->spacetype == SPACE_SCRIPT) {
SpaceScript *sc = (SpaceScript *)sfile;
if (sc->script) sc->script->flags &=~SCRIPT_FILESEL;
}
2002-10-12 11:37:38 +00:00
newspace(curarea, sfile->spacetype);
}
else newspace(curarea, SPACE_INFO);
}
static int countselect(SpaceFile *sfile)
{
int a, count=0;
for(a=0; a<sfile->totfile; a++) {
if(sfile->filelist[a].flags & ACTIVE) {
count++;
}
}
return count;
}
static int getotherdir(void)
{
ScrArea *sa;
SpaceFile *sfile=0;
sa= G.curscreen->areabase.first;
while(sa) {
if(sa!=curarea) {
if(sa->spacetype==SPACE_FILE) {
/* already found one */
2002-10-12 11:37:38 +00:00
if(sfile) return 0;
sfile= sa->spacedata.first;
if(sfile->type & FILE_UNIX) {
otherarea= sa;
BLI_make_file_string(G.sce, otherdir, sfile->dir, "");
}
else sfile= 0;
}
}
sa= sa->next;
}
if(sfile) return 1;
return 0;
}
static void reread_other_fs(void)
{
SpaceFile *sfile;
/* watch it: only call when getotherdir returned OK */
2002-10-12 11:37:38 +00:00
sfile= otherarea->spacedata.first;
freefilelist(sfile);
scrarea_queue_winredraw(otherarea);
}
void free_filesel_spec(char *dir)
{
/* all filesels with 'dir' are freed */
2002-10-12 11:37:38 +00:00
bScreen *sc;
sc= G.main->screen.first;
while(sc) {
ScrArea *sa= sc->areabase.first;
while(sa) {
SpaceLink *sl= sa->spacedata.first;
while(sl) {
if(sl->spacetype==SPACE_FILE) {
SpaceFile *sfile= (SpaceFile*) sl;
if (BLI_streq(sfile->dir, dir)) {
freefilelist(sfile);
}
}
sl= sl->next;
}
sa= sa->next;
}
sc= sc->id.next;
}
}
static void filesel_execute(SpaceFile *sfile)
{
struct direntry *files;
char name[FILE_MAXDIR];
int a;
filesel_prevspace();
if(sfile->type==FILE_LOADLIB) {
do_library_append(sfile);
BIF_undo_push("Append from file");
2002-10-12 11:37:38 +00:00
allqueue(REDRAWALL, 1);
}
else if(sfile->returnfunc) {
fsmenu_insert_entry(sfile->dir, 1);
if(sfile->type==FILE_MAIN) {
if (sfile->menup) {
if(sfile->act>=0) {
if(sfile->filelist) {
files= sfile->filelist+sfile->act;
*sfile->menup= files->nr;
}
else *sfile->menup= sfile->act+1;
}
else {
*sfile->menup= -1;
for(a=0; a<sfile->totfile; a++) {
if( strcmp(sfile->filelist[a].relname, sfile->file)==0) {
*sfile->menup= a+1;
break;
}
}
}
}
sfile->returnfunc((char*) (long)sfile->retval);
2002-10-12 11:37:38 +00:00
}
else {
if(strncmp(sfile->title, "Save", 4)==0) free_filesel_spec(sfile->dir);
if(strncmp(sfile->title, "Export", 6)==0) free_filesel_spec(sfile->dir);
2002-10-12 11:37:38 +00:00
strcpy(name, sfile->dir);
strcat(name, sfile->file);
if(sfile->flag & FILE_STRINGCODE) BLI_makestringcode(G.sce, name);
sfile->returnfunc(name);
}
}
}
static void do_filesel_buttons(short event, SpaceFile *sfile)
{
char butname[FILE_MAXDIR];
if (event == 1) {
if (strchr(sfile->file, '*') || strchr(sfile->file, '?') || strchr(sfile->file, '[')) {
int i, match = FALSE;
for (i = 2; i < sfile->totfile; i++) {
if (fnmatch(sfile->file, sfile->filelist[i].relname, 0) == 0) {
sfile->filelist[i].flags |= ACTIVE;
match = TRUE;
}
}
if (match) strcpy(sfile->file, "");
if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
scrarea_queue_winredraw(curarea);
}
}
else if(event== 2) {
/* reuse the butname variable */
checkdir(sfile->dir);
BLI_make_file_string(G.sce, butname, sfile->dir, "");
/* strip the trailing slash if its a real dir */
if (strlen(butname)!=1)
butname[strlen(butname)-1]=0;
if(sfile->type & FILE_UNIX) {
if (!BLI_exists(butname)) {
if (okee("Makedir")) {
BLI_recurdir_fileops(butname);
if (!BLI_exists(butname)) parent(sfile);
} else parent(sfile);
}
}
freefilelist(sfile);
sfile->ofs= 0;
scrarea_queue_winredraw(curarea);
}
else if(event== 3) {
char *selected= fsmenu_get_entry(sfile->menu-1);
/* which string */
2002-10-12 11:37:38 +00:00
if (selected) {
strcpy(sfile->dir, selected);
BLI_make_exist(sfile->dir);
checkdir(sfile->dir);
freefilelist(sfile);
sfile->ofs= 0;
scrarea_queue_winredraw(curarea);
}
sfile->act= -1;
}
else if(event== 4) parent(sfile);
else if(event== 5) {
if(sfile->type) filesel_execute(sfile);
}
else if(event== 6) filesel_prevspace();
}
/****/
typedef void (*ReplaceFP)(ID *oldblock, ID *newblock);
static void change_id_link(void *linkpv, void *newlinkv) {
ID **linkp= (ID**) linkpv;
ID *newlink= newlinkv;
if (*linkp) {
(*linkp)->us--;
}
(*linkp)= newlink;
if (newlink) {
id_us_plus(newlink);
}
}
static void replace_image(ID *oldblock, ID *newblock) {
Image *oldima= (Image*) oldblock;
Image *newima= (Image*) newblock;
bScreen *sc;
Scene *sce;
Tex *tex;
Mesh *me;
for (tex= G.main->tex.first; tex; tex= tex->id.next) {
if (tex->env && tex->env->type == ENV_LOAD && tex->env->ima == oldima)
change_id_link(&tex->env->ima, newima);
if (tex->ima == oldima)
change_id_link(&tex->ima, newima);
}
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
if (sce->ima == oldima)
change_id_link(&sce->ima, newima);
}
for (sc= G.main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
BGpic *bgp= v3d->bgpic;
if (bgp && bgp->ima == oldima)
change_id_link(&bgp->ima, newima);
} else if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage*) sl;
if (sima->image == oldima)
change_id_link(&sima->image, newima);
}
}
}
}
for (me= G.main->mesh.first; me; me= me->id.next) {
TFace *tfaces= me->tface;
if (tfaces) {
int i;
for (i=0; i<me->totface; i++) {
TFace *tf= &tfaces[i];
if (tf->tpage == oldima) {
/* not change_id_link, tpage's aren't owners :(
* see hack below.
*/
tf->tpage= newima;
}
}
}
}
/* Nasty hack, necessary because tpages don't act
* as a user, so there lots of image user count
* munging occurs... this will ensure the image
* really dies.
*/
oldima->id.us= 0;
}
static void replace_material(ID *oldblock, ID *newblock)
{
Material *old= (Material*) oldblock;
Material *new= (Material*) newblock;
Material ***matarar;
ID *id;
Object *ob;
int a;
ob= G.main->object.first;
while(ob) {
if(ob->totcol && ob->id.lib==0) {
matarar= give_matarar(ob);
for(a=1; a<=ob->totcol; a++) {
if(ob->mat[a-1] == old) {
if(old) old->id.us--;
id_us_plus((ID *)new);
ob->mat[a-1]= new;
}
id= ob->data;
if( (*matarar)[a-1] == old && id->lib==0) {
if(old) old->id.us--;
id_us_plus((ID *)new);
(*matarar)[a-1]= new;
}
}
}
ob= ob->id.next;
}
}
static ReplaceFP get_id_replace_function(int idcode) {
switch (idcode) {
case ID_MA:
return &replace_material;
case ID_IM:
return &replace_image;
default:
return NULL;
}
}
static void databrowse_replace(SpaceFile *sfile, int idcode)
{
ReplaceFP replace_func= get_id_replace_function(idcode);
if (!replace_func) {
error("Replacing %s blocks is unsupported", BLO_idcode_to_name(idcode));
} else if (sfile->act==-1) {
error("Select target with leftmouse");
} else {
ID *target= (ID*) sfile->filelist[sfile->act].poin;
if (target) {
char buf[128];
sprintf(buf, "Replace with %s: %s", BLO_idcode_to_name(idcode), target->name+2);
if (okee(buf)) {
int i;
for (i = 0; i <sfile->totfile; i++)
if ((sfile->filelist[i].flags&ACTIVE) && sfile->filelist[i].poin!=target)
replace_func(sfile->filelist[i].poin, target);
}
}
}
freefilelist(sfile);
scrarea_queue_winredraw(curarea);
}
static void fs_fake_users(SpaceFile *sfile)
{
ID *id;
int a;
/* only for F4 DATABROWSE */
2002-10-12 11:37:38 +00:00
if(sfile->returnfunc) return;
for(a=0; a<sfile->totfile; a++) {
if(sfile->filelist[a].flags & ACTIVE) {
id= (ID *)sfile->filelist[a].poin;
if(id) {
if( id->flag & LIB_FAKEUSER) {
id->flag -= LIB_FAKEUSER;
id->us--;
}
else {
id->flag |= LIB_FAKEUSER;
id->us++;
}
}
}
}
freefilelist(sfile);
scrarea_queue_winredraw(curarea);
}
static int get_hilited_entry(SpaceFile *sfile)
{
int a;
for(a=0; a<sfile->totfile; a++) {
if(sfile->filelist[a].flags & HILITE) {
return a;
}
}
return -1;
}
void winqreadfilespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
2002-10-12 11:37:38 +00:00
{
unsigned short event= evt->event;
short val= evt->val;
2002-10-12 11:37:38 +00:00
static int acto=0;
SpaceFile *sfile;
int act, do_draw= 0, i, test, ret = 0;
short qual, mval[2];
char str[FILE_MAXDIR+FILE_MAXFILE+12];
sfile= curarea->spacedata.first;
if(sfile==0) return;
if(sfile->filelist==0) {
return;
}
if(curarea->win==0) return;
calc_file_rcts(sfile);
getmouseco_areawin(mval);
/* prevent looping */
2002-10-12 11:37:38 +00:00
if(selecting && !(get_mbut() & R_MOUSE)) selecting= 0;
if(val) {
if( event!=RETKEY && event!=PADENTER)
if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
switch(event) {
case UI_BUT_EVENT:
do_filesel_buttons(val, sfile);
break;
2003-01-27 23:57:43 +00:00
case WHEELDOWNMOUSE:
2003-01-28 11:14:38 +00:00
do_filescrollwheel(sfile, U.wheellinescroll);
2003-01-27 23:57:43 +00:00
act= find_active_file(sfile, mval[0], mval[1]);
set_active_file(sfile, act);
do_draw= 1;
break;
case WHEELUPMOUSE:
2003-01-28 11:14:38 +00:00
do_filescrollwheel(sfile, -U.wheellinescroll);
2003-01-27 23:57:43 +00:00
act= find_active_file(sfile, mval[0], mval[1]);
set_active_file(sfile, act);
do_draw= 1;
break;
2002-10-12 11:37:38 +00:00
case LEFTMOUSE:
case MIDDLEMOUSE:
if(mval[0]>scrollrct.xmin && mval[0]<scrollrct.xmax && mval[1]>scrollrct.ymin && mval[1]<scrollrct.ymax) {
do_filescroll(sfile);
}
else if(mval[0]>textrct.xmin && mval[0]<textrct.xmax && mval[1]>textrct.ymin && mval[1]<textrct.ymax) {
/* sfile->act is used in databrowse: double names of library objects */
2002-10-12 11:37:38 +00:00
sfile->act= act= find_active_file(sfile, mval[0], mval[1]);
if(act>=0 && act<sfile->totfile) {
if(S_ISDIR(sfile->filelist[act].type)) {
strcat(sfile->dir, sfile->filelist[act].relname);
strcat(sfile->dir,"/");
checkdir(sfile->dir);
freefilelist(sfile);
sfile->ofs= 0;
do_draw= 1;
}
else {
if( strcmp(sfile->file, sfile->filelist[act].relname)) {
do_draw= 1;
strcpy(sfile->file, sfile->filelist[act].relname);
}
if(event==MIDDLEMOUSE && sfile->type) filesel_execute(sfile);
}
}
}
break;
case RIGHTMOUSE:
act= find_active_file(sfile, mval[0], mval[1]);
acto= act;
if(act>=0 && act<sfile->totfile) {
if (sfile->filelist[act].flags & ACTIVE) {
sfile->filelist[act].flags &= ~ACTIVE;
selecting = INACTIVATE;
}
else {
test= sfile->filelist[act].relname[0];
if (act>=2 || test!='.') sfile->filelist[act].flags |= ACTIVE;
selecting = ACTIVATE;
}
do_draw= 1;
}
break;
case MOUSEY:
act= find_active_file(sfile, mval[0], mval[1]);
if (act!=acto) {
set_active_file(sfile, act);
}
if(selecting && act!=acto) {
while(1) {
if (acto >= 2 && acto < sfile->totfile) {
if (selecting == ACTIVATE) sfile->filelist[acto].flags |= ACTIVE;
else if (selecting == INACTIVATE) sfile->filelist[acto].flags &= ~ACTIVE;
}
if (acto < act) acto++;
else if (acto > act) acto--;
else break;
}
}
acto= act;
break;
case PAGEUPKEY:
sfile->ofs-= page_ofs;
do_draw= 1;
break;
case PAGEDOWNKEY:
sfile->ofs+= page_ofs;
do_draw= 1;
break;
case HOMEKEY:
sfile->ofs= 0;
do_draw= 1;
break;
case ENDKEY:
sfile->ofs= sfile->totfile;
do_draw= 1;
break;
case AKEY:
swapselect_file(sfile);
if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
do_draw= 1;
break;
case BKEY:
case CKEY:
case LKEY:
if(event==LKEY && sfile->type==FILE_MAIN && (G.qual & LR_CTRLKEY)) {
databrowse_replace(sfile, groupname_to_code(sfile->dir));
break;
}
/* pass */
2002-10-12 11:37:38 +00:00
case MKEY:
if(sfile->type==FILE_MAIN) break;
if(!countselect(sfile)) {
error("No files selected");
break;
}
if(!getotherdir()) {
error("No second fileselect");
break;
}
if (!strcmp(sfile->dir, otherdir)) {
error("Same directories");
break;
}
if(event==BKEY) sprintf(str, "Backup to %s", otherdir);
else if(event==CKEY) sprintf(str, "Copy to %s", otherdir);
else if(event==LKEY) sprintf(str, "Linked copy to %s", otherdir);
else if(event==MKEY) sprintf(str, "Move to %s", otherdir);
if (!okee(str)) break;
for (i = 0; i<sfile->totfile; i++){
if (sfile->filelist[i].flags & ACTIVE) {
BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[i].relname);
if(event==BKEY) ret= BLI_backup(sfile->filelist[i].relname, sfile->dir, otherdir);
else if(event==CKEY) ret= BLI_copy_fileops(str, otherdir);
else if(event==LKEY) ret= BLI_link(str, otherdir);
else if(event==MKEY) ret= BLI_move(str, otherdir);
if (ret) {error("Command failed, see console"); break;}
else sfile->filelist[i].flags &= ~ACTIVE;
}
}
do_draw= 1;
if(event==BKEY || event==MKEY)
freefilelist(sfile);
reread_other_fs();
break;
case XKEY:
test = get_hilited_entry(sfile);
if (test != -1 && !(S_ISDIR(sfile->filelist[test].type))){
BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[test].relname);
if( okee("Remove %s", str) ) {
ret = BLI_delete(str, 0, 0);
if (ret) {
error("Command failed, see console");
} else {
freefilelist(sfile);
do_draw= 1;
}
}
}
break;
2002-10-12 11:37:38 +00:00
case RKEY:
if(sfile->type==FILE_MAIN) {
databrowse_replace(sfile, groupname_to_code(sfile->dir));
break;
}
/* pass to TKEY! */
2002-10-12 11:37:38 +00:00
case TKEY:
if(sfile->type==FILE_MAIN) break;
if(!countselect(sfile)) {
error("No files selected");
break;
}
if(event==TKEY) sprintf(str, "Touch");
else if(event==RKEY) sprintf(str, "Remove from %s", sfile->dir);
qual= G.qual; /* because after okee() you released the SHIFT */
2002-10-12 11:37:38 +00:00
if (!okee(str)) break;
for (i = 0; i <sfile->totfile; i++) {
if (sfile->filelist[i].flags & ACTIVE) {
BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[i].relname);
if(event==TKEY) ret= BLI_touch(str);
else if(event==RKEY) {
if(qual & LR_SHIFTKEY) ret= BLI_delete(str, 0, 1);
else if(S_ISDIR(sfile->filelist[i].type)) ret= BLI_delete(str, 1, 0);
else ret= BLI_delete(str, 0, 0);
}
if (ret) {error("Command failed, see console"); break;}
else sfile->filelist[i].flags &= ~ACTIVE;
}
}
do_draw= 1;
freefilelist(sfile);
break;
case PKEY:
if(G.qual & LR_SHIFTKEY) {
extern char bprogname[]; /* usiblender.c */
sprintf(str, "%s -a \"%s%s\"", bprogname, sfile->dir, sfile->file);
system(str);
}
else
parent(sfile);
break;
case IKEY:
if(sfile->type==FILE_MAIN) break;
sprintf(str, "$IMAGEEDITOR %s%s", sfile->dir, sfile->file);
system(str);
break;
case EKEY:
if(sfile->type==FILE_MAIN) break;
sprintf(str, "$WINEDITOR %s%s", sfile->dir, sfile->file);
system(str);
break;
case FKEY:
if(sfile->type==FILE_MAIN) {
fs_fake_users(sfile);
}
break;
case PADPLUSKEY:
case EQUALKEY:
if (G.qual & LR_CTRLKEY) BLI_newname(sfile->file, +100);
else if (G.qual & LR_SHIFTKEY) BLI_newname(sfile->file, +10);
else BLI_newname(sfile->file, +1);
do_draw= 1;
break;
case PADMINUS:
case MINUSKEY:
if (G.qual & LR_CTRLKEY) BLI_newname(sfile->file, -100);
else if (G.qual & LR_SHIFTKEY) BLI_newname(sfile->file, -10);
else BLI_newname(sfile->file, -1);
do_draw= 1;
break;
case BACKSLASHKEY:
case SLASHKEY:
if(sfile->type==FILE_MAIN) break;
#ifdef WIN32
strcpy(sfile->dir, "\\");
#else
strcpy(sfile->dir, "/");
#endif
freefilelist(sfile);
sfile->ofs= 0;
do_draw= 1;
break;
case PERIODKEY:
freefilelist(sfile);
do_draw= 1;
break;
case ESCKEY:
filesel_prevspace();
break;
case PADENTER:
case RETKEY:
if(sfile->type) filesel_execute(sfile);
break;
}
}
else if(event==RIGHTMOUSE) {
selecting = NOTACTIVE;
if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
}
else if(event==LEFTMOUSE) {
if(sfile->type==FILE_MAIN) active_file_object(sfile);
}
/* XXX, stupid patch, curarea can become undone
* because of file loading... fixme zr
*/
if(do_draw && curarea) scrarea_queue_winredraw(curarea);
}
/* ************* LIBRARY FILESEL ******************* */
static int groupname_to_code(char *group)
{
char buf[32];
char *lslash;
BLI_strncpy(buf, group, 31);
2002-10-12 11:37:38 +00:00
lslash= BLI_last_slash(buf);
if (lslash)
lslash[0]= '\0';
return BLO_idcode_from_name(buf);
}
static int is_a_library(SpaceFile *sfile, char *dir, char *group)
{
/* return ok when a blenderfile, in dir is the filename,
* in group the type of libdata
2002-10-12 11:37:38 +00:00
*/
int len;
char *fd;
strcpy(dir, sfile->dir);
len= strlen(dir);
if(len<7) return 0;
if( dir[len-1] != '/' && dir[len-1] != '\\') return 0;
2002-10-12 11:37:38 +00:00
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)) {
*fd= '/';
}
else {
strcpy(group, fd+1);
/* Find the last slash */
fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
}
return 1;
}
static void do_library_append(SpaceFile *sfile)
{
Library *lib;
2002-10-12 11:37:38 +00:00
char dir[FILE_MAXDIR], group[32];
if ( is_a_library(sfile, dir, group)==0 ) {
error("Not a library");
} else if (!sfile->libfiledata) {
error("Library not loaded");
} else if (group[0]==0) {
error("Nothing indicated");
} else if (BLI_streq(G.main->name, dir)) {
error("Cannot use current file as library");
} else {
Object *ob;
int idcode = groupname_to_code(group);
BLO_library_append(sfile, dir, idcode);
/* DISPLISTS */
2002-10-12 11:37:38 +00:00
ob= G.main->object.first;
set_displist_onlyzero(1);
while(ob) {
if(ob->id.lib) {
if(ob->type==OB_FONT) {
Curve *cu= ob->data;
if(cu->nurb.first==0) text_to_curve(ob, 0);
}
makeDispList(ob);
}
else if(ob->type==OB_MESH && ob->parent && ob->parent->type==OB_LATTICE ) {
makeDispList(ob);
}
ob= ob->id.next;
}
set_displist_onlyzero(0);
/* in sfile->dir is the whole lib name */
2002-10-12 11:37:38 +00:00
strcpy(G.lib, sfile->dir);
/* and now find the latest append lib file */
lib= G.main->library.first;
while(lib) {
if (BLI_streq(dir, lib->name)) break;
lib= lib->id.next;
}
if((sfile->flag & FILE_LINK)==0) all_local(lib);
2002-10-12 11:37:38 +00:00
}
}
static void library_to_filelist(SpaceFile *sfile)
{
LinkNode *l, *names;
int ok, i, nnames, idcode;
char filename[FILE_MAXDIR+FILE_MAXFILE];
char dir[FILE_MAXDIR], group[24];
2002-10-12 11:37:38 +00:00
/* name test */
2002-10-12 11:37:38 +00:00
ok= is_a_library(sfile, dir, group);
if (!ok) {
/* free */
2002-10-12 11:37:38 +00:00
if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
sfile->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 */
2002-10-12 11:37:38 +00:00
if (sfile->libfiledata==0) {
sfile->libfiledata= BLO_blendhandle_from_file(dir); // this sets G.sce, we dont want it
2002-10-12 11:37:38 +00:00
if(sfile->libfiledata==0) return;
}
idcode= groupname_to_code(group);
// memory for strings is passed into filelist[i].relname
// and free'd in freefilelist
if (idcode) {
2002-10-12 11:37:38 +00:00
names= BLO_blendhandle_get_datablock_names(sfile->libfiledata, idcode);
} else {
names= BLO_blendhandle_get_linkable_groups(sfile->libfiledata);
}
nnames= BLI_linklist_length(names);
sfile->totfile= nnames + 2;
sfile->filelist= malloc(sfile->totfile * sizeof(*sfile->filelist));
memset(sfile->filelist, 0, sfile->totfile * sizeof(*sfile->filelist));
sfile->filelist[0].relname= BLI_strdup(".");
2002-10-12 11:37:38 +00:00
sfile->filelist[0].type |= S_IFDIR;
sfile->filelist[1].relname= BLI_strdup("..");
2002-10-12 11:37:38 +00:00
sfile->filelist[1].type |= S_IFDIR;
for (i=0, l= names; i<nnames; i++, l= l->next) {
char *blockname= BLI_strdup(l->link);
2002-10-12 11:37:38 +00:00
sfile->filelist[i + 2].relname= blockname;
if (!idcode)
sfile->filelist[i + 2].type |= S_IFDIR;
}
BLI_linklist_free(names, free);
2002-10-12 11:37:38 +00:00
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
sfile->maxnamelen= 0;
for(i=0; i<sfile->totfile; i++) {
int len = BMF_GetStringWidth(G.font, sfile->filelist[i].relname);
if (len > sfile->maxnamelen)
sfile->maxnamelen = len;
}
BLI_strncpy(G.sce, filename, sizeof(filename)); // prevent G.sce to change
2002-10-12 11:37:38 +00:00
}
/* ******************* DATA SELECT ********************* */
static void filesel_select_objects(SpaceFile *sfile)
{
Object *ob;
Base *base;
Scene *sce;
int a;
/* only when F4 DATABROWSE */
2002-10-12 11:37:38 +00:00
if(sfile->returnfunc) return;
if( strcmp(sfile->dir, "Object/")==0 ) {
for(a=0; a<sfile->totfile; a++) {
ob= (Object *)sfile->filelist[a].poin;
if(ob) {
if(sfile->filelist[a].flags & ACTIVE) ob->flag |= SELECT;
else ob->flag &= ~SELECT;
}
}
base= FIRSTBASE;
while(base) {
base->flag= base->object->flag;
base= base->next;
}
countall();
2002-10-12 11:37:38 +00:00
allqueue(REDRAWVIEW3D, 0);
}
else if( strcmp(sfile->dir, "Scene/")==0 ) {
for(a=0; a<sfile->totfile; a++) {
sce= (Scene *)sfile->filelist[a].poin;
if(sce) {
if(sfile->filelist[a].flags & ACTIVE) sce->r.scemode |= R_BG_RENDER;
else sce->r.scemode &= ~R_BG_RENDER;
}
}
allqueue(REDRAWBUTSSCENE, 0);
2002-10-12 11:37:38 +00:00
}
}
static void active_file_object(SpaceFile *sfile)
{
Object *ob;
/* only when F4 DATABROWSE */
2002-10-12 11:37:38 +00:00
if(sfile->returnfunc) return;
if( strcmp(sfile->dir, "Object/")==0 ) {
if(sfile->act >= 0) {
ob= (Object *)sfile->filelist[sfile->act].poin;
if(ob) {
set_active_object(ob);
if(BASACT && BASACT->object==ob) {
BASACT->flag |= SELECT;
sfile->filelist[sfile->act].flags |= ACTIVE;
allqueue(REDRAWVIEW3D, 0);
scrarea_queue_winredraw(curarea);
}
}
}
}
}
void main_to_filelist(SpaceFile *sfile)
{
ID *id;
struct direntry *files, *firstlib = NULL;
ListBase *lb;
int a, fake, idcode, len, ok, totlib, totbl;
if(sfile->dir[0]=='/') sfile->dir[0]= 0;
if(sfile->dir[0]) {
idcode= groupname_to_code(sfile->dir);
if(idcode==0) sfile->dir[0]= 0;
}
if( sfile->dir[0]==0) {
/* make directories */
2002-10-12 11:37:38 +00:00
sfile->totfile= 22;
sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
for(a=0; a<sfile->totfile; a++) {
memset( &(sfile->filelist[a]), 0 , sizeof(struct direntry));
sfile->filelist[a].type |= S_IFDIR;
}
sfile->filelist[0].relname= BLI_strdup("..");
sfile->filelist[1].relname= BLI_strdup(".");
sfile->filelist[2].relname= BLI_strdup("Scene");
sfile->filelist[3].relname= BLI_strdup("Object");
sfile->filelist[4].relname= BLI_strdup("Mesh");
sfile->filelist[5].relname= BLI_strdup("Curve");
sfile->filelist[6].relname= BLI_strdup("Metaball");
sfile->filelist[7].relname= BLI_strdup("Material");
sfile->filelist[8].relname= BLI_strdup("Texture");
sfile->filelist[9].relname= BLI_strdup("Image");
sfile->filelist[10].relname= BLI_strdup("Ika");
sfile->filelist[11].relname= BLI_strdup("Wave");
sfile->filelist[12].relname= BLI_strdup("Lattice");
sfile->filelist[13].relname= BLI_strdup("Lamp");
sfile->filelist[14].relname= BLI_strdup("Camera");
sfile->filelist[15].relname= BLI_strdup("Ipo");
sfile->filelist[16].relname= BLI_strdup("World");
sfile->filelist[17].relname= BLI_strdup("Screen");
sfile->filelist[18].relname= BLI_strdup("VFont");
sfile->filelist[19].relname= BLI_strdup("Text");
sfile->filelist[20].relname= BLI_strdup("Armature");
sfile->filelist[21].relname= BLI_strdup("Action");
2002-10-12 11:37:38 +00:00
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
}
else {
/* make files */
2002-10-12 11:37:38 +00:00
idcode= groupname_to_code(sfile->dir);
lb= wich_libbase(G.main, idcode );
if(lb==0) return;
id= lb->first;
sfile->totfile= 0;
while(id) {
if(sfile->returnfunc && idcode==ID_IP) {
if(sfile->ipotype== ((Ipo *)id)->blocktype) sfile->totfile++;
}
else sfile->totfile++;
id= id->next;
}
if(sfile->returnfunc==0) sfile->totfile+= 2;
sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
files= sfile->filelist;
if(sfile->returnfunc==0) {
memset( &(sfile->filelist[0]), 0 , sizeof(struct direntry));
sfile->filelist[0].relname= BLI_strdup(".");
2002-10-12 11:37:38 +00:00
sfile->filelist[0].type |= S_IFDIR;
memset( &(sfile->filelist[1]), 0 , sizeof(struct direntry));
sfile->filelist[1].relname= BLI_strdup("..");
2002-10-12 11:37:38 +00:00
sfile->filelist[1].type |= S_IFDIR;
files+= 2;
}
id= lb->first;
totlib= totbl= 0;
while(id) {
ok= 0;
if(sfile->returnfunc && idcode==ID_IP) {
if(sfile->ipotype== ((Ipo *)id)->blocktype) ok= 1;
}
else ok= 1;
if(ok) {
memset( files, 0 , sizeof(struct direntry));
files->relname= BLI_strdup(id->name+2);
2002-10-12 11:37:38 +00:00
if(sfile->returnfunc==0) { /* 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;
}
}
files->nr= totbl+1;
files->poin= id;
fake= id->flag & LIB_FAKEUSER;
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 libraryblokken */
2002-10-12 11:37:38 +00:00
if(totlib>1) {
qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
}
}
sfile->maxnamelen= 0;
for(a=0; a<sfile->totfile; a++) {
len = BMF_GetStringWidth(G.font, sfile->filelist[a].relname);
if (len > sfile->maxnamelen) sfile->maxnamelen = len;
if(filetoname) {
if( strcmp(sfile->file, sfile->filelist[a].relname)==0) {
sfile->ofs= a-( sfile->collums*(curarea->winy-FILESELHEAD-10)/(2*FILESEL_DY));
filetoname= 0;
if(sfile->returnfunc) sfile->filelist[a].flags |= ACTIVE;
}
}
}
}
void clever_numbuts_filesel()
{
SpaceFile *sfile;
char orgname[FILE_MAXDIR+FILE_MAXFILE+12];
char filename[FILE_MAXDIR+FILE_MAXFILE+12];
char newname[FILE_MAXDIR+FILE_MAXFILE+12];
int test;
int len;
sfile= curarea->spacedata.first;
if(sfile->type==FILE_MAIN) return;
len = 110;
test = get_hilited_entry(sfile);
if (test != -1 && !(S_ISDIR(sfile->filelist[test].type))){
BLI_make_file_string(G.sce, orgname, sfile->dir, sfile->filelist[test].relname);
strcpy(filename, sfile->filelist[test].relname);
add_numbut(0, TEX, "", 0, len, filename, "Rename File");
if( do_clever_numbuts("Rename File", 1, REDRAW) ) {
BLI_make_file_string(G.sce, newname, sfile->dir, filename);
if( strcmp(orgname, newname) != 0 ) {
BLI_rename(orgname, newname);
freefilelist(sfile);
}
}
scrarea_queue_winredraw(curarea);
}
}
2002-10-12 11:37:38 +00:00