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/blenloader/intern/writefile.c

1925 lines
44 KiB
C
Raw Normal View History

/* writefile.c
*
* .blend file writing
*
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 *****
*/
/*
FILEFORMAT: IFF-style structure (but not IFF compatible!)
2002-10-12 11:37:38 +00:00
start file:
BLENDER_V100 12 bytes (versie 1.00)
V = big endian, v = little endian
_ = 4 byte pointer, - = 8 byte pointer
datablocks: also see struct BHead
2002-10-12 11:37:38 +00:00
<bh.code> 4 chars
<bh.len> int, len data after BHead
<bh.old> void, old pointer
2002-10-12 11:37:38 +00:00
<bh.SDNAnr> int
<bh.nr> int, in case of array: amount of structs
data
2002-10-12 11:37:38 +00:00
...
...
Almost all data in Blender are structures. Each struct saved
gets a BHead header. With BHead the struct can be linked again
and compared with StructDNA .
2002-10-12 11:37:38 +00:00
WRITE
2002-10-12 11:37:38 +00:00
Preferred writing order: (not really a must, but why would you do it random?)
Any case: direct data is ALWAYS after the lib block
2002-10-12 11:37:38 +00:00
(Local file data)
- for each LibBlock
- write LibBlock
- write associated direct data
(External file data)
2002-10-12 11:37:38 +00:00
- per library
- write library block
2002-10-12 11:37:38 +00:00
- per LibBlock
- write the ID of LibBlock
- write FileGlobal (some global vars)
- write SDNA
- write USER if filename is ~/.B.blend
*/
/* for version 2.2+
Important to know is that 'streaming' has been added to files, for Blender Publisher
2002-10-12 11:37:38 +00:00
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "zlib.h"
#ifndef WIN32
2002-10-12 11:37:38 +00:00
#include <unistd.h>
#else
#include "winsock2.h"
#include "BLI_winstuff.h"
#include <io.h>
#include <process.h> // for getpid
#endif
#include <math.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "nla.h" // __NLA is defined
#include "DNA_armature_types.h"
#include "DNA_action_types.h"
2002-10-12 11:37:38 +00:00
#include "DNA_actuator_types.h"
#include "DNA_controller_types.h"
2002-10-12 11:37:38 +00:00
#include "DNA_curve_types.h"
#include "DNA_constraint_types.h"
2002-10-12 11:37:38 +00:00
#include "DNA_camera_types.h"
Orange: - New UI element: the "Curve Button". For mapping ranges (like 0 - 1) to another range, the curve button can be used for proportional falloff, bone influences, painting density, etc. Most evident use is of course to map RGB color with curves. To be able to use it, you have to allocate a CurveMapping struct and pass this on to the button. The CurveMapping API is in the new C file blenkernel/intern/colortools.c It's as simple as calling: curvemap= curvemapping_add(3, 0, 0, 1, 1) Which will create 3 curves, and sets a default 0-1 range. The current code only supports up to 4 curves maximum per mapping struct. The CurveMap button in Blender than handles allmost all editing. Evaluating a single channel: float newvalue= curvemapping_evaluateF(curvemap, 0, oldval); Where the second argument is the channel index, here 0-1-2 are possible. Or mapping a vector: curvemapping_evaluate3F(curvemap, newvec, oldvec); Optimized versions for byte or short mapping is possible too, not done yet. In butspace.c I've added a template wrapper for buttons around the curve, to reveil settings or show tools; check this screenie: http://www.blender.org/bf/curves.jpg - Buttons R, G, B: select channel - icons + and -: zoom in, out - icon 'wrench': menu with tools, like clear curve, set handle type - icon 'clipping': menu with clip values, and to dis/enable clipping - icon 'x': delete selection In the curve button itself, only LMB clicks are handled (like all UI elements in Blender). - click on point: select - shift+click on point: swap select - click on point + drag: select point (if not selected) and move it - click outside point + drag: translate view - CTRL+click: add new point - hold SHIFT while dragging to snap to grid (Yes I know... either one of these can be Blender compliant, not both!) - if you drag a point exactly on top of another, it merges them Other fixes: - Icons now draw using "Safe RasterPos", so they align with pixel boundary. the old code made ints from the raster pos coordinate, which doesn't work well for zoom in/out situations - bug in Node editing: buttons could not get freed, causing in memory error prints at end of a Blender session. That one was a very simple, but nasty error causing me all evening last night to find! (Hint; check diff of editnode.c, where uiDoButtons is called) Last note: this adds 3 new files in our tree, I did scons, but not MSVC!
2006-01-08 11:41:06 +00:00
#include "DNA_color_types.h"
#include "DNA_effect_types.h"
#include "DNA_group_types.h"
#include "DNA_image_types.h"
#include "DNA_ipo_types.h"
#include "DNA_fileglobal_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_listBase.h" /* for Listbase, the type of samples, ...*/
#include "DNA_lamp_types.h"
2002-10-12 11:37:38 +00:00
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
2002-10-12 11:37:38 +00:00
#include "DNA_material_types.h"
#include "DNA_modifier_types.h"
#include "DNA_nla_types.h"
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
2002-10-12 11:37:38 +00:00
#include "DNA_oops_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_property_types.h"
#include "DNA_scene_types.h"
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sensor_types.h"
2002-10-12 11:37:38 +00:00
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_sound_types.h"
#include "DNA_texture_types.h"
#include "DNA_text_types.h"
#include "DNA_view3d_types.h"
#include "DNA_vfont_types.h"
#include "DNA_userdef_types.h"
2002-10-12 11:37:38 +00:00
#include "MEM_guardedalloc.h" // MEM_freeN
2002-10-12 11:37:38 +00:00
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
#include "BKE_action.h"
#include "BKE_bad_level_calls.h" // build_seqar (from WHILE_SEQ) free_oops error
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 "BKE_curve.h"
2002-10-12 11:37:38 +00:00
#include "BKE_constraint.h"
#include "BKE_global.h" // for G
#include "BKE_library.h" // for set_listbasepointers
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 "BKE_main.h" // G.main
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
#include "BKE_node.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 "BKE_packedFile.h" // for packAll
#include "BKE_screen.h" // for waitcursor
#include "BKE_scene.h" // for do_seq
2002-10-12 11:37:38 +00:00
#include "BKE_sound.h" /* ... and for samples */
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 "BKE_utildefines.h" // for defines
#include "BKE_modifier.h"
2002-10-12 11:37:38 +00:00
#include "GEN_messaging.h"
#include "BLO_writefile.h"
#include "BLO_readfile.h"
#include "BLO_undofile.h"
2002-10-12 11:37:38 +00:00
#include "readfile.h"
#include "genfile.h"
#include <errno.h>
/* ********* my write, buffered writing with minimum 50k chunks ************ */
2002-10-12 11:37:38 +00:00
typedef struct {
struct SDNA *sdna;
int file;
unsigned char *buf;
MemFile *compare, *current;
int tot, count, error, memsize;
2002-10-12 11:37:38 +00:00
} WriteData;
static WriteData *writedata_new(int file)
2002-10-12 11:37:38 +00:00
{
extern char DNAstr[]; /* DNA.c */
extern int DNAlen;
2002-10-12 11:37:38 +00:00
WriteData *wd= MEM_callocN(sizeof(*wd), "writedata");
/* XXX, see note about this in readfile.c, remove
* once we have an xp lock - zr
*/
wd->sdna= dna_sdna_from_data(DNAstr, DNAlen, 0);
2002-10-12 11:37:38 +00:00
wd->file= file;
wd->buf= MEM_mallocN(100000, "wd->buf");
2002-10-12 11:37:38 +00:00
return wd;
}
static void writedata_do_write(WriteData *wd, void *mem, int memlen)
{
if (wd->error) return;
/* memory based save */
if(wd->current) {
add_memfilechunk(NULL, wd->current, mem, memlen);
}
else {
if (write(wd->file, mem, memlen) != memlen)
wd->error= 1;
}
2002-10-12 11:37:38 +00:00
}
static void writedata_free(WriteData *wd)
2002-10-12 11:37:38 +00:00
{
dna_freestructDNA(wd->sdna);
MEM_freeN(wd->buf);
MEM_freeN(wd);
}
/***/
int mywfile;
/**
* Low level WRITE(2) wrapper that buffers data
* @param adr Pointer to new chunk of data
* @param len Length of new chunk of data
* @warning Talks to other functions with global parameters
*/
#define MYWRITE_FLUSH NULL
static void mywrite( WriteData *wd, void *adr, int len)
2002-10-12 11:37:38 +00:00
{
if (wd->error) return;
if(adr==MYWRITE_FLUSH) {
if(wd->count) {
writedata_do_write(wd, wd->buf, wd->count);
wd->count= 0;
}
return;
}
2002-10-12 11:37:38 +00:00
wd->tot+= len;
2002-10-12 11:37:38 +00:00
if(len>50000) {
if(wd->count) {
writedata_do_write(wd, wd->buf, wd->count);
wd->count= 0;
}
writedata_do_write(wd, adr, len);
return;
}
if(len+wd->count>99999) {
writedata_do_write(wd, wd->buf, wd->count);
wd->count= 0;
2002-10-12 11:37:38 +00:00
}
memcpy(&wd->buf[wd->count], adr, len);
wd->count+= len;
2002-10-12 11:37:38 +00:00
}
/**
* BeGiN initializer for mywrite
* @param file File descriptor
* @param write_flags Write parameters
* @warning Talks to other functions with global parameters
*/
static WriteData *bgnwrite(int file, MemFile *compare, MemFile *current, int write_flags)
2002-10-12 11:37:38 +00:00
{
WriteData *wd= writedata_new(file);
wd->compare= compare;
wd->current= current;
/* this inits comparing */
add_memfilechunk(compare, NULL, NULL, 0);
2002-10-12 11:37:38 +00:00
return wd;
}
/**
* END the mywrite wrapper
* @return 1 if write failed
* @return unknown global variable otherwise
* @warning Talks to other functions with global parameters
*/
static int endwrite(WriteData *wd)
2002-10-12 11:37:38 +00:00
{
int err;
2002-10-12 11:37:38 +00:00
if (wd->count) {
writedata_do_write(wd, wd->buf, wd->count);
wd->count= 0;
2002-10-12 11:37:38 +00:00
}
2002-10-12 11:37:38 +00:00
err= wd->error;
writedata_free(wd);
2004-09-07 20:45:09 +00:00
/* blender gods may live forever but this parent pointer died in the statement above
if(wd->current) printf("undo size %d\n", wd->current->size);
2004-09-07 20:45:09 +00:00
*/
2002-10-12 11:37:38 +00:00
return err;
}
/* ********** WRITE FILE ****************** */
static void writestruct(WriteData *wd, int filecode, char *structname, int nr, void *adr)
{
BHead bh;
short *sp;
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
if(adr==NULL || nr==0) return;
/* init BHead */
2002-10-12 11:37:38 +00:00
bh.code= filecode;
bh.old= adr;
bh.nr= nr;
2002-10-12 11:37:38 +00:00
bh.SDNAnr= dna_findstruct_nr(wd->sdna, structname);
if(bh.SDNAnr== -1) {
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
printf("error: can't find SDNA code <%s>\n", structname);
2002-10-12 11:37:38 +00:00
return;
}
sp= wd->sdna->structs[bh.SDNAnr];
2002-10-12 11:37:38 +00:00
bh.len= nr*wd->sdna->typelens[sp[0]];
2002-10-12 11:37:38 +00:00
if(bh.len==0) return;
2002-10-12 11:37:38 +00:00
mywrite(wd, &bh, sizeof(BHead));
mywrite(wd, adr, bh.len);
}
static void writedata(WriteData *wd, int filecode, int len, void *adr) /* do not use for structs */
2002-10-12 11:37:38 +00:00
{
BHead bh;
2002-10-12 11:37:38 +00:00
if(adr==0) return;
if(len==0) return;
2002-10-12 11:37:38 +00:00
len+= 3;
len-= ( len % 4);
/* init BHead */
2002-10-12 11:37:38 +00:00
bh.code= filecode;
bh.old= adr;
bh.nr= 1;
bh.SDNAnr= 0;
2002-10-12 11:37:38 +00:00
bh.len= len;
2002-10-12 11:37:38 +00:00
mywrite(wd, &bh, sizeof(BHead));
if(len) mywrite(wd, adr, len);
}
Orange: - New UI element: the "Curve Button". For mapping ranges (like 0 - 1) to another range, the curve button can be used for proportional falloff, bone influences, painting density, etc. Most evident use is of course to map RGB color with curves. To be able to use it, you have to allocate a CurveMapping struct and pass this on to the button. The CurveMapping API is in the new C file blenkernel/intern/colortools.c It's as simple as calling: curvemap= curvemapping_add(3, 0, 0, 1, 1) Which will create 3 curves, and sets a default 0-1 range. The current code only supports up to 4 curves maximum per mapping struct. The CurveMap button in Blender than handles allmost all editing. Evaluating a single channel: float newvalue= curvemapping_evaluateF(curvemap, 0, oldval); Where the second argument is the channel index, here 0-1-2 are possible. Or mapping a vector: curvemapping_evaluate3F(curvemap, newvec, oldvec); Optimized versions for byte or short mapping is possible too, not done yet. In butspace.c I've added a template wrapper for buttons around the curve, to reveil settings or show tools; check this screenie: http://www.blender.org/bf/curves.jpg - Buttons R, G, B: select channel - icons + and -: zoom in, out - icon 'wrench': menu with tools, like clear curve, set handle type - icon 'clipping': menu with clip values, and to dis/enable clipping - icon 'x': delete selection In the curve button itself, only LMB clicks are handled (like all UI elements in Blender). - click on point: select - shift+click on point: swap select - click on point + drag: select point (if not selected) and move it - click outside point + drag: translate view - CTRL+click: add new point - hold SHIFT while dragging to snap to grid (Yes I know... either one of these can be Blender compliant, not both!) - if you drag a point exactly on top of another, it merges them Other fixes: - Icons now draw using "Safe RasterPos", so they align with pixel boundary. the old code made ints from the raster pos coordinate, which doesn't work well for zoom in/out situations - bug in Node editing: buttons could not get freed, causing in memory error prints at end of a Blender session. That one was a very simple, but nasty error causing me all evening last night to find! (Hint; check diff of editnode.c, where uiDoButtons is called) Last note: this adds 3 new files in our tree, I did scons, but not MSVC!
2006-01-08 11:41:06 +00:00
/* *************** writing some direct data structs used in more code parts **************** */
static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
{
int a;
writestruct(wd, DATA, "CurveMapping", 1, cumap);
for(a=0; a<CM_TOT; a++)
writestruct(wd, DATA, "CurveMapPoint", cumap->cm[a].totpoint, cumap->cm[a].curve);
}
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
/* this is only direct data, tree itself should have been written */
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
bNodeLink *link;
/* for link_list() speed, we write per list */
for(node= ntree->nodes.first; node; node= node->next)
writestruct(wd, DATA, "bNode", 1, node);
for(node= ntree->nodes.first; node; node= node->next) {
Orange: - New UI element: the "Curve Button". For mapping ranges (like 0 - 1) to another range, the curve button can be used for proportional falloff, bone influences, painting density, etc. Most evident use is of course to map RGB color with curves. To be able to use it, you have to allocate a CurveMapping struct and pass this on to the button. The CurveMapping API is in the new C file blenkernel/intern/colortools.c It's as simple as calling: curvemap= curvemapping_add(3, 0, 0, 1, 1) Which will create 3 curves, and sets a default 0-1 range. The current code only supports up to 4 curves maximum per mapping struct. The CurveMap button in Blender than handles allmost all editing. Evaluating a single channel: float newvalue= curvemapping_evaluateF(curvemap, 0, oldval); Where the second argument is the channel index, here 0-1-2 are possible. Or mapping a vector: curvemapping_evaluate3F(curvemap, newvec, oldvec); Optimized versions for byte or short mapping is possible too, not done yet. In butspace.c I've added a template wrapper for buttons around the curve, to reveil settings or show tools; check this screenie: http://www.blender.org/bf/curves.jpg - Buttons R, G, B: select channel - icons + and -: zoom in, out - icon 'wrench': menu with tools, like clear curve, set handle type - icon 'clipping': menu with clip values, and to dis/enable clipping - icon 'x': delete selection In the curve button itself, only LMB clicks are handled (like all UI elements in Blender). - click on point: select - shift+click on point: swap select - click on point + drag: select point (if not selected) and move it - click outside point + drag: translate view - CTRL+click: add new point - hold SHIFT while dragging to snap to grid (Yes I know... either one of these can be Blender compliant, not both!) - if you drag a point exactly on top of another, it merges them Other fixes: - Icons now draw using "Safe RasterPos", so they align with pixel boundary. the old code made ints from the raster pos coordinate, which doesn't work well for zoom in/out situations - bug in Node editing: buttons could not get freed, causing in memory error prints at end of a Blender session. That one was a very simple, but nasty error causing me all evening last night to find! (Hint; check diff of editnode.c, where uiDoButtons is called) Last note: this adds 3 new files in our tree, I did scons, but not MSVC!
2006-01-08 11:41:06 +00:00
if(node->storage) {
/* could be handlerized at some point, now only 1 exception still */
if(ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
write_curvemapping(wd, node->storage);
else
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
for(sock= node->inputs.first; sock; sock= sock->next)
writestruct(wd, DATA, "bNodeSocket", 1, sock);
for(sock= node->outputs.first; sock; sock= sock->next)
writestruct(wd, DATA, "bNodeSocket", 1, sock);
}
for(link= ntree->links.first; link; link= link->next)
writestruct(wd, DATA, "bNodeLink", 1, link);
}
2002-10-12 11:37:38 +00:00
static void write_scriptlink(WriteData *wd, ScriptLink *slink)
{
writedata(wd, DATA, sizeof(void *)*slink->totscript, slink->scripts);
writedata(wd, DATA, sizeof(short)*slink->totscript, slink->flag);
2002-10-12 11:37:38 +00:00
}
static void write_renderinfo(WriteData *wd) /* for renderdaemon */
2002-10-12 11:37:38 +00:00
{
Scene *sce;
int data[8];
2002-10-12 11:37:38 +00:00
sce= G.main->scene.first;
while(sce) {
if(sce->id.lib==0 && ( sce==G.scene || (sce->r.scemode & R_BG_RENDER)) ) {
data[0]= sce->r.sfra;
data[1]= sce->r.efra;
2002-10-12 11:37:38 +00:00
strncpy((char *)(data+2), sce->id.name+2, 23);
2002-10-12 11:37:38 +00:00
writedata(wd, REND, 32, data);
}
sce= sce->id.next;
}
}
static void write_userdef(WriteData *wd)
{
bTheme *btheme;
2002-10-12 11:37:38 +00:00
writestruct(wd, USER, "UserDef", 1, &U);
btheme= U.themes.first;
while(btheme) {
writestruct(wd, DATA, "bTheme", 1, btheme);
btheme= btheme->next;
}
2002-10-12 11:37:38 +00:00
}
static void write_effects(WriteData *wd, ListBase *lb)
{
Effect *eff;
2002-10-12 11:37:38 +00:00
eff= lb->first;
while(eff) {
2002-10-12 11:37:38 +00:00
switch(eff->type) {
case EFF_PARTICLE:
writestruct(wd, DATA, "PartEff", 1, eff);
break;
2002-10-12 11:37:38 +00:00
default:
writedata(wd, DATA, MEM_allocN_len(eff), eff);
}
2002-10-12 11:37:38 +00:00
eff= eff->next;
}
}
static void write_properties(WriteData *wd, ListBase *lb)
{
bProperty *prop;
2002-10-12 11:37:38 +00:00
prop= lb->first;
while(prop) {
writestruct(wd, DATA, "bProperty", 1, prop);
if(prop->poin && prop->poin != &prop->data)
2002-10-12 11:37:38 +00:00
writedata(wd, DATA, MEM_allocN_len(prop->poin), prop->poin);
2002-10-12 11:37:38 +00:00
prop= prop->next;
}
}
static void write_sensors(WriteData *wd, ListBase *lb)
{
bSensor *sens;
2002-10-12 11:37:38 +00:00
sens= lb->first;
while(sens) {
writestruct(wd, DATA, "bSensor", 1, sens);
2002-10-12 11:37:38 +00:00
writedata(wd, DATA, sizeof(void *)*sens->totlinks, sens->links);
2002-10-12 11:37:38 +00:00
switch(sens->type) {
case SENS_NEAR:
writestruct(wd, DATA, "bNearSensor", 1, sens->data);
break;
case SENS_MOUSE:
writestruct(wd, DATA, "bMouseSensor", 1, sens->data);
break;
case SENS_TOUCH:
writestruct(wd, DATA, "bTouchSensor", 1, sens->data);
break;
case SENS_KEYBOARD:
writestruct(wd, DATA, "bKeyboardSensor", 1, sens->data);
break;
case SENS_PROPERTY:
writestruct(wd, DATA, "bPropertySensor", 1, sens->data);
break;
case SENS_COLLISION:
writestruct(wd, DATA, "bCollisionSensor", 1, sens->data);
break;
case SENS_RADAR:
writestruct(wd, DATA, "bRadarSensor", 1, sens->data);
break;
case SENS_RANDOM:
writestruct(wd, DATA, "bRandomSensor", 1, sens->data);
break;
case SENS_RAY:
writestruct(wd, DATA, "bRaySensor", 1, sens->data);
break;
case SENS_MESSAGE:
writestruct(wd, DATA, "bMessageSensor", 1, sens->data);
break;
2005-01-23 01:36:29 +00:00
case SENS_JOYSTICK:
writestruct(wd, DATA, "bJoystickSensor", 1, sens->data);
break;
2002-10-12 11:37:38 +00:00
default:
; /* error: don't know how to write this file */
}
2002-10-12 11:37:38 +00:00
sens= sens->next;
}
}
static void write_controllers(WriteData *wd, ListBase *lb)
{
bController *cont;
2002-10-12 11:37:38 +00:00
cont= lb->first;
while(cont) {
writestruct(wd, DATA, "bController", 1, cont);
2002-10-12 11:37:38 +00:00
writedata(wd, DATA, sizeof(void *)*cont->totlinks, cont->links);
2002-10-12 11:37:38 +00:00
switch(cont->type) {
case CONT_EXPRESSION:
writestruct(wd, DATA, "bExpressionCont", 1, cont->data);
break;
case CONT_PYTHON:
writestruct(wd, DATA, "bPythonCont", 1, cont->data);
break;
default:
; /* error: don't know how to write this file */
}
2002-10-12 11:37:38 +00:00
cont= cont->next;
}
}
static void write_actuators(WriteData *wd, ListBase *lb)
{
bActuator *act;
2002-10-12 11:37:38 +00:00
act= lb->first;
while(act) {
writestruct(wd, DATA, "bActuator", 1, act);
2002-10-12 11:37:38 +00:00
switch(act->type) {
case ACT_ACTION:
writestruct(wd, DATA, "bActionActuator", 1, act->data);
break;
case ACT_SOUND:
writestruct(wd, DATA, "bSoundActuator", 1, act->data);
break;
case ACT_CD:
writestruct(wd, DATA, "bCDActuator", 1, act->data);
break;
case ACT_OBJECT:
writestruct(wd, DATA, "bObjectActuator", 1, act->data);
break;
case ACT_IPO:
writestruct(wd, DATA, "bIpoActuator", 1, act->data);
break;
case ACT_PROPERTY:
writestruct(wd, DATA, "bPropertyActuator", 1, act->data);
break;
case ACT_CAMERA:
writestruct(wd, DATA, "bCameraActuator", 1, act->data);
break;
case ACT_CONSTRAINT:
writestruct(wd, DATA, "bConstraintActuator", 1, act->data);
break;
case ACT_EDIT_OBJECT:
writestruct(wd, DATA, "bEditObjectActuator", 1, act->data);
break;
case ACT_SCENE:
writestruct(wd, DATA, "bSceneActuator", 1, act->data);
break;
case ACT_GROUP:
writestruct(wd, DATA, "bGroupActuator", 1, act->data);
break;
case ACT_RANDOM:
writestruct(wd, DATA, "bRandomActuator", 1, act->data);
break;
case ACT_MESSAGE:
writestruct(wd, DATA, "bMessageActuator", 1, act->data);
break;
case ACT_GAME:
writestruct(wd, DATA, "bGameActuator", 1, act->data);
break;
case ACT_VISIBILITY:
writestruct(wd, DATA, "bVisibilityActuator", 1, act->data);
break;
default:
; /* error: don't know how to write this file */
}
2002-10-12 11:37:38 +00:00
act= act->next;
}
}
static void write_nlastrips(WriteData *wd, ListBase *nlabase)
{
bActionStrip *strip;
for (strip=nlabase->first; strip; strip=strip->next)
writestruct(wd, DATA, "bActionStrip", 1, strip);
}
static void write_constraints(WriteData *wd, ListBase *conlist)
{
bConstraint *con;
2002-10-12 11:37:38 +00:00
for (con=conlist->first; con; con=con->next) {
/* Write the specific data */
switch (con->type) {
case CONSTRAINT_TYPE_NULL:
break;
case CONSTRAINT_TYPE_TRACKTO:
writestruct(wd, DATA, "bTrackToConstraint", 1, con->data);
break;
case CONSTRAINT_TYPE_KINEMATIC:
writestruct(wd, DATA, "bKinematicConstraint", 1, con->data);
break;
case CONSTRAINT_TYPE_ROTLIKE:
writestruct(wd, DATA, "bRotateLikeConstraint", 1, con->data);
break;
case CONSTRAINT_TYPE_LOCLIKE:
writestruct(wd, DATA, "bLocateLikeConstraint", 1, con->data);
break;
case CONSTRAINT_TYPE_ACTION:
writestruct(wd, DATA, "bActionConstraint", 1, con->data);
break;
case CONSTRAINT_TYPE_LOCKTRACK:
writestruct(wd, DATA, "bLockTrackConstraint", 1, con->data);
break;
case CONSTRAINT_TYPE_FOLLOWPATH:
writestruct(wd, DATA, "bFollowPathConstraint", 1, con->data);
break;
case CONSTRAINT_TYPE_STRETCHTO:
writestruct(wd, DATA, "bStretchToConstraint", 1, con->data);
break;
case CONSTRAINT_TYPE_MINMAX:
writestruct(wd, DATA, "bMinMaxConstraint", 1, con->data);
break;
2002-10-12 11:37:38 +00:00
default:
break;
}
/* Write the constraint */
writestruct(wd, DATA, "bConstraint", 1, con);
}
}
static void write_pose(WriteData *wd, bPose *pose)
{
bPoseChannel *chan;
2002-10-12 11:37:38 +00:00
/* Write each channel */
2002-10-12 11:37:38 +00:00
if (!pose)
return;
2002-10-12 11:37:38 +00:00
// Write channels
for (chan=pose->chanbase.first; chan; chan=chan->next) {
write_constraints(wd, &chan->constraints);
writestruct(wd, DATA, "bPoseChannel", 1, chan);
}
// Write this pose
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "bPose", 1, pose);
}
static void write_defgroups(WriteData *wd, ListBase *defbase)
{
bDeformGroup *defgroup;
2002-10-12 11:37:38 +00:00
for (defgroup=defbase->first; defgroup; defgroup=defgroup->next)
writestruct(wd, DATA, "bDeformGroup", 1, defgroup);
}
static void write_constraint_channels(WriteData *wd, ListBase *chanbase)
{
bConstraintChannel *chan;
for (chan = chanbase->first; chan; chan=chan->next)
writestruct(wd, DATA, "bConstraintChannel", 1, chan);
2002-10-12 11:37:38 +00:00
}
static void write_modifiers(WriteData *wd, ListBase *modbase)
{
ModifierData *md;
for (md=modbase->first; md; md= md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
writestruct(wd, DATA, mti->structName, 1, md);
if (md->type==eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData*) md;
writedata(wd, DATA, sizeof(int)*hmd->totindex, hmd->indexar);
}
}
}
2002-10-12 11:37:38 +00:00
static void write_objects(WriteData *wd, ListBase *idbase)
{
Object *ob;
int a;
2002-10-12 11:37:38 +00:00
ob= idbase->first;
while(ob) {
if(ob->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_OB, "Object", 1, ob);
/* direct data */
2002-10-12 11:37:38 +00:00
writedata(wd, DATA, sizeof(void *)*ob->totcol, ob->mat);
write_effects(wd, &ob->effect);
write_properties(wd, &ob->prop);
write_sensors(wd, &ob->sensors);
write_controllers(wd, &ob->controllers);
write_actuators(wd, &ob->actuators);
write_scriptlink(wd, &ob->scriptlink);
write_pose(wd, ob->pose);
write_defgroups(wd, &ob->defbase);
write_constraints(wd, &ob->constraints);
write_constraint_channels(wd, &ob->constraintChannels);
write_nlastrips(wd, &ob->nlastrips);
writestruct(wd, DATA, "PartDeflect", 1, ob->pd);
writestruct(wd, DATA, "SoftBody", 1, ob->soft);
if(ob->soft) {
SoftBody *sb= ob->soft;
if(sb->keys) {
writedata(wd, DATA, sizeof(void *)*sb->totkey, sb->keys);
for(a=0; a<sb->totkey; a++) {
writestruct(wd, DATA, "SBVertex", sb->totpoint, sb->keys[a]);
}
}
}
writestruct(wd, DATA, "FluidsimSettings", 1, ob->fluidsimSettings); // NT
write_modifiers(wd, &ob->modifiers);
2002-10-12 11:37:38 +00:00
}
ob= ob->id.next;
}
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);
2002-10-12 11:37:38 +00:00
}
static void write_vfonts(WriteData *wd, ListBase *idbase)
{
VFont *vf;
PackedFile * pf;
2002-10-12 11:37:38 +00:00
vf= idbase->first;
while(vf) {
if(vf->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_VF, "VFont", 1, vf);
/* direct data */
2002-10-12 11:37:38 +00:00
if (vf->packedfile) {
pf = vf->packedfile;
writestruct(wd, DATA, "PackedFile", 1, pf);
writedata(wd, DATA, pf->size, pf->data);
}
}
2002-10-12 11:37:38 +00:00
vf= vf->id.next;
}
}
static void write_ipos(WriteData *wd, ListBase *idbase)
{
Ipo *ipo;
IpoCurve *icu;
2002-10-12 11:37:38 +00:00
ipo= idbase->first;
while(ipo) {
if(ipo->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_IP, "Ipo", 1, ipo);
/* direct data */
2002-10-12 11:37:38 +00:00
icu= ipo->curve.first;
while(icu) {
writestruct(wd, DATA, "IpoCurve", 1, icu);
icu= icu->next;
}
2002-10-12 11:37:38 +00:00
icu= ipo->curve.first;
while(icu) {
if(icu->bezt) writestruct(wd, DATA, "BezTriple", icu->totvert, icu->bezt);
if(icu->bp) writestruct(wd, DATA, "BPoint", icu->totvert, icu->bp);
Version 1.0 of IpoDrivers. First note that this is new functionality, unfinished, and only for testing and feedback purposes. I'll list below what works, and what will need work still. This text is also in cms: http://www.blender.org/cms/Ipo_Drivers.680.0.html An IpoDriver is like an IpoCurve, but instead of a Bezier curve, it allows to connect a property of other Objects as input for the "channel". For example, IpoDrivers can be used to have a Shape Key being "driven" by the rotation of a Bone. Or the RGB colors of a Material get driven by the XYZ location of an Object. Editing of Drivers happens in the IpoWindow. Here you can notice that the channels (right hand window) now have an "active" channel indicator. To add a Driver, you have to use the "Transform Properties" Panel (Nkey). Here you can add or remove a Driver to the active channel, and use the buttons to fill in what kind of relationship you want to establish. Driver Objects Note that any Ipo Channel can become driven now, but that only Object transformation or Pose Bone transformation can be used to become a Driver now. At this moment, only the local transformation is taken into account. For Objects that means the location/rotation/scale value without Parent transform (as shown in "Transform Properties" Panel for Objects). For Pose Bones it means that only the Pose transform (changes of rest position) is Driver information (also as shown in Transform Property Panel in Pose Mode). Mapping of Drivers When an Ipo Channel is "driven", the mapping is by default one-to-one. It is only restricted by already built-in limits for Channels, like for Material the "R" value can only range from 0.0 to 1.0. Also note that when mapping rotations, the actual rotation values in Ipos are scaled down with a factor 10.0. (180 degrees actually has in the Ipo system a value of 18.0). This is an ancient year zero convention in Blender... it is a bit hidden, because the ruler (vertical as well as horizontal) displays the virtual values correctly. Only the Properties panel shows the actual value. When you draw an IpoCurve in a Driven channel, this curve will define the mapping between the Driver output (horizontal) and Driven input (vertical, as usual). A nice new option to use is "Insert one-to-one curve" (press I-key, or in pulldown menu). This will also zoom the display in exactly to fill the window, allowing easy edit. If you use this option with degrees, it will map 180 degree rotation to a range of 1.0 unit. Live updates Since the Drivers are integrated in the Ipo system, they will always be updated whenever an Ipo is evaluated. This happens at least on frame changes. For interactive feedback, updates while transforming objects were added in these cases: - Driven Object Ipos, by other Objects or Pose Bones - Driven Shape Key Ipos, by other Objects or Pose Bones You can also insert Drivers on Action Ipos, but these are only evaluated on frame change now. Todo - Drivers can also get a text button, allowing a 1 line Python script to be executed. - Make UI for it a bit less hidden... maybe with visualization in 3D? - Allowing global transform coordinates as Driver too. Issues - renaming Bones won't rename drivers - (file) appending the Ipo won't append the linked driver Objects
2005-10-02 20:51:35 +00:00
if(icu->driver) writestruct(wd, DATA, "IpoDriver", 1, icu->driver);
2002-10-12 11:37:38 +00:00
icu= icu->next;
}
}
2002-10-12 11:37:38 +00:00
ipo= ipo->id.next;
}
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);
2002-10-12 11:37:38 +00:00
}
static void write_keys(WriteData *wd, ListBase *idbase)
{
Key *key;
KeyBlock *kb;
2002-10-12 11:37:38 +00:00
key= idbase->first;
while(key) {
if(key->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_KE, "Key", 1, key);
/* direct data */
2002-10-12 11:37:38 +00:00
kb= key->block.first;
while(kb) {
writestruct(wd, DATA, "KeyBlock", 1, kb);
if(kb->data) writedata(wd, DATA, kb->totelem*key->elemsize, kb->data);
kb= kb->next;
}
}
2002-10-12 11:37:38 +00:00
key= key->id.next;
}
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);
2002-10-12 11:37:38 +00:00
}
static void write_cameras(WriteData *wd, ListBase *idbase)
{
Camera *cam;
2002-10-12 11:37:38 +00:00
cam= idbase->first;
while(cam) {
if(cam->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_CA, "Camera", 1, cam);
/* direct data */
2002-10-12 11:37:38 +00:00
write_scriptlink(wd, &cam->scriptlink);
}
2002-10-12 11:37:38 +00:00
cam= cam->id.next;
}
}
static void write_mballs(WriteData *wd, ListBase *idbase)
{
MetaBall *mb;
MetaElem *ml;
2002-10-12 11:37:38 +00:00
mb= idbase->first;
while(mb) {
if(mb->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_MB, "MetaBall", 1, mb);
/* direct data */
2002-10-12 11:37:38 +00:00
writedata(wd, DATA, sizeof(void *)*mb->totcol, mb->mat);
2002-10-12 11:37:38 +00:00
ml= mb->elems.first;
while(ml) {
writestruct(wd, DATA, "MetaElem", 1, ml);
ml= ml->next;
}
}
mb= mb->id.next;
}
}
int amount_of_chars(char *str)
{
// Since the data is saved as UTF-8 to the cu->str
// The cu->len is not same as the strlen(cu->str)
return strlen(str);
}
2002-10-12 11:37:38 +00:00
static void write_curves(WriteData *wd, ListBase *idbase)
{
Curve *cu;
Nurb *nu;
2002-10-12 11:37:38 +00:00
cu= idbase->first;
while(cu) {
if(cu->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_CU, "Curve", 1, cu);
/* direct data */
2002-10-12 11:37:38 +00:00
writedata(wd, DATA, sizeof(void *)*cu->totcol, cu->mat);
2002-10-12 11:37:38 +00:00
if(cu->vfont) {
writedata(wd, DATA, amount_of_chars(cu->str)+1, cu->str);
writestruct(wd, DATA, "CharInfo", cu->len, cu->strinfo);
writestruct(wd, DATA, "TextBox", cu->totbox, cu->tb);
2002-10-12 11:37:38 +00:00
}
else {
/* is also the order of reading */
2002-10-12 11:37:38 +00:00
nu= cu->nurb.first;
while(nu) {
writestruct(wd, DATA, "Nurb", 1, nu);
nu= nu->next;
}
nu= cu->nurb.first;
while(nu) {
if( (nu->type & 7)==CU_BEZIER)
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "BezTriple", nu->pntsu, nu->bezt);
else {
writestruct(wd, DATA, "BPoint", nu->pntsu*nu->pntsv, nu->bp);
if(nu->knotsu) writedata(wd, DATA, KNOTSU(nu)*sizeof(float), nu->knotsu);
if(nu->knotsv) writedata(wd, DATA, KNOTSV(nu)*sizeof(float), nu->knotsv);
}
nu= nu->next;
}
}
}
cu= cu->id.next;
}
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);
2002-10-12 11:37:38 +00:00
}
static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
{
int i;
2002-10-12 11:37:38 +00:00
/* Write the dvert list */
writestruct(wd, DATA, "MDeformVert", count, dvlist);
2002-10-12 11:37:38 +00:00
/* Write deformation data for each dvert */
if (dvlist) {
for (i=0; i<count; i++) {
if (dvlist[i].dw)
writestruct(wd, DATA, "MDeformWeight", dvlist[i].totweight, dvlist[i].dw);
2002-10-12 11:37:38 +00:00
}
}
}
static void write_meshs(WriteData *wd, ListBase *idbase)
{
Mesh *mesh;
2002-10-12 11:37:38 +00:00
mesh= idbase->first;
while(mesh) {
if(mesh->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_ME, "Mesh", 1, mesh);
/* direct data */
2002-10-12 11:37:38 +00:00
writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "MVert", mesh->totvert, mesh->mvert);
writestruct(wd, DATA, "MEdge", mesh->totedge, mesh->medge);
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "MFace", mesh->totface, mesh->mface);
writestruct(wd, DATA, "TFace", mesh->totface, mesh->tface);
writestruct(wd, DATA, "MCol", 4*mesh->totface, mesh->mcol);
writestruct(wd, DATA, "MSticky", mesh->totvert, mesh->msticky);
write_dverts(wd, mesh->totvert, mesh->dvert);
2002-10-12 11:37:38 +00:00
}
mesh= mesh->id.next;
}
}
static void write_images(WriteData *wd, ListBase *idbase)
{
Image *ima;
PackedFile * pf;
2002-10-12 11:37:38 +00:00
ima= idbase->first;
while(ima) {
if(ima->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_IM, "Image", 1, ima);
2002-10-12 11:37:38 +00:00
if (ima->packedfile) {
pf = ima->packedfile;
writestruct(wd, DATA, "PackedFile", 1, pf);
writedata(wd, DATA, pf->size, pf->data);
}
}
ima= ima->id.next;
}
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);
2002-10-12 11:37:38 +00:00
}
static void write_textures(WriteData *wd, ListBase *idbase)
{
Tex *tex;
2002-10-12 11:37:38 +00:00
tex= idbase->first;
while(tex) {
if(tex->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_TE, "Tex", 1, tex);
/* direct data */
2002-10-12 11:37:38 +00:00
if(tex->plugin) writestruct(wd, DATA, "PluginTex", 1, tex->plugin);
if(tex->coba) writestruct(wd, DATA, "ColorBand", 1, tex->coba);
if(tex->env) writestruct(wd, DATA, "EnvMap", 1, tex->env);
}
tex= tex->id.next;
}
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);
2002-10-12 11:37:38 +00:00
}
static void write_materials(WriteData *wd, ListBase *idbase)
{
Material *ma;
MaterialLayer *ml;
2002-10-12 11:37:38 +00:00
int a;
2002-10-12 11:37:38 +00:00
ma= idbase->first;
while(ma) {
if(ma->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_MA, "Material", 1, ma);
for(a=0; a<MAX_MTEX; a++) {
2002-10-12 11:37:38 +00:00
if(ma->mtex[a]) writestruct(wd, DATA, "MTex", 1, ma->mtex[a]);
}
if(ma->ramp_col) writestruct(wd, DATA, "ColorBand", 1, ma->ramp_col);
if(ma->ramp_spec) writestruct(wd, DATA, "ColorBand", 1, ma->ramp_spec);
2002-10-12 11:37:38 +00:00
write_scriptlink(wd, &ma->scriptlink);
for (ml=ma->layers.first; ml; ml=ml->next)
writestruct(wd, DATA, "MaterialLayer", 1, ml);
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
/* nodetree is integral part of material, no libdata */
if(ma->nodetree) {
writestruct(wd, DATA, "bNodeTree", 1, ma->nodetree);
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
write_nodetree(wd, ma->nodetree);
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
}
2002-10-12 11:37:38 +00:00
}
ma= ma->id.next;
}
}
static void write_worlds(WriteData *wd, ListBase *idbase)
{
World *wrld;
int a;
2002-10-12 11:37:38 +00:00
wrld= idbase->first;
while(wrld) {
if(wrld->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_WO, "World", 1, wrld);
for(a=0; a<MAX_MTEX; a++) {
2002-10-12 11:37:38 +00:00
if(wrld->mtex[a]) writestruct(wd, DATA, "MTex", 1, wrld->mtex[a]);
}
2002-10-12 11:37:38 +00:00
write_scriptlink(wd, &wrld->scriptlink);
}
wrld= wrld->id.next;
}
}
static void write_lamps(WriteData *wd, ListBase *idbase)
{
Lamp *la;
int a;
2002-10-12 11:37:38 +00:00
la= idbase->first;
while(la) {
if(la->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_LA, "Lamp", 1, la);
/* direct data */
for(a=0; a<MAX_MTEX; a++) {
2002-10-12 11:37:38 +00:00
if(la->mtex[a]) writestruct(wd, DATA, "MTex", 1, la->mtex[a]);
}
2002-10-12 11:37:38 +00:00
write_scriptlink(wd, &la->scriptlink);
}
la= la->id.next;
}
}
static void write_lattices(WriteData *wd, ListBase *idbase)
{
Lattice *lt;
2002-10-12 11:37:38 +00:00
lt= idbase->first;
while(lt) {
if(lt->id.us>0 || wd->current) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_LT, "Lattice", 1, lt);
/* direct data */
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "BPoint", lt->pntsu*lt->pntsv*lt->pntsw, lt->def);
}
lt= lt->id.next;
}
}
static void write_scenes(WriteData *wd, ListBase *scebase)
{
Scene *sce;
Base *base;
Editing *ed;
Sequence *seq;
MetaStack *ms;
2002-10-12 11:37:38 +00:00
Strip *strip;
Added the new Timeline Window, copied from Tuhopuu, coded by Matt Ebb. Main change is that it's an own Space type now, not part of the Audio window... the audio window should restrict to own options. This way functionality is nicely separated. Since it's the first time I added a new space (since long!) I've made an extensive tutorial as well. You can find that here: http://www.blender3d.org/cms/Adding_new_Space_Window.557.0.html Notes for using timewindow; - Add time markers with MKey - CTRL+M gives option to name Marker - Markers cannot be moved yet... - Pageup-Pagedown keys moves current frame to next-prev Marker - Xkey removes Markers - If an object has Ipos or an Action, it draws key lines - CTRL+Pageup-Pagedown moves current frame to next-prev Key - Press S or E to set start/end frame for playback Notes about the implementation in Tuhopuu: - Add new Marker now selects new, deselects others - Selecting Marker didn't work like elsewhere in Blender, on click it should deselect all, except the indicated Marker. Not when holding SHIFT of course - Not exported functions are static now - Removed unused defines (MARKER_NONE NEXT_AVAIL) - Drawing order was confusing, doing too many matrix calls - Removed not needed scrollbar, added new function to draw time values. (Has advantage the MMB scroll works not confusing on a scrollbar) - Added proper support for 'frame mapping' - The string button (name Marker) had a bug (checked str[64] while str was only 64 long) - String button itself didn't allow "OK on enter" - Made frame buttons in header larger, the arrows overlapped - Removed support for negative frame values, that won't work so simple!
2005-05-05 17:19:21 +00:00
TimeMarker *marker;
2002-10-12 11:37:38 +00:00
sce= scebase->first;
while(sce) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_SCE, "Scene", 1, sce);
/* direct data */
2002-10-12 11:37:38 +00:00
base= sce->base.first;
while(base) {
writestruct(wd, DATA, "Base", 1, base);
base= base->next;
}
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "Radio", 1, sce->radio);
writestruct(wd, DATA, "ToolSettings", 1, sce->toolsettings);
2002-10-12 11:37:38 +00:00
ed= sce->ed;
if(ed) {
writestruct(wd, DATA, "Editing", 1, ed);
/* reset write flags too */
2002-10-12 11:37:38 +00:00
WHILE_SEQ(&ed->seqbase) {
if(seq->strip) seq->strip->done= 0;
writestruct(wd, DATA, "Sequence", 1, seq);
}
END_SEQ
2002-10-12 11:37:38 +00:00
WHILE_SEQ(&ed->seqbase) {
if(seq->strip && seq->strip->done==0) {
/* write strip with 'done' at 0 because readfile */
2002-10-12 11:37:38 +00:00
if(seq->plugin) writestruct(wd, DATA, "PluginSeq", 1, seq->plugin);
if(seq->effectdata) {
switch(seq->type){
case SEQ_WIPE:
writestruct(wd, DATA, "WipeVars", 1, seq->effectdata);
break;
case SEQ_GLOW:
writestruct(wd, DATA, "GlowVars", 1, seq->effectdata);
break;
}
}
2002-10-12 11:37:38 +00:00
strip= seq->strip;
writestruct(wd, DATA, "Strip", 1, strip);
if(seq->type==SEQ_IMAGE)
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "StripElem", strip->len, strip->stripdata);
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(seq->type==SEQ_MOVIE || seq->type==SEQ_SOUND)
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "StripElem", 1, strip->stripdata);
2002-10-12 11:37:38 +00:00
strip->done= 1;
}
}
END_SEQ
/* new; meta stack too, even when its nasty restore code */
for(ms= ed->metastack.first; ms; ms= ms->next) {
writestruct(wd, DATA, "MetaStack", 1, ms);
}
2002-10-12 11:37:38 +00:00
}
2002-10-12 11:37:38 +00:00
write_scriptlink(wd, &sce->scriptlink);
if (sce->r.avicodecdata) {
writestruct(wd, DATA, "AviCodecData", 1, sce->r.avicodecdata);
if (sce->r.avicodecdata->lpFormat) writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
if (sce->r.avicodecdata->lpParms) writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
}
if (sce->r.qtcodecdata) {
writestruct(wd, DATA, "QuicktimeCodecData", 1, sce->r.qtcodecdata);
if (sce->r.qtcodecdata->cdParms) writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms);
}
Added the new Timeline Window, copied from Tuhopuu, coded by Matt Ebb. Main change is that it's an own Space type now, not part of the Audio window... the audio window should restrict to own options. This way functionality is nicely separated. Since it's the first time I added a new space (since long!) I've made an extensive tutorial as well. You can find that here: http://www.blender3d.org/cms/Adding_new_Space_Window.557.0.html Notes for using timewindow; - Add time markers with MKey - CTRL+M gives option to name Marker - Markers cannot be moved yet... - Pageup-Pagedown keys moves current frame to next-prev Marker - Xkey removes Markers - If an object has Ipos or an Action, it draws key lines - CTRL+Pageup-Pagedown moves current frame to next-prev Key - Press S or E to set start/end frame for playback Notes about the implementation in Tuhopuu: - Add new Marker now selects new, deselects others - Selecting Marker didn't work like elsewhere in Blender, on click it should deselect all, except the indicated Marker. Not when holding SHIFT of course - Not exported functions are static now - Removed unused defines (MARKER_NONE NEXT_AVAIL) - Drawing order was confusing, doing too many matrix calls - Removed not needed scrollbar, added new function to draw time values. (Has advantage the MMB scroll works not confusing on a scrollbar) - Added proper support for 'frame mapping' - The string button (name Marker) had a bug (checked str[64] while str was only 64 long) - String button itself didn't allow "OK on enter" - Made frame buttons in header larger, the arrows overlapped - Removed support for negative frame values, that won't work so simple!
2005-05-05 17:19:21 +00:00
/* writing dynamic list of TimeMarkers to the blend file */
marker= sce->markers.first;
while(marker){
writestruct(wd, DATA, "TimeMarker", 1, marker);
marker= marker->next;
}
2002-10-12 11:37:38 +00:00
sce= sce->id.next;
}
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);
2002-10-12 11:37:38 +00:00
}
static void write_screens(WriteData *wd, ListBase *scrbase)
{
bScreen *sc;
ScrArea *sa;
ScrVert *sv;
ScrEdge *se;
2002-10-12 11:37:38 +00:00
sc= scrbase->first;
while(sc) {
/* write LibData */
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_SCR, "Screen", 1, sc);
/* direct data */
2002-10-12 11:37:38 +00:00
sv= sc->vertbase.first;
while(sv) {
writestruct(wd, DATA, "ScrVert", 1, sv);
sv= sv->next;
}
2002-10-12 11:37:38 +00:00
se= sc->edgebase.first;
while(se) {
writestruct(wd, DATA, "ScrEdge", 1, se);
se= se->next;
}
2002-10-12 11:37:38 +00:00
sa= sc->areabase.first;
while(sa) {
SpaceLink *sl;
Panel *pa;
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "ScrArea", 1, sa);
pa= sa->panels.first;
while(pa) {
writestruct(wd, DATA, "Panel", 1, pa);
pa= pa->next;
}
BPython: - Made Blender.event var (previously only used by script links) hold ascii value -- where it applies -- of current event during events callback registered with Draw.Register(gui, events, button_events). Useful for gui scripts like Campbell's Python console. No problem using this var to hold the value, since in gui scripts it was not used (always None). - Updated Window and Window.Theme with new theme vars and the Time space. - Script links: -- Added "Render" event for script links (runs twice, second time as "PostEvent", for clean-up actions). Now FrameChanged links don't run when a single pic is rendered. -- Added "Enable Script Links" button in the script buttons tab. Now this bit gets saved in .blends along with the rest of G.f, so users can define per .blend if they are on or off by default. "blender -y" also disables all slinks as happened before with OnLoad ones only. -- Other small changes in the script buttons tab: When a link is added (button "new"), it becomes the active one for the window, no need to press a button to reach it. Also, a pupmenu showing all available texts is shown when "new" is pressed, so users can choose a text w/o having to type. Cancel the popup to leave the string button empty (link exists, but has no script assigned). A pulldown would be better UI-wise, but it's kinda weird to show both scripts and normal texts (Blender doesn't differentiate them) in a script links pulldown. With a popup we can show only texts ending in ".py" (not done in this commit, need opinions) and if the script has no or another extension, case of many in old and current .blend's, there's still the string box for writing its name. -- Implemented Ton's space handler script links: Right now only for the 3d View, but it's trivial to add for others. There are two types: EVENT, to receive 3d View events from a chosen window and DRAW, to draw on the window. Ton's idea was to give scripts a controlled way to integrate better within Blender. Here's how it works: - scripts must have a proper header, like: # SPACEHANDLER.VIEW3D.EVENT and then they are shown in 3d View's View menu, "Space Handler Scripts" submenu. Check (mark, click on it) a script to make it active. EVENT handlers should consult the Blender.event var to get the current event, which can be compared with values from the Draw module: import Blender from Blender import Draw evt = Blender.event if evt == Draw.AKEY: print "a" elif evt == Draw.LEFTMOUSE: print "left mouse button" else: return # ignore, pass event back to Blender Blender.event = None # tell Blender not to process itself the event DRAW handlers are free to draw to their owner 3D View. OpenGL attributes and modelview and projection matrices are pushed before running the handler and poped when it finishes. To communicate between EVENT and DRAW handler scripts we have the Blender.Registry module, as always. Still need to code some nice example, which should also serve to test properly space handlers. Simple tests went fine. - doc updates about the additions. ======= Note: the UI part of the space handlers and script links is of course open for changes, I just tried to make it understandable. Probably we won't use the scriptlinks icon for "None Available" (check 3d View -> View -> Space Handler Scripts), though it hints at what space handlers are. The tooltips may not be accepted either, since other menus don't use them. Opinions welcomed.
2005-05-08 21:20:34 +00:00
/* space handler scriptlinks */
write_scriptlink(wd, &sa->scriptlink);
2002-10-12 11:37:38 +00:00
sl= sa->spacedata.first;
while(sl) {
if(sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
writestruct(wd, DATA, "View3D", 1, v3d);
if(v3d->bgpic) writestruct(wd, DATA, "BGpic", 1, v3d->bgpic);
if(v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd);
if(v3d->clipbb) writestruct(wd, DATA, "BoundBox", 1, v3d->clipbb);
2002-10-12 11:37:38 +00:00
}
else if(sl->spacetype==SPACE_IPO) {
writestruct(wd, DATA, "SpaceIpo", 1, sl);
}
else if(sl->spacetype==SPACE_BUTS) {
writestruct(wd, DATA, "SpaceButs", 1, sl);
}
else if(sl->spacetype==SPACE_FILE) {
writestruct(wd, DATA, "SpaceFile", 1, sl);
}
else if(sl->spacetype==SPACE_SEQ) {
writestruct(wd, DATA, "SpaceSeq", 1, sl);
}
else if(sl->spacetype==SPACE_OOPS) {
SpaceOops *so= (SpaceOops *)sl;
Oops *oops;
2002-10-12 11:37:38 +00:00
/* cleanup */
oops= so->oops.first;
while(oops) {
Oops *oopsn= oops->next;
if(oops->id==0) {
BLI_remlink(&so->oops, oops);
free_oops(oops);
}
oops= oopsn;
}
/* ater cleanup, because of listbase! */
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "SpaceOops", 1, so);
2002-10-12 11:37:38 +00:00
oops= so->oops.first;
while(oops) {
writestruct(wd, DATA, "Oops", 1, oops);
oops= oops->next;
}
Version 1.0 of the new Outliner The outliner is a hierarchical diagram displaying a list of data in Blender and its dependencies. The 'databrowse' doesn't really show it, and Oops is too chaotic still. And most of all, the former two don't offer much tools. After discussions on irc, Matt came with this design proposal; http://mke3.net/blender/interface/layout/outliner/ Which is closely followed for the implementation. The current version only shows all 'library data' in Blender (objects, meshes, ipos, etc) and not the 'direct data' such as vertex groups or NLA. I decided to make it inside the Oopw window, as an option. You can find the option in the "View" pulldown, or directly invoke it with ALT+SHIFT+F9 Here's a quick overview of the Outliner GUI: - Header pulldown has options what it can show (Visible = in current layers) - click on triangle arrow to open/close - press AKEY to open/close all - Leftmouse click on an item activates; and does based on type a couple of extra things: - activates a scene - selects/activates the Object - enters editmode (if clicked on Mesh, Curve, etc) - shows the appropriate Shading buttons (Lamp, Material, Texture) - sets the IpoWindow to the current IPO - activates the Ipo-channel in an Action - Selected and Active objects are drawn in its Theme selection color - SHIFT+click on Object does extend-select - Press DOTkey to get the current active data in center of view TODO; - rightmouse selection; for indicating operations like delete or duplicate - showing more data types - icon (re)design... - lotsof options as described in Matts paper still...
2004-10-06 18:55:00 +00:00
/* outliner */
if(so->treestore) {
writestruct(wd, DATA, "TreeStore", 1, so->treestore);
if(so->treestore->data)
writestruct(wd, DATA, "TreeStoreElem", so->treestore->usedelem, so->treestore->data);
}
2002-10-12 11:37:38 +00:00
}
else if(sl->spacetype==SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage *)sl;
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "SpaceImage", 1, sl);
if(sima->cumap)
write_curvemapping(wd, sima->cumap);
2002-10-12 11:37:38 +00:00
}
else if(sl->spacetype==SPACE_IMASEL) {
writestruct(wd, DATA, "SpaceImaSel", 1, sl);
}
else if(sl->spacetype==SPACE_TEXT) {
writestruct(wd, DATA, "SpaceText", 1, sl);
}
else if(sl->spacetype==SPACE_SCRIPT) {
writestruct(wd, DATA, "SpaceScript", 1, sl);
}
2002-10-12 11:37:38 +00:00
else if(sl->spacetype==SPACE_ACTION) {
writestruct(wd, DATA, "SpaceAction", 1, sl);
}
else if(sl->spacetype==SPACE_SOUND) {
writestruct(wd, DATA, "SpaceSound", 1, sl);
}
else if(sl->spacetype==SPACE_NLA){
writestruct(wd, DATA, "SpaceNla", 1, sl);
}
Added the new Timeline Window, copied from Tuhopuu, coded by Matt Ebb. Main change is that it's an own Space type now, not part of the Audio window... the audio window should restrict to own options. This way functionality is nicely separated. Since it's the first time I added a new space (since long!) I've made an extensive tutorial as well. You can find that here: http://www.blender3d.org/cms/Adding_new_Space_Window.557.0.html Notes for using timewindow; - Add time markers with MKey - CTRL+M gives option to name Marker - Markers cannot be moved yet... - Pageup-Pagedown keys moves current frame to next-prev Marker - Xkey removes Markers - If an object has Ipos or an Action, it draws key lines - CTRL+Pageup-Pagedown moves current frame to next-prev Key - Press S or E to set start/end frame for playback Notes about the implementation in Tuhopuu: - Add new Marker now selects new, deselects others - Selecting Marker didn't work like elsewhere in Blender, on click it should deselect all, except the indicated Marker. Not when holding SHIFT of course - Not exported functions are static now - Removed unused defines (MARKER_NONE NEXT_AVAIL) - Drawing order was confusing, doing too many matrix calls - Removed not needed scrollbar, added new function to draw time values. (Has advantage the MMB scroll works not confusing on a scrollbar) - Added proper support for 'frame mapping' - The string button (name Marker) had a bug (checked str[64] while str was only 64 long) - String button itself didn't allow "OK on enter" - Made frame buttons in header larger, the arrows overlapped - Removed support for negative frame values, that won't work so simple!
2005-05-05 17:19:21 +00:00
else if(sl->spacetype==SPACE_TIME){
writestruct(wd, DATA, "SpaceTime", 1, sl);
}
else if(sl->spacetype==SPACE_NODE){
writestruct(wd, DATA, "SpaceNode", 1, sl);
}
2002-10-12 11:37:38 +00:00
sl= sl->next;
}
2002-10-12 11:37:38 +00:00
sa= sa->next;
}
2002-10-12 11:37:38 +00:00
sc= sc->id.next;
}
}
static void write_libraries(WriteData *wd, Main *main)
{
ListBase *lbarray[30];
ID *id;
int a, tot, foundone;
2002-10-12 11:37:38 +00:00
while(main) {
2002-10-12 11:37:38 +00:00
a=tot= set_listbasepointers(main, lbarray);
/* test: is lib being used */
2002-10-12 11:37:38 +00:00
foundone= 0;
while(tot--) {
id= lbarray[tot]->first;
while(id) {
if(id->us>0 && (id->flag & LIB_EXTERN)) {
foundone= 1;
break;
}
id= id->next;
}
if(foundone) break;
}
if(foundone) {
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_LI, "Library", 1, main->curlib);
2002-10-12 11:37:38 +00:00
while(a--) {
id= lbarray[a]->first;
while(id) {
if(G.rt==127 && GS(id->name)!=ID_GR) break;
2002-10-12 11:37:38 +00:00
if(id->us>0 && (id->flag & LIB_EXTERN)) {
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_ID, "ID", 1, id);
}
id= id->next;
}
}
}
2002-10-12 11:37:38 +00:00
main= main->next;
}
}
static void write_bone(WriteData *wd, Bone* bone)
{
Bone* cbone;
// PATCH for upward compatibility after 2.37+ armature recode
bone->size[0]= bone->size[1]= bone->size[2]= 1.0f;
// Write this bone
2002-10-12 11:37:38 +00:00
writestruct(wd, DATA, "Bone", 1, bone);
// Write Children
2002-10-12 11:37:38 +00:00
cbone= bone->childbase.first;
while(cbone) {
write_bone(wd, cbone);
cbone= cbone->next;
}
}
static void write_armatures(WriteData *wd, ListBase *idbase)
{
bArmature *arm;
Bone *bone;
2002-10-12 11:37:38 +00:00
arm=idbase->first;
while (arm) {
if (arm->id.us>0 || wd->current) {
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_AR, "bArmature", 1, arm);
2002-10-12 11:37:38 +00:00
/* Direct data */
bone= arm->bonebase.first;
while(bone) {
write_bone(wd, bone);
bone=bone->next;
}
}
arm=arm->id.next;
}
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);
2002-10-12 11:37:38 +00:00
}
static void write_actions(WriteData *wd, ListBase *idbase)
{
bAction *act;
bActionChannel *chan;
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
for(act=idbase->first; act; act= act->id.next) {
if (act->id.us>0 || wd->current) {
2002-10-12 11:37:38 +00:00
writestruct(wd, ID_AC, "bAction", 1, act);
2002-10-12 11:37:38 +00:00
for (chan=act->chanbase.first; chan; chan=chan->next) {
writestruct(wd, DATA, "bActionChannel", 1, chan);
write_constraint_channels(wd, &chan->constraintChannels);
}
}
}
}
static void write_texts(WriteData *wd, ListBase *idbase)
{
Text *text;
TextLine *tmp;
2002-10-12 11:37:38 +00:00
text= idbase->first;
while(text) {
if ( (text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) text->flags &= ~TXT_ISEXT;
2002-10-12 11:37:38 +00:00
/* write LibData */
writestruct(wd, ID_TXT, "Text", 1, text);
if(text->name) writedata(wd, DATA, strlen(text->name)+1, text->name);
if(!(text->flags & TXT_ISEXT)) {
2002-10-12 11:37:38 +00:00
/* now write the text data, in two steps for optimization in the readfunction */
tmp= text->lines.first;
while (tmp) {
writestruct(wd, DATA, "TextLine", 1, tmp);
tmp= tmp->next;
}
2002-10-12 11:37:38 +00:00
tmp= text->lines.first;
while (tmp) {
writedata(wd, DATA, tmp->len+1, tmp->line);
tmp= tmp->next;
}
}
text= text->id.next;
}
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);
2002-10-12 11:37:38 +00:00
}
static void write_sounds(WriteData *wd, ListBase *idbase)
{
bSound *sound;
bSample *sample;
2002-10-12 11:37:38 +00:00
PackedFile * pf;
2002-10-12 11:37:38 +00:00
// set all samples to unsaved status
2002-10-12 11:37:38 +00:00
sample = samples->first;
while (sample) {
sample->flags |= SAMPLE_NEEDS_SAVE;
sample = sample->id.next;
}
2002-10-12 11:37:38 +00:00
sound= idbase->first;
while(sound) {
if(sound->id.us>0 || wd->current) {
2002-10-12 11:37:38 +00:00
// do we need to save the packedfile as well ?
sample = sound->sample;
if (sample) {
if (sample->flags & SAMPLE_NEEDS_SAVE) {
sound->newpackedfile = sample->packedfile;
sample->flags &= ~SAMPLE_NEEDS_SAVE;
} else {
sound->newpackedfile = NULL;
}
}
2002-10-12 11:37:38 +00:00
/* write LibData */
writestruct(wd, ID_SO, "bSound", 1, sound);
2002-10-12 11:37:38 +00:00
if (sound->newpackedfile) {
pf = sound->newpackedfile;
writestruct(wd, DATA, "PackedFile", 1, pf);
writedata(wd, DATA, pf->size, pf->data);
}
2002-10-12 11:37:38 +00:00
if (sample) {
sound->newpackedfile = sample->packedfile;
}
}
sound= sound->id.next;
}
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);
2002-10-12 11:37:38 +00:00
}
static void write_groups(WriteData *wd, ListBase *idbase)
{
Group *group;
GroupObject *go;
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
for(group= idbase->first; group; group= group->id.next) {
if(group->id.us>0 || wd->current) {
2002-10-12 11:37:38 +00:00
/* write LibData */
writestruct(wd, ID_GR, "Group", 1, group);
2002-10-12 11:37:38 +00:00
go= group->gobject.first;
while(go) {
writestruct(wd, DATA, "GroupObject", 1, go);
go= go->next;
}
}
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
}
}
static void write_nodetrees(WriteData *wd, ListBase *idbase)
{
bNodeTree *ntree;
for(ntree=idbase->first; ntree; ntree= ntree->id.next) {
if (ntree->id.us>0 || wd->current) {
writestruct(wd, ID_NT, "bNodeTree", 1, ntree);
write_nodetree(wd, ntree);
}
2002-10-12 11:37:38 +00:00
}
}
static void write_global(WriteData *wd)
{
FileGlobal fg;
2002-10-12 11:37:38 +00:00
fg.curscreen= G.curscreen;
fg.curscene= G.scene;
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
fg.displaymode= G.displaymode;
fg.winpos= G.winpos;
fg.fileflags= (G.fileflags & ~G_FILE_NO_UI); // prevent to save this, is not good convention, and feature with concerns...
fg.globalf= G.f;
2002-10-12 11:37:38 +00:00
writestruct(wd, GLOB, "FileGlobal", 1, &fg);
}
/* if *mem there's filesave to memory */
static int write_file_handle(int handle, MemFile *compare, MemFile *current, int write_user_block, int write_flags)
2002-10-12 11:37:38 +00:00
{
BHead bhead;
2002-10-12 11:37:38 +00:00
ListBase mainlist;
char buf[13];
WriteData *wd;
/* int data; */ /*unused*/
2002-10-12 11:37:38 +00:00
mainlist.first= mainlist.last= G.main;
G.main->next= NULL;
2002-10-12 11:37:38 +00:00
blo_split_main(&mainlist);
wd= bgnwrite(handle, compare, current, write_flags);
2002-10-12 11:37:38 +00:00
sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (G.order==B_ENDIAN)?'V':'v', G.version);
mywrite(wd, buf, 12);
2002-10-12 11:37:38 +00:00
write_renderinfo(wd);
if(current==NULL)
write_screens (wd, &G.main->screen); // no UI save
2002-10-12 11:37:38 +00:00
write_scenes (wd, &G.main->scene);
write_curves (wd, &G.main->curve);
write_mballs (wd, &G.main->mball);
write_images (wd, &G.main->image);
write_cameras (wd, &G.main->camera);
write_lamps (wd, &G.main->lamp);
write_lattices (wd, &G.main->latt);
write_vfonts (wd, &G.main->vfont);
write_ipos (wd, &G.main->ipo);
write_keys (wd, &G.main->key);
write_worlds (wd, &G.main->world);
write_texts (wd, &G.main->text);
write_sounds (wd, &G.main->sound);
write_groups (wd, &G.main->group);
write_armatures(wd, &G.main->armature);
write_actions (wd, &G.main->action);
write_objects (wd, &G.main->object);
write_materials(wd, &G.main->mat);
write_textures (wd, &G.main->tex);
write_meshs (wd, &G.main->mesh);
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
write_nodetrees(wd, &G.main->nodetree);
2002-10-12 11:37:38 +00:00
write_libraries(wd, G.main->next);
write_global(wd);
if (write_user_block) {
write_userdef(wd);
}
/* dna as last, because (to be implemented) test for which structs are written */
2002-10-12 11:37:38 +00:00
writedata(wd, DNA1, wd->sdna->datalen, wd->sdna->data);
/* end of file */
memset(&bhead, 0, sizeof(BHead));
bhead.code= ENDB;
mywrite(wd, &bhead, sizeof(BHead));
2002-10-12 11:37:38 +00:00
blo_join_main(&mainlist);
G.main= mainlist.first;
2002-10-12 11:37:38 +00:00
return endwrite(wd);
}
/* return: success (1) */
2002-10-12 11:37:38 +00:00
int BLO_write_file(char *dir, int write_flags, char **error_r)
{
char userfilename[FILE_MAXDIR+FILE_MAXFILE];
char tempname[FILE_MAXDIR+FILE_MAXFILE];
int file, fout, write_user_block;
2002-10-12 11:37:38 +00:00
sprintf(tempname, "%s@", dir);
file = open(tempname,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
if(file == -1) {
*error_r= "Unable to open";
return 0;
}
2002-10-12 11:37:38 +00:00
BLI_make_file_string(G.sce, userfilename, BLI_gethome(), ".B.blend");
2002-10-12 11:37:38 +00:00
write_user_block= BLI_streq(dir, userfilename);
fout= write_file_handle(file, NULL,NULL, write_user_block, write_flags);
2002-10-12 11:37:38 +00:00
close(file);
2002-10-12 11:37:38 +00:00
if(!fout) {
if(write_flags & G_FILE_COMPRESS)
{
// compressed files have the same ending as regular files... only from 2.4!!!
int ret = BLI_gzip(tempname, dir);
if(-1==ret) {
*error_r= "Failed opening .gz file";
return 0;
}
if(-2==ret) {
*error_r= "Failed opening .blend file for compression";
return 0;
}
}
else
2002-10-12 11:37:38 +00:00
if(BLI_rename(tempname, dir) < 0) {
*error_r= "Can't change old file. File saved with @";
return 0;
}
2002-10-12 11:37:38 +00:00
} else {
remove(tempname);
*error_r= "Not enough diskspace";
return 0;
}
2002-10-12 11:37:38 +00:00
return 1;
}
/* return: success (1) */
int BLO_write_file_mem(MemFile *compare, MemFile *current, int write_flags, char **error_r)
{
int err;
err= write_file_handle(0, compare, current, 0, write_flags);
if(err==0) return 1;
return 0;
}
2002-10-12 11:37:38 +00:00
/* Runtime writing */
#ifdef WIN32
#define PATHSEPERATOR "\\"
#else
#define PATHSEPERATOR "/"
#endif
2002-10-12 11:37:38 +00:00
static char *get_install_dir(void) {
extern char bprogname[];
char *tmpname = BLI_strdup(bprogname);
char *cut;
#ifdef __APPLE__
cut = strstr(tmpname, ".app");
if (cut) cut[0] = 0;
#endif
cut = BLI_last_slash(tmpname);
2002-10-12 11:37:38 +00:00
if (cut) {
cut[0] = 0;
return tmpname;
} else {
MEM_freeN(tmpname);
return NULL;
}
}
static char *get_runtime_path(char *exename) {
char *installpath= get_install_dir();
2002-10-12 11:37:38 +00:00
if (!installpath) {
return NULL;
} else {
char *path= MEM_mallocN(strlen(installpath)+strlen(PATHSEPERATOR)+strlen(exename)+1, "runtimepath");
strcpy(path, installpath);
strcat(path, PATHSEPERATOR);
strcat(path, exename);
2002-10-12 11:37:38 +00:00
MEM_freeN(installpath);
2002-10-12 11:37:38 +00:00
return path;
}
}
#ifdef __APPLE__
static int recursive_copy_runtime(char *outname, char *exename, char **cause_r)
{
2002-10-12 11:37:38 +00:00
char *cause = NULL, *runtime = get_runtime_path(exename);
char command[2 * (FILE_MAXDIR+FILE_MAXFILE) + 32];
int progfd = -1;
2002-10-12 11:37:38 +00:00
if (!runtime) {
cause= "Unable to find runtime";
goto cleanup;
}
//printf("runtimepath %s\n", runtime);
2002-10-12 11:37:38 +00:00
progfd= open(runtime, O_BINARY|O_RDONLY, 0);
if (progfd==-1) {
cause= "Unable to find runtime";
goto cleanup;
}
sprintf(command, "/bin/cp -R \"%s\" \"%s\"", runtime, outname);
//printf("command %s\n", command);
2002-10-12 11:37:38 +00:00
if (system(command) == -1) {
cause = "Couldn't copy runtime";
}
cleanup:
if (progfd!=-1)
close(progfd);
if (runtime)
MEM_freeN(runtime);
2002-10-12 11:37:38 +00:00
if (cause) {
*cause_r= cause;
return 0;
} else
return 1;
}
void BLO_write_runtime(char *file, char *exename) {
char gamename[FILE_MAXDIR+FILE_MAXFILE];
int outfd = -1;
char *cause= NULL;
2002-10-12 11:37:38 +00:00
// remove existing file / bundle
//printf("Delete file %s\n", file);
2002-10-12 11:37:38 +00:00
BLI_delete(file, NULL, TRUE);
2002-10-12 11:37:38 +00:00
if (!recursive_copy_runtime(file, exename, &cause))
goto cleanup;
2002-10-12 11:37:38 +00:00
strcpy(gamename, file);
strcat(gamename, "/Contents/Resources/game.blend");
//printf("gamename %s\n", gamename);
2002-10-12 11:37:38 +00:00
outfd= open(gamename, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0777);
if (outfd != -1) {
write_file_handle(outfd, NULL,NULL, 0, G.fileflags);
2002-10-12 11:37:38 +00:00
if (write(outfd, " ", 1) != 1) {
cause= "Unable to write to output file";
goto cleanup;
}
} else {
cause = "Unable to open blenderfile";
}
2002-10-12 11:37:38 +00:00
cleanup:
if (outfd!=-1)
close(outfd);
2002-10-12 11:37:38 +00:00
if (cause)
error("Unable to make runtime: %s", cause);
}
#else /* !__APPLE__ */
2002-10-12 11:37:38 +00:00
static int handle_append_runtime(int handle, char *exename, char **cause_r) {
char *cause= NULL, *runtime= get_runtime_path(exename);
unsigned char buf[1024];
int count, progfd= -1;
2002-10-12 11:37:38 +00:00
if (!runtime) {
cause= "Unable to find runtime";
goto cleanup;
}
2002-10-12 11:37:38 +00:00
progfd= open(runtime, O_BINARY|O_RDONLY, 0);
if (progfd==-1) {
cause= "Unable to find runtime";
goto cleanup;
}
while ((count= read(progfd, buf, sizeof(buf)))>0) {
if (write(handle, buf, count)!=count) {
cause= "Unable to write to output file";
goto cleanup;
}
}
2002-10-12 11:37:38 +00:00
cleanup:
if (progfd!=-1)
close(progfd);
if (runtime)
MEM_freeN(runtime);
2002-10-12 11:37:38 +00:00
if (cause) {
*cause_r= cause;
return 0;
} else
return 1;
}
static int handle_write_msb_int(int handle, int i) {
unsigned char buf[4];
buf[0]= (i>>24)&0xFF;
buf[1]= (i>>16)&0xFF;
buf[2]= (i>>8)&0xFF;
buf[3]= (i>>0)&0xFF;
2002-10-12 11:37:38 +00:00
return (write(handle, buf, 4)==4);
}
void BLO_write_runtime(char *file, char *exename) {
int outfd= open(file, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0777);
char *cause= NULL;
int datastart;
2002-10-12 11:37:38 +00:00
if (!outfd) {
cause= "Unable to open output file";
goto cleanup;
}
if (!handle_append_runtime(outfd, exename, &cause))
goto cleanup;
2002-10-12 11:37:38 +00:00
datastart= lseek(outfd, 0, SEEK_CUR);
write_file_handle(outfd, NULL,NULL, 0, G.fileflags);
2002-10-12 11:37:38 +00:00
if (!handle_write_msb_int(outfd, datastart) || (write(outfd, "BRUNTIME", 8)!=8)) {
cause= "Unable to write to output file";
goto cleanup;
}
2002-10-12 11:37:38 +00:00
cleanup:
if (outfd!=-1)
close(outfd);
2002-10-12 11:37:38 +00:00
if (cause)
error("Unable to make runtime: %s", cause);
}
#endif /* !__APPLE__ */