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/blenkernel/intern/library.c

903 lines
19 KiB
C
Raw Normal View History

/**
2002-10-12 11:37:38 +00:00
* $Id$
*
2002-10-12 11:37:38 +00:00
* ***** 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 *****
*/
/*
* Contains management of ID's and libraries
* allocate and free of all library data
*
*/
2002-10-12 11:37:38 +00:00
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
2002-10-12 11:37:38 +00:00
#include "MEM_guardedalloc.h"
/* all types are needed here, in order to do memory operations */
#include "DNA_ID.h"
#include "DNA_listBase.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_lattice_types.h"
#include "DNA_curve_types.h"
#include "DNA_meta_types.h"
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
#include "DNA_image_types.h"
#include "DNA_wave_types.h"
#include "DNA_lamp_types.h"
#include "DNA_camera_types.h"
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_world_types.h"
#include "DNA_screen_types.h"
#include "DNA_vfont_types.h"
#include "DNA_text_types.h"
#include "DNA_sound_types.h"
#include "DNA_group_types.h"
#include "DNA_armature_types.h"
#include "DNA_action_types.h"
#include "DNA_userdef_types.h"
2002-10-12 11:37:38 +00:00
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
#include "BKE_bad_level_calls.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_global.h"
#include "BKE_sound.h"
#include "BKE_object.h"
#include "BKE_screen.h"
#include "BKE_script.h"
2002-10-12 11:37:38 +00:00
#include "BKE_mesh.h"
#include "BKE_material.h"
#include "BKE_curve.h"
#include "BKE_mball.h"
#include "BKE_text.h"
2002-10-12 11:37:38 +00:00
#include "BKE_texture.h"
#include "BKE_scene.h"
#include "BKE_image.h"
#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_world.h"
#include "BKE_font.h"
#include "BKE_group.h"
#include "BKE_lattice.h"
#include "BKE_armature.h"
#include "BKE_action.h"
#include "BPI_script.h"
2002-10-12 11:37:38 +00:00
#define MAX_IDPUP 60 /* was 24 */
#define MAX_LIBARRAY 100 /* was 30, warning: used it readfile.c too */
2002-10-12 11:37:38 +00:00
/* ************* general ************************ */
2002-10-12 11:37:38 +00:00
void id_lib_extern(ID *id)
{
if(id) {
if(id->flag & LIB_INDIRECT) {
id->flag -= LIB_INDIRECT;
id->flag |= LIB_EXTERN;
}
}
}
void id_us_plus(ID *id)
{
if(id) {
id->us++;
if(id->flag & LIB_INDIRECT) {
id->flag -= LIB_INDIRECT;
id->flag |= LIB_EXTERN;
}
}
}
ListBase *wich_libbase(Main *mainlib, short type)
{
switch( type ) {
case ID_SCE:
return &(mainlib->scene);
case ID_LI:
return &(mainlib->library);
case ID_OB:
return &(mainlib->object);
case ID_ME:
return &(mainlib->mesh);
case ID_CU:
return &(mainlib->curve);
case ID_MB:
return &(mainlib->mball);
case ID_MA:
return &(mainlib->mat);
case ID_TE:
return &(mainlib->tex);
case ID_IM:
return &(mainlib->image);
case ID_WV:
return &(mainlib->wave);
case ID_LT:
return &(mainlib->latt);
case ID_LA:
return &(mainlib->lamp);
case ID_CA:
return &(mainlib->camera);
case ID_IP:
return &(mainlib->ipo);
case ID_KE:
return &(mainlib->key);
case ID_WO:
return &(mainlib->world);
case ID_SCR:
return &(mainlib->screen);
case ID_VF:
return &(mainlib->vfont);
case ID_TXT:
return &(mainlib->text);
case ID_SCRIPT:
return &(mainlib->script);
2002-10-12 11:37:38 +00:00
case ID_SO:
return &(mainlib->sound);
case ID_SAMPLE:
/* declared as an external in sound.h !!! */
return (samples);
case ID_GR:
return &(mainlib->group);
case ID_AR:
return &(mainlib->armature);
case ID_AC:
return &(mainlib->action);
}
return 0;
}
int set_listbasepointers(Main *main, ListBase **lb)
{
/* BACKWARDS! also watch order of free-ing! (mesh<->mat) */
2002-10-12 11:37:38 +00:00
lb[0]= &(main->ipo);
lb[1]= &(main->key);
lb[2]= &(main->image);
lb[3]= &(main->tex);
lb[4]= &(main->mat);
lb[5]= &(main->vfont);
/* Important!: When adding a new object type,
* the specific data should be inserted here
*/
lb[6]= &(main->armature);
lb[7]= &(main->action);
lb[8]= &(main->mesh);
lb[9]= &(main->curve);
lb[10]= &(main->mball);
Result of 2 weeks of quiet coding work in Greece :) Aim was to get a total refresh of the animation system. This is needed because; - we need to upgrade it with 21st century features - current code is spaghetti/hack combo, and hides good design - it should become lag-free with using dependency graphs A full log, with complete code API/structure/design explanation will follow, that's a load of work... so here below the list with hot changes; - The entire object update system (matrices, geometry) is now centralized. Calls to where_is_object and makeDispList are forbidden, instead we tag objects 'changed' and let the depgraph code sort it out - Removed all old "Ika" code - Depgraph is aware of all relationships, including meta balls, constraints, bevelcurve, and so on. - Made depgraph aware of relation types and layers, to do smart flushing of 'changed' events. Nothing gets calculated too often! - Transform uses depgraph to detect changes - On frame-advance, depgraph flushes animated changes Armatures; Almost all armature related code has been fully built from scratch. It now reveils the original design much better, with a very clean implementation, lag free without even calculating each Bone more than once. Result is quite a speedup yes! Important to note is; 1) Armature is data containing the 'rest position' 2) Pose is the changes of rest position, and always on object level. That way more Objects can use same Pose. Also constraints are in Pose 3) Actions only contain the Ipos to change values in Poses. - Bones draw unrotated now - Drawing bones speedup enormously (10-20 times) - Bone selecting in EditMode, selection state is saved for PoseMode, and vice-versa - Undo in editmode - Bone renaming does vertexgroups, constraints, posechannels, actions, for all users of Armature in entire file - Added Bone renaming in NKey panel - Nkey PoseMode shows eulers now - EditMode and PoseMode now have 'active' bone too (last clicked) - Parenting in EditMode' CTRL+P, ALT+P, with nice options! - Pose is added in Outliner now, with showing that constraints are in the Pose, not Armature - Disconnected IK solving from constraints. It's a separate phase now, on top of the full Pose calculations - Pose itself has a dependency graph too, so evaluation order is lag free. TODO NOW; - Rotating in Posemode has incorrect inverse transform (Martin will fix) - Python Bone/Armature/Pose API disabled... needs full recode too (wait for my doc!) - Game engine will need upgrade too - Depgraph code needs revision, cleanup, can be much faster! (But, compliments for Jean-Luc, it works like a charm!) - IK changed, it now doesnt use previous position to advance to next position anymore. That system looks nice (no flips) but is not well suited for NLA and background render. TODO LATER; We now can do loadsa new nifty features as well; like: - Kill PoseMode (can be option for armatures itself) - Make B-Bones (Bezier, Bspline, like for spines) - Move all silly button level edit to 3d window (like CTRL+I = add IK) - Much better & informative drawing - Fix action/nla editors - Put all ipos in Actions (object, mesh key, lamp color) - Add hooks - Null bones - Much more advanced constraints... Bugfixes; - OGL render (view3d header) had wrong first frame on anim render - Ipo 'recording' mode had wrong playback speed - Vertex-key mode now sticks to show 'active key', until frame change -Ton-
2005-07-03 17:35:38 +00:00
lb[11]= &(main->wave);
lb[12]= &(main->latt);
lb[13]= &(main->lamp);
lb[14]= &(main->camera);
2002-10-12 11:37:38 +00:00
Result of 2 weeks of quiet coding work in Greece :) Aim was to get a total refresh of the animation system. This is needed because; - we need to upgrade it with 21st century features - current code is spaghetti/hack combo, and hides good design - it should become lag-free with using dependency graphs A full log, with complete code API/structure/design explanation will follow, that's a load of work... so here below the list with hot changes; - The entire object update system (matrices, geometry) is now centralized. Calls to where_is_object and makeDispList are forbidden, instead we tag objects 'changed' and let the depgraph code sort it out - Removed all old "Ika" code - Depgraph is aware of all relationships, including meta balls, constraints, bevelcurve, and so on. - Made depgraph aware of relation types and layers, to do smart flushing of 'changed' events. Nothing gets calculated too often! - Transform uses depgraph to detect changes - On frame-advance, depgraph flushes animated changes Armatures; Almost all armature related code has been fully built from scratch. It now reveils the original design much better, with a very clean implementation, lag free without even calculating each Bone more than once. Result is quite a speedup yes! Important to note is; 1) Armature is data containing the 'rest position' 2) Pose is the changes of rest position, and always on object level. That way more Objects can use same Pose. Also constraints are in Pose 3) Actions only contain the Ipos to change values in Poses. - Bones draw unrotated now - Drawing bones speedup enormously (10-20 times) - Bone selecting in EditMode, selection state is saved for PoseMode, and vice-versa - Undo in editmode - Bone renaming does vertexgroups, constraints, posechannels, actions, for all users of Armature in entire file - Added Bone renaming in NKey panel - Nkey PoseMode shows eulers now - EditMode and PoseMode now have 'active' bone too (last clicked) - Parenting in EditMode' CTRL+P, ALT+P, with nice options! - Pose is added in Outliner now, with showing that constraints are in the Pose, not Armature - Disconnected IK solving from constraints. It's a separate phase now, on top of the full Pose calculations - Pose itself has a dependency graph too, so evaluation order is lag free. TODO NOW; - Rotating in Posemode has incorrect inverse transform (Martin will fix) - Python Bone/Armature/Pose API disabled... needs full recode too (wait for my doc!) - Game engine will need upgrade too - Depgraph code needs revision, cleanup, can be much faster! (But, compliments for Jean-Luc, it works like a charm!) - IK changed, it now doesnt use previous position to advance to next position anymore. That system looks nice (no flips) but is not well suited for NLA and background render. TODO LATER; We now can do loadsa new nifty features as well; like: - Kill PoseMode (can be option for armatures itself) - Make B-Bones (Bezier, Bspline, like for spines) - Move all silly button level edit to 3d window (like CTRL+I = add IK) - Much better & informative drawing - Fix action/nla editors - Put all ipos in Actions (object, mesh key, lamp color) - Add hooks - Null bones - Much more advanced constraints... Bugfixes; - OGL render (view3d header) had wrong first frame on anim render - Ipo 'recording' mode had wrong playback speed - Vertex-key mode now sticks to show 'active key', until frame change -Ton-
2005-07-03 17:35:38 +00:00
lb[15]= &(main->world);
lb[16]= &(main->screen);
lb[17]= &(main->object);
lb[18]= &(main->scene);
lb[19]= &(main->library);
lb[20]= &(main->text);
lb[21]= &(main->sound);
lb[22]= &(main->group);
Result of 2 weeks of quiet coding work in Greece :) Aim was to get a total refresh of the animation system. This is needed because; - we need to upgrade it with 21st century features - current code is spaghetti/hack combo, and hides good design - it should become lag-free with using dependency graphs A full log, with complete code API/structure/design explanation will follow, that's a load of work... so here below the list with hot changes; - The entire object update system (matrices, geometry) is now centralized. Calls to where_is_object and makeDispList are forbidden, instead we tag objects 'changed' and let the depgraph code sort it out - Removed all old "Ika" code - Depgraph is aware of all relationships, including meta balls, constraints, bevelcurve, and so on. - Made depgraph aware of relation types and layers, to do smart flushing of 'changed' events. Nothing gets calculated too often! - Transform uses depgraph to detect changes - On frame-advance, depgraph flushes animated changes Armatures; Almost all armature related code has been fully built from scratch. It now reveils the original design much better, with a very clean implementation, lag free without even calculating each Bone more than once. Result is quite a speedup yes! Important to note is; 1) Armature is data containing the 'rest position' 2) Pose is the changes of rest position, and always on object level. That way more Objects can use same Pose. Also constraints are in Pose 3) Actions only contain the Ipos to change values in Poses. - Bones draw unrotated now - Drawing bones speedup enormously (10-20 times) - Bone selecting in EditMode, selection state is saved for PoseMode, and vice-versa - Undo in editmode - Bone renaming does vertexgroups, constraints, posechannels, actions, for all users of Armature in entire file - Added Bone renaming in NKey panel - Nkey PoseMode shows eulers now - EditMode and PoseMode now have 'active' bone too (last clicked) - Parenting in EditMode' CTRL+P, ALT+P, with nice options! - Pose is added in Outliner now, with showing that constraints are in the Pose, not Armature - Disconnected IK solving from constraints. It's a separate phase now, on top of the full Pose calculations - Pose itself has a dependency graph too, so evaluation order is lag free. TODO NOW; - Rotating in Posemode has incorrect inverse transform (Martin will fix) - Python Bone/Armature/Pose API disabled... needs full recode too (wait for my doc!) - Game engine will need upgrade too - Depgraph code needs revision, cleanup, can be much faster! (But, compliments for Jean-Luc, it works like a charm!) - IK changed, it now doesnt use previous position to advance to next position anymore. That system looks nice (no flips) but is not well suited for NLA and background render. TODO LATER; We now can do loadsa new nifty features as well; like: - Kill PoseMode (can be option for armatures itself) - Make B-Bones (Bezier, Bspline, like for spines) - Move all silly button level edit to 3d window (like CTRL+I = add IK) - Much better & informative drawing - Fix action/nla editors - Put all ipos in Actions (object, mesh key, lamp color) - Add hooks - Null bones - Much more advanced constraints... Bugfixes; - OGL render (view3d header) had wrong first frame on anim render - Ipo 'recording' mode had wrong playback speed - Vertex-key mode now sticks to show 'active key', until frame change -Ton-
2005-07-03 17:35:38 +00:00
lb[23]= samples;
lb[24]= &(main->script);
lb[25]= NULL;
return 25;
2002-10-12 11:37:38 +00:00
}
/* *********** ALLOC AND FREE *****************
2002-10-12 11:37:38 +00:00
free_libblock(ListBase *lb, ID *id )
provide a list-basis and datablock, but only ID is read
2002-10-12 11:37:38 +00:00
void *alloc_libblock(ListBase *lb, type, name)
inserts in list and returns a new ID
2002-10-12 11:37:38 +00:00
***************************** */
static ID *alloc_libblock_notest(short type)
{
ID *id= 0;
switch( type ) {
case ID_SCE:
id= MEM_callocN(sizeof(Scene), "scene");
break;
case ID_LI:
id= MEM_callocN(sizeof(Library), "library");
break;
case ID_OB:
id= MEM_callocN(sizeof(Object), "object");
break;
case ID_ME:
id= MEM_callocN(sizeof(Mesh), "mesh");
break;
case ID_CU:
id= MEM_callocN(sizeof(Curve), "curve");
break;
case ID_MB:
id= MEM_callocN(sizeof(MetaBall), "mball");
break;
case ID_MA:
id= MEM_callocN(sizeof(Material), "mat");
break;
case ID_TE:
id= MEM_callocN(sizeof(Tex), "tex");
break;
case ID_IM:
id= MEM_callocN(sizeof(Image), "image");
break;
case ID_WV:
id= MEM_callocN(sizeof(Wave), "wave");
break;
case ID_LT:
id= MEM_callocN(sizeof(Lattice), "latt");
break;
case ID_LA:
id= MEM_callocN(sizeof(Lamp), "lamp");
break;
case ID_CA:
id= MEM_callocN(sizeof(Camera), "camera");
break;
case ID_IP:
id= MEM_callocN(sizeof(Ipo), "ipo");
break;
case ID_KE:
id= MEM_callocN(sizeof(Key), "key");
break;
case ID_WO:
id= MEM_callocN(sizeof(World), "world");
break;
case ID_SCR:
id= MEM_callocN(sizeof(bScreen), "screen");
break;
case ID_VF:
id= MEM_callocN(sizeof(VFont), "vfont");
break;
case ID_TXT:
id= MEM_callocN(sizeof(Text), "text");
break;
case ID_SCRIPT:
id= MEM_callocN(sizeof(Script), "script");
break;
2002-10-12 11:37:38 +00:00
case ID_SO:
id= MEM_callocN(sizeof(bSound), "sound");
break;
case ID_SAMPLE:
id = MEM_callocN(sizeof(bSample), "sound");
break;
case ID_GR:
id= MEM_callocN(sizeof(Group), "sound");
break;
case ID_AR:
id = MEM_callocN(sizeof(bArmature), "armature");
break;
case ID_AC:
id = MEM_callocN(sizeof(bAction), "action");
break;
}
return id;
}
// used everywhere in blenkernel and text.c
void *alloc_libblock(ListBase *lb, short type, char *name)
{
ID *id= 0;
id= alloc_libblock_notest(type);
if(id) {
BLI_addtail(lb, id);
id->us= 1;
*( (short *)id->name )= type;
new_id(lb, id, name);
/* alphabetic insterion: is in new_id */
2002-10-12 11:37:38 +00:00
}
return id;
}
/* GS reads the memory pointed at in a specific ordering. There are,
* however two definitions for it. I have jotted them down here, both,
* but I think the first one is actually used. The thing is that
* big-endian systems might read this the wrong way round. OTOH, we
* constructed the IDs that are read out with this macro explicitly as
* well. I expect we'll sort it out soon... */
/* from blendef: */
#define GS(a) (*((short *)(a)))
/* from misc_util: flip the bytes from x */
/*#define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
// used everywhere in blenkernel and text.c
void *copy_libblock(void *rt)
{
ID *idn, *id;
ListBase *lb;
char *cp, *cpn;
int idn_len;
id= rt;
lb= wich_libbase(G.main, GS(id->name));
idn= alloc_libblock(lb, GS(id->name), id->name+2);
idn_len= MEM_allocN_len(idn);
if(idn_len - sizeof(ID) > 0) {
cp= (char *)id;
cpn= (char *)idn;
memcpy(cpn+sizeof(ID), cp+sizeof(ID), idn_len - sizeof(ID));
}
id->newid= idn;
idn->flag |= LIB_NEW;
return idn;
}
static void free_library(Library *lib)
{
/* no freeing needed for libraries yet */
}
// used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
void free_libblock(ListBase *lb, void *idv)
{
ID *id= idv;
switch( GS(id->name) ) { /* GetShort from util.h */
2002-10-12 11:37:38 +00:00
case ID_SCE:
free_scene((Scene *)id);
break;
case ID_LI:
free_library((Library *)id);
break;
case ID_OB:
free_object((Object *)id);
break;
case ID_ME:
free_mesh((Mesh *)id);
break;
case ID_CU:
free_curve((Curve *)id);
break;
case ID_MB:
free_mball((MetaBall *)id);
break;
case ID_MA:
free_material((Material *)id);
break;
case ID_TE:
free_texture((Tex *)id);
break;
case ID_IM:
free_image((Image *)id);
break;
case ID_WV:
/* free_wave(id); */
break;
case ID_LT:
free_lattice((Lattice *)id);
break;
case ID_LA:
free_lamp((Lamp *)id);
break;
case ID_CA:
free_camera((Camera*) id);
break;
case ID_IP:
free_ipo((Ipo *)id);
break;
case ID_KE:
free_key((Key *)id);
break;
case ID_WO:
free_world((World *)id);
break;
case ID_SCR:
free_screen((bScreen *)id);
break;
case ID_VF:
free_vfont((VFont *)id);
break;
case ID_TXT:
free_text((Text *)id);
break;
case ID_SCRIPT:
free_script((Script *)id);
break;
2002-10-12 11:37:38 +00:00
case ID_SO:
sound_free_sound((bSound *)id);
break;
case ID_SAMPLE:
sound_free_sample((bSample *)id);
break;
case ID_GR:
free_group((Group *)id);
break;
case ID_AR:
free_armature((bArmature *)id);
break;
case ID_AC:
free_action((bAction *)id);
break;
}
BLI_remlink(lb, id);
MEM_freeN(id);
}
void free_libblock_us(ListBase *lb, void *idv) /* test users */
{
ID *id= idv;
id->us--;
if(id->us<0) {
if(id->lib) printf("ERROR block %s %s users %d\n", id->lib->name, id->name, id->us);
else printf("ERROR block %s users %d\n", id->name, id->us);
}
if(id->us==0) {
if( GS(id->name)==ID_OB ) unlink_object((Object *)id);
free_libblock(lb, id);
}
}
void free_main(Main *mainvar)
{
/* also call when reading a file, erase all, etc */
2002-10-12 11:37:38 +00:00
ListBase *lbarray[MAX_LIBARRAY];
int a;
a= set_listbasepointers(mainvar, lbarray);
while(a--) {
ListBase *lb= lbarray[a];
ID *id;
Phew, a lot of work, and no new features... Main target was to make the inner rendering loop using no globals anymore. This is essential for proper usage while raytracing, it caused a lot of hacks in the raycode as well, which even didn't work correctly for all situations (textures especially). Done this by creating a new local struct RenderInput, which replaces usage of the global struct Render R. The latter now only is used to denote image size, viewmatrix, and the like. Making the inner render loops using no globals caused 1000s of vars to be changed... but the result definitely is much nicer code, which enables making 'real' shaders in a next stage. It also enabled me to remove the hacks from ray.c Then i went to the task of removing redundant code. Especially the calculus of texture coords took place (identical) in three locations. Most obvious is the change in the unified render part, which is much less code now; it uses the same rendering routines as normal render now. (Note; not for halos yet!) I also removed 6 files called 'shadowbuffer' something. This was experimen- tal stuff from NaN days. And again saved a lot of double used code. Finally I went over the blenkernel and blender/src calls to render stuff. Here the same local data is used now, resulting in less dependency. I also moved render-texture to the render module, this was still in Kernel. (new file: texture.c) So! After this commit I will check on the autofiles, to try to fix that. MSVC people have to do it themselves. This commit will need quite some testing help, but I'm around!
2003-12-21 21:52:51 +00:00
while ( (id= lb->first) ) {
2002-10-12 11:37:38 +00:00
free_libblock(lb, id);
}
}
MEM_freeN(mainvar);
}
/* ***************** ID ************************ */
// only used in exotic.c
ID *find_id(char *type, char *name) /* type: "OB" or "MA" etc */
2002-10-12 11:37:38 +00:00
{
ID *id;
ListBase *lb;
lb= wich_libbase(G.main, GS(type));
id= lb->first;
while(id) {
if( strcmp(id->name+2, name)==0 ) return id;
id= id->next;
}
return 0;
}
static void get_flags_for_id(ID *id, char *buf) {
int isfake= id->flag & LIB_FAKEUSER;
/* Writeout the flags for the entry, note there
* is a small hack that writes 5 spaces instead
* of 4 if no flags are displayed... this makes
* things usually line up ok - better would be
* to have that explicit, oh well - zr
*/
if (id->us<0)
sprintf(buf, "-1W ");
else if (!id->lib && !isfake && id->us)
sprintf(buf, " ");
else
sprintf(buf, "%c%c%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' ');
}
static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr)
{
int i, nids= BLI_countlist(lb);
if (nr) *nr= -1;
2002-10-12 11:37:38 +00:00
if (nr && nids>MAX_IDPUP) {
2002-10-12 11:37:38 +00:00
BLI_dynstr_append(pupds, "DataBrowse %x-2");
*nr= -2;
2002-10-12 11:37:38 +00:00
} else {
ID *id;
for (i=0, id= lb->first; id; id= id->next, i++) {
char buf[32];
if (nr && id==link) *nr= i+1;
if (U.uiflag & USER_HIDE_DOT && id->name[2]=='.')
continue;
2002-10-12 11:37:38 +00:00
get_flags_for_id(id, buf);
BLI_dynstr_append(pupds, buf);
BLI_dynstr_append(pupds, id->name+2);
sprintf(buf, "%%x%d", i+1);
BLI_dynstr_append(pupds, buf);
2002-10-12 11:37:38 +00:00
if(id->next)
BLI_dynstr_append(pupds, "|");
}
}
}
/* Silly routine, the only difference between the one
* above is that it only adds items with a matching
* blocktype... this should be unified somehow... - zr
*/
static void IPOnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int blocktype)
{
ID *id;
int i, nids;
for (id= lb->first, nids= 0; id; id= id->next) {
Ipo *ipo= (Ipo*) id;
if (ipo->blocktype==blocktype)
nids++;
}
if (nids>MAX_IDPUP) {
BLI_dynstr_append(pupds, "DataBrowse %x-2");
} else {
for (i=0, id= lb->first; id; id= id->next) {
Ipo *ipo= (Ipo*) id;
if (ipo->blocktype==blocktype) {
char buf[32];
if (id==link)
*nr= i+1;
if (U.uiflag & USER_HIDE_DOT && id->name[2]=='.')
continue;
2002-10-12 11:37:38 +00:00
get_flags_for_id(id, buf);
BLI_dynstr_append(pupds, buf);
BLI_dynstr_append(pupds, id->name+2);
sprintf(buf, "%%x%d", i+1);
BLI_dynstr_append(pupds, buf);
2002-10-12 11:37:38 +00:00
if(id->next)
BLI_dynstr_append(pupds, "|");
i++;
}
}
}
}
// used by headerbuttons.c buttons.c editobject.c editseq.c
// if nr==NULL no MAX_IDPUP, this for non-header browsing
2002-10-12 11:37:38 +00:00
void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr)
{
DynStr *pupds= BLI_dynstr_new();
if (title) {
BLI_dynstr_append(pupds, title);
BLI_dynstr_append(pupds, "%t|");
}
if (extraops) {
BLI_dynstr_append(pupds, extraops);
2002-10-12 11:37:38 +00:00
if (BLI_dynstr_get_len(pupds))
BLI_dynstr_append(pupds, "|");
}
IDnames_to_dyn_pupstring(pupds, lb, link, nr);
2002-10-12 11:37:38 +00:00
*str= BLI_dynstr_get_cstring(pupds);
BLI_dynstr_free(pupds);
}
// only used by headerbuttons.c
void IPOnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr, int blocktype)
{
DynStr *pupds= BLI_dynstr_new();
if (title) {
BLI_dynstr_append(pupds, title);
BLI_dynstr_append(pupds, "%t|");
}
if (extraops) {
BLI_dynstr_append(pupds, extraops);
2002-10-12 11:37:38 +00:00
if (BLI_dynstr_get_len(pupds))
BLI_dynstr_append(pupds, "|");
}
IPOnames_to_dyn_pupstring(pupds, lb, link, nr, blocktype);
2002-10-12 11:37:38 +00:00
*str= BLI_dynstr_get_cstring(pupds);
BLI_dynstr_free(pupds);
}
// used by buttons.c library.c mball.c
void splitIDname(char *name, char *left, int *nr)
{
int a;
*nr= 0;
strncpy(left, name, 21);
a= strlen(name);
if(a>1 && name[a-1]=='.') return;
while(a--) {
if( name[a]=='.' ) {
left[a]= 0;
*nr= atol(name+a+1);
return;
}
if( isdigit(name[a])==0 ) break;
left[a]= 0;
}
strcpy(left, name);
}
static void sort_alpha_id(ListBase *lb, ID *id)
{
ID *idtest;
/* insert alphabetically */
2002-10-12 11:37:38 +00:00
if(lb->first!=lb->last) {
BLI_remlink(lb, id);
idtest= lb->first;
while(idtest) {
if(BLI_strcasecmp(idtest->name, id->name)>0 || idtest->lib) {
2002-10-12 11:37:38 +00:00
BLI_insertlinkbefore(lb, idtest, id);
break;
}
idtest= idtest->next;
}
/* as last */
2002-10-12 11:37:38 +00:00
if(idtest==0) {
BLI_addtail(lb, id);
}
}
}
int new_id(ListBase *lb, ID *id, char *tname)
/* only for local blocks: external en indirect blocks already have a unique ID */
/* return 1: created a new name */
2002-10-12 11:37:38 +00:00
{
ID *idtest;
int nr= 0, nrtest, maxtest=32, a;
char aname[32], *name, left[24], leftest[24], in_use[32];
/* - split name
* - search
2002-10-12 11:37:38 +00:00
*/
if(id->lib) return 0;
if(tname==0) name= id->name+2;
else {
/* tname can be const */
strncpy(aname, tname, 21);
name= aname;
if( strlen(name) > 21 ) name[21]= 0;
}
if(lb==0) lb= wich_libbase(G.main, GS(id->name));
/* phase 1: id already exists? */
2002-10-12 11:37:38 +00:00
idtest= lb->first;
while(idtest) {
if(id!=idtest && idtest->lib==0) {
/* do not test alphabetic! */
/* optimized */
2002-10-12 11:37:38 +00:00
if( idtest->name[2] == name[0] ) {
if(strcmp(name, idtest->name+2)==0) break;
}
}
idtest= idtest->next;
}
/* if there is no double return */
if(idtest==0) {
strcpy(id->name+2, name);
return 0;
}
memset(in_use, 0, maxtest);
splitIDname(name, left, &nr);
if(nr>999 && strlen(left)>16) left[16]= 0;
else if(strlen(left)>17) left[17]= 0;
idtest= lb->first;
while(idtest) {
if(id!=idtest && idtest->lib==0) {
splitIDname(idtest->name+2, leftest, &nrtest);
if(strcmp(left, leftest)==0) {
if(nrtest<maxtest) in_use[nrtest]= 1;
if(nr <= nrtest) nr= nrtest+1;
}
}
idtest= idtest->next;
}
for(a=0; a<maxtest; a++) {
if(a>=nr) break;
if( in_use[a]==0 ) {
nr= a;
break;
}
}
if(nr==0) sprintf(id->name+2, "%s", left);
else {
if (nr >= 1000 && strlen(left) > 16) {
// this would overflow name buffer
left[16]= 0;
return (new_id(lb, id, left));
}
/* this format specifier is from hell... */
Phew, a lot of work, and no new features... Main target was to make the inner rendering loop using no globals anymore. This is essential for proper usage while raytracing, it caused a lot of hacks in the raycode as well, which even didn't work correctly for all situations (textures especially). Done this by creating a new local struct RenderInput, which replaces usage of the global struct Render R. The latter now only is used to denote image size, viewmatrix, and the like. Making the inner render loops using no globals caused 1000s of vars to be changed... but the result definitely is much nicer code, which enables making 'real' shaders in a next stage. It also enabled me to remove the hacks from ray.c Then i went to the task of removing redundant code. Especially the calculus of texture coords took place (identical) in three locations. Most obvious is the change in the unified render part, which is much less code now; it uses the same rendering routines as normal render now. (Note; not for halos yet!) I also removed 6 files called 'shadowbuffer' something. This was experimen- tal stuff from NaN days. And again saved a lot of double used code. Finally I went over the blenkernel and blender/src calls to render stuff. Here the same local data is used now, resulting in less dependency. I also moved render-texture to the render module, this was still in Kernel. (new file: texture.c) So! After this commit I will check on the autofiles, to try to fix that. MSVC people have to do it themselves. This commit will need quite some testing help, but I'm around!
2003-12-21 21:52:51 +00:00
sprintf(id->name+2, "%s.%.3d", left, nr);
2002-10-12 11:37:38 +00:00
}
sort_alpha_id(lb, id);
return 1;
}
// next to indirect usage in read/writefile also in editobject.c scene.c
void clear_id_newpoins()
{
ListBase *lbarray[MAX_LIBARRAY];
ID *id;
int a;
a= set_listbasepointers(G.main, lbarray);
while(a--) {
id= lbarray[a]->first;
while(id) {
id->newid= 0;
id->flag &= ~LIB_NEW;
id= id->next;
}
}
}
/* if lib!=NULL, only all from lib local */
void all_local(Library *lib)
2002-10-12 11:37:38 +00:00
{
ListBase *lbarray[MAX_LIBARRAY], tempbase={0, 0};
ID *id, *idn;
int a;
a= set_listbasepointers(G.main, lbarray);
while(a--) {
id= lbarray[a]->first;
while(id) {
id->newid= NULL;
idn= id->next; /* id is possibly being inserted again */
if(id->flag & (LIB_EXTERN|LIB_INDIRECT|LIB_NEW)) {
if(lib==NULL || id->lib==lib) {
id->flag &= ~(LIB_EXTERN|LIB_INDIRECT|LIB_NEW);
if(id->lib) {
id->lib= NULL;
new_id(lbarray[a], id, 0); /* new_id only does it with double names */
sort_alpha_id(lbarray[a], id);
2002-10-12 11:37:38 +00:00
}
}
}
id= idn;
}
/* patch2: make it aphabetically */
2002-10-12 11:37:38 +00:00
while( (id=tempbase.first) ) {
BLI_remlink(&tempbase, id);
BLI_addtail(lbarray[a], id);
new_id(lbarray[a], id, 0);
}
}
}
void test_idbutton(char *name)
{
/* called from buttons: when name already exists: call new_id */
2002-10-12 11:37:38 +00:00
ListBase *lb;
ID *idtest;
lb= wich_libbase(G.main, GS(name-2) );
if(lb==0) return;
/* search for id */
2002-10-12 11:37:38 +00:00
idtest= lb->first;
while(idtest) {
if( strcmp(idtest->name+2, name)==0) break;
idtest= idtest->next;
}
if(idtest) if( new_id(lb, idtest, name)==0 ) sort_alpha_id(lb, idtest);
}
void rename_id(ID *id, char *name)
{
ListBase *lb;
strncpy(id->name+2, name, 21);
lb= wich_libbase(G.main, GS(id->name) );
new_id(lb, id, name);
}