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!
This commit is contained in:
2006-01-02 13:06:05 +00:00
parent 9710d4c84c
commit ea7538dca6
27 changed files with 3311 additions and 2093 deletions

View File

@@ -41,13 +41,13 @@ struct ID;
struct Main;
struct Library;
void *alloc_libblock(struct ListBase *lb, short type, char *name);
void *alloc_libblock(struct ListBase *lb, short type, const char *name);
void *copy_libblock(void *rt);
void id_lib_extern(struct ID *id);
void id_us_plus(struct ID *id);
int new_id(struct ListBase *lb, struct ID *id, char *name);
int new_id(struct ListBase *lb, struct ID *id, const char *name);
struct ListBase *wich_libbase(struct Main *mainlib, short type);
int set_listbasepointers(struct Main *main, struct ListBase **lb);

View File

@@ -72,8 +72,9 @@ typedef struct Main {
ListBase text;
ListBase sound;
ListBase group;
ListBase armature; /* NLA */
ListBase action; /* NLA */
ListBase armature;
ListBase action;
ListBase nodetree;
} Main;

View File

@@ -56,11 +56,13 @@ ID *material_from(struct Object *ob, int act);
void assign_material(struct Object *ob, struct Material *ma, int act);
void new_material_to_objectdata(struct Object *ob);
struct Material *get_active_matlayer(struct Material *ma);
void init_render_material(struct Material *ma);
struct Material *get_active_matlayer(struct Material *);
void init_render_material(struct Material *);
void init_render_materials(void);
void end_render_material(struct Material *);
void end_render_materials(void);
void automatname(struct Material *ma);
void automatname(struct Material *);
void delete_material_index(void);
#ifdef __cplusplus

View File

@@ -54,7 +54,9 @@ typedef struct bNodeSocketType {
float min, max; /* default range for inputs */
/* after this line is used internal only */
struct bNodeSocket *sock; /* to verify */
struct bNodeSocket *sock; /* used during verify_types */
struct bNodeSocket *internsock; /* group nodes, the internal socket counterpart */
int own_index; /* verify group nodes */
} bNodeSocketType;
@@ -71,7 +73,7 @@ typedef struct bNodeType {
void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **);
/* after this line is set on startup of blender */
int (*butfunc)(struct uiBlock *, struct bNodeTree *, struct bNode *, rctf *);
int (*butfunc)(struct uiBlock *, struct bNodeTree *, struct bNode *, struct rctf *);
} bNodeType;
@@ -80,26 +82,34 @@ typedef struct bNodeType {
#define NODE_CLASS_OUTPUT 1
#define NODE_CLASS_GENERATOR 2
#define NODE_CLASS_OPERATOR 3
#define NODE_CLASS_GROUP 4
/* ************** GENERIC API, TREES *************** */
void ntreeVerifyTypes(struct bNodeTree *ntree);
struct bNodeTree *ntreeAddTree(int type);
void ntreeInitTypes(struct bNodeTree *ntree);
void ntreeMakeOwnType(struct bNodeTree *ntree);
void ntreeFreeTree(struct bNodeTree *ntree);
struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree, int internal_select);
void ntreeSolveOrder(struct bNodeTree *ntree);
void ntreeBeginExecTree(struct bNodeTree *ntree, int xsize, int ysize);
void ntreeBeginExecTree(struct bNodeTree *ntree);
void ntreeExecTree(struct bNodeTree *ntree);
void ntreeEndExecTree(struct bNodeTree *ntree);
void ntreeInitPreview(struct bNodeTree *, int xsize, int ysize);
void ntreeClearPixelTree(struct bNodeTree *, int, int);
/* ************** GENERIC API, NODES *************** */
void nodeVerifyType(struct bNodeTree *ntree, struct bNode *node);
void nodeAddToPreview(struct bNode *, float *, int, int);
struct bNode *nodeAddNodeType(struct bNodeTree *ntree, int type);
struct bNode *nodeAddNodeType(struct bNodeTree *ntree, int type, struct bNodeTree *ngroup);
void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
@@ -114,6 +124,21 @@ struct bNode *nodeGetActive(struct bNodeTree *ntree);
struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype);
void nodeClearActiveID(struct bNodeTree *ntree, short idtype);
/* ************** Groups ****************** */
struct bNode *nodeMakeGroupFromSelected(struct bNodeTree *ntree);
int nodeGroupUnGroup(struct bNodeTree *ntree, struct bNode *gnode);
void nodeVerifyGroup(struct bNodeTree *ngroup);
void nodeGroupSocketUseFlags(struct bNodeTree *ngroup);
/* ************** COMMON NODES *************** */
#define NODE_GROUP 2
extern bNodeType node_group_typeinfo;
/* ************** SHADER NODES *************** */
struct ShadeInput;

View File

@@ -74,6 +74,7 @@
#include "DNA_armature_types.h"
#include "DNA_action_types.h"
#include "DNA_userdef_types.h"
#include "DNA_node_types.h"
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
@@ -103,6 +104,8 @@
#include "BKE_lattice.h"
#include "BKE_armature.h"
#include "BKE_action.h"
#include "BKE_node.h"
#include "BPI_script.h"
#define MAX_IDPUP 60 /* was 24 */
@@ -185,6 +188,8 @@ ListBase *wich_libbase(Main *mainlib, short type)
return &(mainlib->armature);
case ID_AC:
return &(mainlib->action);
case ID_NT:
return &(mainlib->nodetree);
}
return 0;
}
@@ -224,12 +229,13 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[20]= &(main->text);
lb[21]= &(main->sound);
lb[22]= &(main->group);
lb[23]= &(main->nodetree);
lb[23]= samples;
lb[24]= &(main->script);
lb[25]= NULL;
lb[24]= samples;
lb[25]= &(main->script);
lb[26]= NULL;
return 25;
return 26;
}
/* *********** ALLOC AND FREE *****************
@@ -244,7 +250,7 @@ void *alloc_libblock(ListBase *lb, type, name)
static ID *alloc_libblock_notest(short type)
{
ID *id= 0;
ID *id= NULL;
switch( type ) {
case ID_SCE:
@@ -322,14 +328,17 @@ static ID *alloc_libblock_notest(short type)
case ID_AC:
id = MEM_callocN(sizeof(bAction), "action");
break;
case ID_NT:
id = MEM_callocN(sizeof(bNodeTree), "action");
break;
}
return id;
}
// used everywhere in blenkernel and text.c
void *alloc_libblock(ListBase *lb, short type, char *name)
void *alloc_libblock(ListBase *lb, short type, const char *name)
{
ID *id= 0;
ID *id= NULL;
id= alloc_libblock_notest(type);
if(id) {
@@ -343,19 +352,13 @@ void *alloc_libblock(ListBase *lb, short type, char *name)
return id;
}
/* GS reads the memory pointed at in a specific ordering. There are,
* however two definitions for it. I have jotted them down here, both,
* but I think the first one is actually used. The thing is that
* big-endian systems might read this the wrong way round. OTOH, we
* constructed the IDs that are read out with this macro explicitly as
* well. I expect we'll sort it out soon... */
/* GS reads the memory pointed at in a specific ordering.
only use this definition, makes little and big endian systems
work fine, in conjunction with MAKE_ID */
/* from blendef: */
#define GS(a) (*((short *)(a)))
/* from misc_util: flip the bytes from x */
/*#define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
// used everywhere in blenkernel and text.c
void *copy_libblock(void *rt)
{
@@ -468,6 +471,9 @@ void free_libblock(ListBase *lb, void *idv)
case ID_AC:
free_action((bAction *)id);
break;
case ID_NT:
ntreeFreeTree((bNodeTree *)id);
break;
}
BLI_remlink(lb, id);
@@ -742,7 +748,7 @@ static void sort_alpha_id(ListBase *lb, ID *id)
}
int new_id(ListBase *lb, ID *id, char *tname)
int new_id(ListBase *lb, ID *id, const char *tname)
/* only for local blocks: external en indirect blocks already have a unique ID */
/* return 1: created a new name */
{

View File

@@ -87,9 +87,11 @@ void free_material(Material *ma)
BLI_freelistN(&ma->layers);
if(ma->nodetree)
/* is no lib link block, but material extension */
if(ma->nodetree) {
ntreeFreeTree(ma->nodetree);
MEM_freeN(ma->nodetree);
}
}
void init_material(Material *ma)
@@ -600,7 +602,7 @@ Material *get_active_matlayer(Material *ma)
return ma;
}
void init_render_material(Material *ma)
static void do_init_render_material(Material *ma)
{
MTex *mtex;
int a, needuv=0;
@@ -655,24 +657,50 @@ void init_render_material(Material *ma)
ma->mode_l= ma->mode;
}
void init_render_material(Material *mat)
{
do_init_render_material(mat);
if(mat->nodetree && mat->use_nodes) {
bNode *node;
for(node=mat->nodetree->nodes.first; node; node= node->next) {
if(node->id && GS(node->id->name)==ID_MA) {
Material *ma= (Material *)node->id;
if(ma!=mat) {
do_init_render_material(ma);
mat->texco |= ma->texco;
mat->mode_l |= ma->mode_l;
}
}
}
ntreeBeginExecTree(mat->nodetree); /* has internal flag to detect it only does it once */
}
}
void init_render_materials()
{
Material *ma;
MaterialLayer *ml;
/* two steps, first initialize, then or the flags for layers */
for(ma= G.main->mat.first; ma; ma= ma->id.next) {
if(ma->id.us) init_render_material(ma);
}
for(ma= G.main->mat.first; ma; ma= ma->id.next)
if(ma->id.us)
init_render_material(ma);
}
for(ma= G.main->mat.first; ma; ma= ma->id.next) {
for(ml= ma->layers.first; ml; ml= ml->next) {
if(ml->mat) {
ma->texco |= ml->mat->texco;
ma->mode_l |= ml->mat->mode;
}
}
}
/* only needed for nodes now */
void end_render_material(Material *mat)
{
if(mat && mat->nodetree && mat->use_nodes)
ntreeEndExecTree(mat->nodetree); /* has internal flag to detect it only does it once */
}
void end_render_materials(void)
{
Material *ma;
for(ma= G.main->mat.first; ma; ma= ma->id.next)
if(ma->id.us)
end_render_material(ma);
}
/* ****************** */

View File

@@ -32,8 +32,12 @@
#include "DNA_ID.h"
#include "DNA_node_types.h"
#include "DNA_material_types.h"
#include "BKE_blender.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
@@ -43,16 +47,27 @@
#include "MEM_guardedalloc.h"
/* ************** Type stuff ********** */
/* not very important, but the stack solver likes to know a maximum */
#define MAX_SOCKET 64
static bNodeType *nodeGetType(bNodeTree *ntree, int type)
#pragma mark /* ************** Type stuff ********** */
static bNodeType *node_get_type(bNodeTree *ntree, int type, bNodeTree *ngroup)
{
if(type==NODE_GROUP) {
if(ngroup && GS(ngroup->id.name)==ID_NT) {
return ngroup->owntype;
}
return NULL;
}
else {
bNodeType **typedefs= ntree->alltypes;
while( *typedefs && (*typedefs)->type!=type)
typedefs++;
return *typedefs;
}
}
void ntreeInitTypes(bNodeTree *ntree)
@@ -68,7 +83,7 @@ void ntreeInitTypes(bNodeTree *ntree)
for(node= ntree->nodes.first; node; node= next) {
next= node->next;
node->typeinfo= nodeGetType(ntree, node->type);
node->typeinfo= node_get_type(ntree, node->type, (bNodeTree *)node->id);
if(node->typeinfo==NULL) {
printf("Error: Node type %s doesn't exist anymore, removed\n", node->name);
nodeFreeNode(ntree, node);
@@ -88,6 +103,9 @@ static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype)
else sock->limit= stype->limit;
sock->type= stype->type;
sock->to_index= stype->own_index;
sock->tosock= stype->internsock;
sock->ns.vec[0]= stype->val1;
sock->ns.vec[1]= stype->val2;
sock->ns.vec[2]= stype->val3;
@@ -119,6 +137,8 @@ static bNodeSocket *verify_socket(ListBase *lb, bNodeSocketType *stype)
bNodeSocket *sock;
for(sock= lb->first; sock; sock= sock->next) {
/* both indices are zero for non-groups, otherwise it's a unique index */
if(sock->to_index==stype->own_index)
if(strncmp(sock->name, stype->name, NODE_MAXSTR)==0)
break;
}
@@ -126,7 +146,10 @@ static bNodeSocket *verify_socket(ListBase *lb, bNodeSocketType *stype)
sock->type= stype->type; /* in future, read this from tydefs! */
if(stype->limit==0) sock->limit= 0xFFF;
else sock->limit= stype->limit;
sock->tosock= stype->internsock;
BLI_remlink(lb, sock);
return sock;
}
else {
@@ -162,37 +185,482 @@ static void verify_socket_list(bNodeTree *ntree, ListBase *lb, bNodeSocketType *
}
}
void ntreeVerifyTypes(bNodeTree *ntree)
void nodeVerifyType(bNodeTree *ntree, bNode *node)
{
bNode *node;
bNodeType *ntype;
bNodeType *ntype= node->typeinfo;
if((ntree->init & NTREE_TYPE_INIT)==0)
ntreeInitTypes(ntree);
/* check inputs and outputs, and remove or insert them */
for(node= ntree->nodes.first; node; node= node->next) {
ntype= node->typeinfo;
if(ntype) {
/* might add some other verify stuff here */
verify_socket_list(ntree, &node->inputs, ntype->inputs);
verify_socket_list(ntree, &node->outputs, ntype->outputs);
}
}
void ntreeVerifyTypes(bNodeTree *ntree)
{
bNode *node;
if((ntree->init & NTREE_TYPE_INIT)==0)
ntreeInitTypes(ntree);
/* check inputs and outputs, and remove or insert them */
for(node= ntree->nodes.first; node; node= node->next)
nodeVerifyType(ntree, node);
}
#pragma mark /* ************** Group stuff ********** */
/* prototype */
static void node_group_exec_func(void *data, bNode *node, bNodeStack **in, bNodeStack **out);
bNodeType node_group_typeinfo= {
/* type code */ NODE_GROUP,
/* name */ "Group",
/* width+range */ 120, 60, 200,
/* class+opts */ NODE_CLASS_GROUP, NODE_OPTIONS,
/* input sock */ NULL,
/* output sock */ NULL,
/* storage */ "",
/* execfunc */ node_group_exec_func,
};
/* tag internal sockets */
static void group_tag_internal_sockets(bNodeTree *ngroup)
{
bNode *node;
bNodeSocket *sock;
bNodeLink *link;
/* clear intern tag, but check already for hidden sockets */
for(node= ngroup->nodes.first; node; node= node->next) {
for(sock= node->inputs.first; sock; sock= sock->next)
sock->intern= sock->flag & SOCK_HIDDEN;
for(sock= node->outputs.first; sock; sock= sock->next)
sock->intern= sock->flag & SOCK_HIDDEN;
}
/* set tag */
for(link= ngroup->links.first; link; link= link->next) {
link->fromsock->intern= 1;
link->tosock->intern= 1;
}
/* remove link pointer to external links (only happens on create group) */
for(node= ngroup->nodes.first; node; node= node->next) {
for(sock= node->inputs.first; sock; sock= sock->next)
if(sock->intern==0)
sock->link= NULL;
}
/* set all intern sockets to own_index zero, makes sure that later use won't mixup */
for(node= ngroup->nodes.first; node; node= node->next) {
for(sock= node->inputs.first; sock; sock= sock->next)
if(sock->intern)
sock->own_index= 0;
for(sock= node->outputs.first; sock; sock= sock->next)
if(sock->intern)
sock->own_index= 0;
}
}
/* ************** Add stuff ********** */
/* not very important, but the stack solver likes to know a maximum */
#define MAX_SOCKET 64
bNode *nodeAddNodeType(bNodeTree *ntree, int type)
/* after editing group, new sockets are zero */
/* this routine ensures unique identifiers for zero sockets that are exposed */
static void group_verify_own_indices(bNodeTree *ngroup)
{
bNode *node;
bNodeType *ntype= nodeGetType(ntree, type);
bNodeSocket *sock;
for(node= ngroup->nodes.first; node; node= node->next) {
for(sock= node->inputs.first; sock; sock= sock->next)
if(sock->own_index==0 && sock->intern==0)
sock->own_index= ++(ngroup->cur_index);
for(sock= node->outputs.first; sock; sock= sock->next)
if(sock->own_index==0 && sock->intern==0)
sock->own_index= ++(ngroup->cur_index);
}
printf("internal index %d\n", ngroup->cur_index);
}
/* nodetrees can be used as groups, so we need typeinfo structs generated */
void ntreeMakeOwnType(bNodeTree *ngroup)
{
bNode *node;
bNodeSocket *sock;
int totin= 0, totout=0, a;
/* tags socket when internal linked */
group_tag_internal_sockets(ngroup);
/* ensure all sockets have own unique id */
group_verify_own_indices(ngroup);
/* counting stats */
for(node= ngroup->nodes.first; node; node= node->next) {
if(node->type==NODE_GROUP)
break;
for(sock= node->inputs.first; sock; sock= sock->next)
if(sock->intern==0)
totin++;
for(sock= node->outputs.first; sock; sock= sock->next)
if(sock->intern==0)
totout++;
}
/* debug: nodetrees in nodetrees not handled yet */
if(node) {
printf("group in group, not supported yet\n");
return;
}
/* free own type struct */
if(ngroup->owntype) {
if(ngroup->owntype->inputs)
MEM_freeN(ngroup->owntype->inputs);
if(ngroup->owntype->outputs)
MEM_freeN(ngroup->owntype->outputs);
MEM_freeN(ngroup->owntype);
}
/* make own type struct */
ngroup->owntype= MEM_mallocN(sizeof(bNodeType), "group type");
*ngroup->owntype= node_group_typeinfo;
/* input type arrays */
if(totin) {
bNodeSocketType *stype;
bNodeSocketType *inputs= MEM_mallocN(sizeof(bNodeSocketType)*(totin+1), "bNodeSocketType");
a= 0;
for(node= ngroup->nodes.first; node; node= node->next) {
/* nodes are presumed fully verified, stype and socket list are in sync */
stype= node->typeinfo->inputs;
for(sock= node->inputs.first; sock; sock= sock->next, stype++) {
if(sock->intern==0) {
/* debug only print */
if(stype==NULL || stype->type==-1) printf("group verification error %s\n", ngroup->id.name);
inputs[a]= *stype;
inputs[a].own_index= sock->own_index;
inputs[a].internsock= sock;
a++;
}
}
}
inputs[a].type= -1; /* terminator code */
ngroup->owntype->inputs= inputs;
}
/* output type arrays */
if(totout) {
bNodeSocketType *stype;
bNodeSocketType *outputs= MEM_mallocN(sizeof(bNodeSocketType)*(totout+1), "bNodeSocketType");
a= 0;
for(node= ngroup->nodes.first; node; node= node->next) {
/* nodes are presumed fully verified, stype and socket list are in sync */
stype= node->typeinfo->outputs;
for(sock= node->outputs.first; sock; sock= sock->next, stype++) {
if(sock->intern==0) {
/* debug only print */
if(stype==NULL || stype->type==-1) printf("group verification error %s\n", ngroup->id.name);
outputs[a]= *stype;
outputs[a].own_index= sock->own_index;
outputs[a].internsock= sock;
a++;
}
}
}
outputs[a].type= -1; /* terminator code */
ngroup->owntype->outputs= outputs;
}
/* voila, the nodetree has the full definition for generating group-node instances! */
}
static bNodeSocket *groupnode_find_tosock(bNode *gnode, int index)
{
bNodeSocket *sock;
for(sock= gnode->inputs.first; sock; sock= sock->next)
if(sock->to_index==index)
return sock;
return NULL;
}
static bNodeSocket *groupnode_find_fromsock(bNode *gnode, int index)
{
bNodeSocket *sock;
for(sock= gnode->outputs.first; sock; sock= sock->next)
if(sock->to_index==index)
return sock;
return NULL;
}
bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
{
bNodeLink *link, *linkn;
bNode *node, *gnode, *nextn;
bNodeTree *ngroup;
float min[2], max[2];
int totnode=0;
INIT_MINMAX2(min, max);
/* is there something to group? also do some clearing */
for(node= ntree->nodes.first; node; node= node->next) {
if(node->flag & NODE_SELECT) {
/* no groups in groups */
if(node->type==NODE_GROUP)
return NULL;
DO_MINMAX2( (&node->locx), min, max);
totnode++;
}
node->done= 0;
}
if(totnode==0) return NULL;
/* check if all connections are OK, no unselected node has both
inputs and outputs to a selection */
for(link= ntree->links.first; link; link= link->next) {
if(link->fromnode->flag & NODE_SELECT)
link->tonode->done |= 1;
if(link->tonode->flag & NODE_SELECT)
link->fromnode->done |= 2;
}
for(node= ntree->nodes.first; node; node= node->next) {
if((node->flag & NODE_SELECT)==0)
if(node->done==3)
break;
}
if(node)
return NULL;
/* OK! new nodetree */
ngroup= alloc_libblock(&G.main->nodetree, ID_NT, "NodeGroup");
ngroup->type= ntree->type;
ngroup->alltypes= ntree->alltypes;
/* move nodes over */
for(node= ntree->nodes.first; node; node= nextn) {
nextn= node->next;
if(node->flag & NODE_SELECT) {
BLI_remlink(&ntree->nodes, node);
BLI_addtail(&ngroup->nodes, node);
node->locx-= 0.5f*(min[0]+max[0]);
node->locy-= 0.5f*(min[1]+max[1]);
}
}
/* move links over */
for(link= ntree->links.first; link; link= linkn) {
linkn= link->next;
if(link->fromnode->flag & link->tonode->flag & NODE_SELECT) {
BLI_remlink(&ntree->links, link);
BLI_addtail(&ngroup->links, link);
}
}
/* now we can make own group typeinfo */
ntreeMakeOwnType(ngroup);
/* make group node */
gnode= nodeAddNodeType(ntree, NODE_GROUP, ngroup);
gnode->locx= 0.5f*(min[0]+max[0]);
gnode->locy= 0.5f*(min[1]+max[1]);
/* relink external sockets */
for(link= ntree->links.first; link; link= link->next) {
if(link->tonode->flag & NODE_SELECT) {
link->tonode= gnode;
link->tosock= groupnode_find_tosock(gnode, link->tosock->own_index);
if(link->tosock==NULL) printf("Bad!\n");
}
else if(link->fromnode->flag & NODE_SELECT) {
link->fromnode= gnode;
link->fromsock= groupnode_find_fromsock(gnode, link->fromsock->own_index);
if(link->fromsock==NULL) printf("Bad!\n");
}
}
return gnode;
}
/* note: ungroup: group_indices zero! */
/* here's a nasty little one, need to check users... */
/* should become callbackable... */
void nodeVerifyGroup(bNodeTree *ngroup)
{
Material *ma;
/* group changed, so we rebuild the type definition */
ntreeMakeOwnType(ngroup);
if(ngroup->type==NTREE_SHADER) {
for(ma= G.main->mat.first; ma; ma= ma->id.next) {
if(ma->nodetree) {
bNode *node;
/* find if group is in tree */
for(node= ma->nodetree->nodes.first; node; node= node->next)
if(node->id == (ID *)ngroup)
break;
if(node) {
/* set all type pointers OK */
ntreeInitTypes(ma->nodetree);
for(node= ma->nodetree->nodes.first; node; node= node->next)
if(node->id == (ID *)ngroup)
nodeVerifyType(ma->nodetree, node);
}
}
}
}
}
/* also to check all users... */
/* should become callbackable... */
void nodeGroupSocketUseFlags(bNodeTree *ngroup)
{
bNode *node;
bNodeSocket *sock;
Material *ma;
/* clear flags */
for(node= ngroup->nodes.first; node; node= node->next) {
for(sock= node->inputs.first; sock; sock= sock->next)
sock->flag &= ~SOCK_IN_USE;
for(sock= node->outputs.first; sock; sock= sock->next)
sock->flag &= ~SOCK_IN_USE;
}
/* tag all thats in use */
if(ngroup->type==NTREE_SHADER) {
for(ma= G.main->mat.first; ma; ma= ma->id.next) {
if(ma->nodetree) {
for(node= ma->nodetree->nodes.first; node; node= node->next) {
if(node->id==(ID *)ngroup) {
for(sock= node->inputs.first; sock; sock= sock->next)
if(sock->link)
if(sock->tosock)
sock->tosock->flag |= SOCK_IN_USE;
for(sock= node->outputs.first; sock; sock= sock->next)
if(nodeCountSocketLinks(ma->nodetree, sock))
if(sock->tosock)
sock->tosock->flag |= SOCK_IN_USE;
}
}
}
}
}
}
static void find_node_with_socket(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex)
{
bNode *node;
bNodeSocket *tsock;
int index;
for(node= ntree->nodes.first; node; node= node->next) {
for(index=0, tsock= node->inputs.first; tsock; tsock= tsock->next, index++)
if(tsock==sock)
break;
if(tsock)
break;
for(index=0, tsock= node->outputs.first; tsock; tsock= tsock->next, index++)
if(tsock==sock)
break;
if(tsock)
break;
}
if(node) {
*nodep= node;
*sockindex= index;
}
else {
*nodep= NULL;
}
}
/* returns 1 if its OK */
int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode)
{
bNodeLink *link, *linkn;
bNode *node, *nextn;
bNodeTree *ngroup, *wgroup;
int index;
ngroup= (bNodeTree *)gnode->id;
if(ngroup==NULL) return 0;
/* clear new pointers, set in copytree */
for(node= ntree->nodes.first; node; node= node->next)
node->new= NULL;
wgroup= ntreeCopyTree(ngroup, 0);
/* add the nodes into the ntree */
for(node= wgroup->nodes.first; node; node= nextn) {
nextn= node->next;
BLI_remlink(&wgroup->nodes, node);
BLI_addtail(&ntree->nodes, node);
node->locx+= gnode->locx;
node->locy+= gnode->locy;
node->flag |= NODE_SELECT;
}
/* and the internal links */
for(link= wgroup->links.first; link; link= linkn) {
linkn= link->next;
BLI_remlink(&wgroup->links, link);
BLI_addtail(&ntree->links, link);
}
/* restore links to and from the gnode */
for(link= ntree->links.first; link; link= link->next) {
if(link->tonode==gnode) {
/* link->tosock->tosock is on the node we look for */
find_node_with_socket(ngroup, link->tosock->tosock, &nextn, &index);
if(nextn==NULL) printf("wrong stuff!\n");
else if(nextn->new==NULL) printf("wrong stuff too!\n");
else {
link->tonode= nextn->new;
link->tosock= BLI_findlink(&link->tonode->inputs, index);
}
}
else if(link->fromnode==gnode) {
/* link->fromsock->tosock is on the node we look for */
find_node_with_socket(ngroup, link->fromsock->tosock, &nextn, &index);
if(nextn==NULL) printf("1 wrong stuff!\n");
else if(nextn->new==NULL) printf("1 wrong stuff too!\n");
else {
link->fromnode= nextn->new;
link->fromsock= BLI_findlink(&link->fromnode->outputs, index);
}
}
}
/* remove the gnode & work tree */
ntreeFreeTree(wgroup);
MEM_freeN(wgroup);
nodeFreeNode(ntree, gnode);
return 1;
}
#pragma mark /* ************** Add stuff ********** */
bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup)
{
bNode *node;
bNodeType *ntype= node_get_type(ntree, type, ngroup);
bNodeSocketType *stype;
node= MEM_callocN(sizeof(bNode), "new node");
@@ -205,6 +673,9 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type)
node->width= ntype->width;
node->miniwidth= 15.0f; /* small value only, allows print of first chars */
if(type==NODE_GROUP)
node->id= (ID *)ngroup;
if(ntype->inputs) {
stype= ntype->inputs;
while(stype->type != -1) {
@@ -236,12 +707,19 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type)
bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
{
bNode *nnode= MEM_callocN(sizeof(bNode), "dupli node");
bNodeSocket *sock;
*nnode= *node;
BLI_addtail(&ntree->nodes, nnode);
duplicatelist(&nnode->inputs, &node->inputs);
for(sock= nnode->inputs.first; sock; sock= sock->next)
sock->own_index= 0;
duplicatelist(&nnode->outputs, &node->outputs);
for(sock= nnode->outputs.first; sock; sock= sock->next)
sock->own_index= 0;
if(nnode->id)
nnode->id->us++;
@@ -286,7 +764,7 @@ bNodeTree *ntreeAddTree(int type)
return ntree;
}
/* ************** Free stuff ********** */
#pragma mark /* ************** Free stuff ********** */
/* goes over entire tree */
static void node_unlink_node(bNodeTree *ntree, bNode *node)
@@ -340,6 +818,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
MEM_freeN(node);
}
/* do not free ntree itself here, free_libblock calls this function too */
void ntreeFreeTree(bNodeTree *ntree)
{
bNode *node, *next;
@@ -350,7 +829,13 @@ void ntreeFreeTree(bNodeTree *ntree)
}
BLI_freelistN(&ntree->links);
MEM_freeN(ntree);
if(ntree->owntype) {
if(ntree->owntype->inputs)
MEM_freeN(ntree->owntype->inputs);
if(ntree->owntype->outputs)
MEM_freeN(ntree->owntype->outputs);
MEM_freeN(ntree->owntype);
}
}
bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select)
@@ -404,10 +889,21 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select)
nlink->tosock= BLI_findlink(&link->tonode->new->inputs, a);
}
}
/* own type definition for group usage */
if(internal_select==0) {
if(ntree->owntype) {
newtree->owntype= MEM_dupallocN(ntree->owntype);
if(ntree->owntype->inputs)
newtree->owntype->inputs= MEM_dupallocN(ntree->owntype->inputs);
if(ntree->owntype->outputs)
newtree->owntype->outputs= MEM_dupallocN(ntree->owntype->outputs);
}
}
return newtree;
}
/* ************ find stuff *************** */
#pragma mark /* ************ find stuff *************** */
bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to)
{
@@ -492,7 +988,7 @@ void nodeSetActive(bNodeTree *ntree, bNode *node)
node->flag |= NODE_ACTIVE_ID;
}
/* ************** dependency stuff *********** */
#pragma mark /* ************** dependency stuff *********** */
/* node is guaranteed to be not checked before */
static int node_recurs_check(bNode *node, bNode ***nsort, int level)
@@ -592,7 +1088,7 @@ void ntreeSolveOrder(bNodeTree *ntree)
}
/* *************** preview *********** */
#pragma mark /* *************** preview *********** */
/* if node->preview, then we assume the rect to exist */
@@ -612,6 +1108,7 @@ static void nodeInitPreview(bNode *node, int xsize, int ysize)
if(node->preview==NULL) {
node->preview= MEM_callocN(sizeof(bNodePreview), "node preview");
printf("added preview %s\n", node->name);
}
if(node->preview->rect==NULL) {
node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect");
@@ -620,6 +1117,16 @@ static void nodeInitPreview(bNode *node, int xsize, int ysize)
}
}
void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize)
{
bNode *node;
for(node= ntree->nodes.first; node; node= node->next) {
if(node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */
nodeInitPreview(node, xsize, ysize);
}
}
void nodeAddToPreview(bNode *node, float *col, int x, int y)
{
bNodePreview *preview= node->preview;
@@ -637,27 +1144,95 @@ void nodeAddToPreview(bNode *node, float *col, int x, int y)
/* ******************* executing ************* */
#pragma mark /* ******************* executing ************* */
/* see notes at ntreeBeginExecTree */
static void group_node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out, bNodeStack **gin, bNodeStack **gout)
{
bNodeSocket *sock;
void ntreeBeginExecTree(bNodeTree *ntree, int xsize, int ysize)
/* build pointer stack */
for(sock= node->inputs.first; sock; sock= sock->next) {
if(sock->intern) {
/* yep, intern can have link or is hidden socket */
if(sock->link)
*(in++)= stack + sock->link->fromsock->stack_index;
else
*(in++)= &sock->ns;
}
else
*(in++)= gin[sock->stack_index_ext];
}
for(sock= node->outputs.first; sock; sock= sock->next) {
if(sock->intern)
*(out++)= stack + sock->stack_index;
else
*(out++)= gout[sock->stack_index_ext];
}
}
static void node_group_exec_func(void *data, bNode *gnode, bNodeStack **in, bNodeStack **out)
{
bNode *node;
bNodeTree *ntree= (bNodeTree *)gnode->id;
bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
if(ntree==NULL) return;
if(ntree->init & NTREE_EXEC_INIT) {
for(node= ntree->nodes.first; node; node= node->next) {
if(node->typeinfo->execfunc) {
group_node_get_stack(node, ntree->stack, nsin, nsout, in, out);
node->typeinfo->execfunc(data, node, nsin, nsout);
}
}
}
}
/* stack indices make sure all nodes only write in allocated data, for making it thread safe */
/* per tree (and per group) unique indices are created */
/* the index_ext we need to be able to map from groups to the group-node own stack */
void ntreeBeginExecTree(bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
int index= 0;
int index= 0, index_in= 0, index_out= 0;
if((ntree->init & NTREE_TYPE_INIT)==0)
ntreeInitTypes(ntree);
if(ntree->init & NTREE_EXEC_INIT)
return;
/* create indices for stack, check preview */
for(node= ntree->nodes.first; node; node= node->next) {
for(sock= node->outputs.first; sock; sock= sock->next) {
sock->stack_index= index++;
for(sock= node->inputs.first; sock; sock= sock->next) {
if(sock->intern==0)
sock->stack_index_ext= index_in++;
}
if(node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */
nodeInitPreview(node, xsize, ysize);
for(sock= node->outputs.first; sock; sock= sock->next) {
sock->stack_index= index++;
if(sock->intern==0)
sock->stack_index_ext= index_out++;
}
if(node->type==NODE_GROUP) {
if(node->id) {
ntreeBeginExecTree((bNodeTree *)node->id);
/* copy internal data from internal nodes to own input sockets */
for(sock= node->inputs.first; sock; sock= sock->next) {
if(sock->tosock) {
sock->ns= sock->tosock->ns;
}
}
}
}
}
if(index) {
bNodeStack *ns;
@@ -672,12 +1247,24 @@ void ntreeBeginExecTree(bNodeTree *ntree, int xsize, int ysize)
void ntreeEndExecTree(bNodeTree *ntree)
{
bNode *node;
if(ntree->init & NTREE_EXEC_INIT) {
if(ntree->stack) {
MEM_freeN(ntree->stack);
ntree->stack= NULL;
}
ntree->init &= ~NTREE_EXEC_INIT;
for(node= ntree->nodes.first; node; node= node->next) {
if(node->type==NODE_GROUP) {
if(node->id) {
ntreeEndExecTree((bNodeTree *)node->id);
}
}
}
}
}
static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
@@ -706,7 +1293,6 @@ void ntreeExecTree(bNodeTree *ntree)
/* only when initialized */
if(ntree->init & NTREE_EXEC_INIT) {
for(node= ntree->nodes.first; node; node= node->next) {
if(node->typeinfo->execfunc) {
node_get_stack(node, ntree->stack, nsin, nsout);

View File

@@ -209,7 +209,8 @@ static void node_shader_exec_normal(void *data, bNode *node, bNodeStack **in, bN
/* stack order output: normal, value */
VECCOPY(out[0]->vec, sock->ns.vec);
out[1]->vec[0]= INPR(out[0]->vec, in[0]->vec);
/* render normals point inside... the widget points outside */
out[1]->vec[0]= -INPR(out[0]->vec, in[0]->vec);
}
/* **************** value node ************ */
@@ -523,6 +524,7 @@ static bNodeType sh_node_rgbtobw= {
/* ****************** types array for all shaders ****************** */
bNodeType *node_all_shaders[]= {
&node_group_typeinfo,
&sh_node_output,
&sh_node_material,
&sh_node_value,

View File

@@ -95,6 +95,7 @@ static IDType idtypes[]= {
{ ID_MA, "Material", IDTYPE_FLAGS_ISLINKABLE},
{ ID_MB, "Metaball", IDTYPE_FLAGS_ISLINKABLE},
{ ID_ME, "Mesh", IDTYPE_FLAGS_ISLINKABLE},
{ ID_NT, "NodeTree", IDTYPE_FLAGS_ISLINKABLE},
{ ID_OB, "Object", IDTYPE_FLAGS_ISLINKABLE},
{ ID_SAMPLE, "Sample", 0},
{ ID_SCE, "Scene", IDTYPE_FLAGS_ISLINKABLE},

View File

@@ -1208,8 +1208,8 @@ static void test_pointer_array(FileData *fd, void **mat)
/* ************ READ NODE TREE *************** */
/* ntree is not NULL */
static void lib_link_nodetree(FileData *fd, ID *id, bNodeTree *ntree)
/* singe node tree, ntree is not NULL */
static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree)
{
bNode *node;
@@ -1217,19 +1217,49 @@ static void lib_link_nodetree(FileData *fd, ID *id, bNodeTree *ntree)
node->id= newlibadr_us(fd, id->lib, node->id);
}
static bNodeTree *direct_link_nodetree(FileData *fd, bNodeTree *ntree)
/* library linking after fileread */
static void lib_link_nodetree(FileData *fd, Main *main)
{
Material *ma;
bNodeTree *ntree;
bNode *node;
/* in multiple steps, first link ID pointers */
for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next) {
if(ntree->id.flag & LIB_NEEDLINK) {
lib_link_ntree(fd, &ntree->id, ntree);
}
}
/* now create the own typeinfo structs an verify nodes */
/* here we still assume no groups in groups */
for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next) {
if(ntree->id.flag & LIB_NEEDLINK) {
ntree->id.flag -= LIB_NEEDLINK;
ntreeVerifyTypes(ntree); /* internal nodes, no groups! */
ntreeMakeOwnType(ntree); /* for group usage */
}
}
/* now verify all types in material trees, groups are set OK now */
for(ma= main->mat.first; ma; ma= ma->id.next) {
if(ma->nodetree)
ntreeVerifyTypes(ma->nodetree);
}
}
/* ntree itself has been read! */
static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
{
/* note: writing and reading goes in sync, for speed */
if(ntree) {
ntree= newdataadr(fd, ntree);
if(ntree) {
bNode *node;
bNodeSocket *sock;
bNodeLink *link;
ntree->init= 0; /* to set callbacks */
ntree->data= NULL; /* safety only */
ntree->owntype= NULL;
link_list(fd, &ntree->nodes);
for(node= ntree->nodes.first; node; node= node->next) {
@@ -1253,13 +1283,8 @@ static bNodeTree *direct_link_nodetree(FileData *fd, bNodeTree *ntree)
link->fromsock= newdataadr(fd, link->fromsock);
link->tosock= newdataadr(fd, link->tosock);
}
/* right after read file, the save-undo will need it */
/* verify also does a full type checking. This is relative slow... so we
might move this later to the do_versions, and put ntreeInitTypes() only here */
ntreeVerifyTypes(ntree);
}
}
return ntree;
/* type verification is in lib-link */
}
/* ************ READ PACKEDFILE *************** */
@@ -2064,7 +2089,7 @@ static void lib_link_material(FileData *fd, Main *main)
ml->mat= newlibadr_us(fd, ma->id.lib, ml->mat);
if(ma->nodetree)
lib_link_nodetree(fd, &ma->id, ma->nodetree);
lib_link_ntree(fd, &ma->id, ma->nodetree);
ma->id.flag -= LIB_NEEDLINK;
}
@@ -2087,7 +2112,9 @@ static void direct_link_material(FileData *fd, Material *ma)
link_list(fd, &ma->layers);
ma->nodetree= direct_link_nodetree(fd, ma->nodetree);
ma->nodetree= newdataadr(fd, ma->nodetree);
if(ma->nodetree)
direct_link_nodetree(fd, ma->nodetree);
}
/* ************ READ MESH ***************** */
@@ -3058,7 +3085,7 @@ void lib_link_screen_restore(Main *newmain, Scene *curscene)
else if(sl->spacetype==SPACE_NODE) {
SpaceNode *snode= (SpaceNode *)sl;
snode->nodetree= NULL;
snode->nodetree= snode->edittree= NULL;
snode->flag |= SNODE_DO_PREVIEW;
}
}
@@ -3153,7 +3180,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
}
else if(sl->spacetype==SPACE_NODE) {
SpaceNode *snode= (SpaceNode *)sl;
snode->nodetree= NULL;
snode->nodetree= snode->edittree= NULL;
snode->flag |= SNODE_DO_PREVIEW;
}
}
@@ -3280,6 +3307,43 @@ static void lib_link_group(FileData *fd, Main *main)
/* ************** GENERAL & MAIN ******************** */
static char *libname(short id_code)
{
}
static char *dataname(short id_code)
{
switch( id_code ) {
case ID_OB: return "Data from OB";
case ID_ME: return "Data from ME";
case ID_IP: return "Data from IP";
case ID_SCE: return "Data from SCE";
case ID_MA: return "Data from MA";
case ID_TE: return "Data from TE";
case ID_CU: return "Data from CU";
case ID_GR: return "Data from GR";
case ID_AR: return "Data from AR";
case ID_AC: return "Data from AC";
case ID_LI: return "Data from LI";
case ID_MB: return "Data from MB";
case ID_IM: return "Data from IM";
case ID_LT: return "Data from LT";
case ID_LA: return "Data from LA";
case ID_CA: return "Data from CA";
case ID_KE: return "Data from KE";
case ID_WO: return "Data from WO";
case ID_SCR: return "Data from SCR";
case ID_VF: return "Data from VF";
case ID_TXT : return "Data from TXT";
case ID_SO: return "Data from SO";
case ID_SAMPLE: return "Data from SAMPLE";
}
return "Data from Lib Block";
}
static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID **id_r)
{
/* this routine reads a libblock and its direct data. Use link functions
@@ -3288,7 +3352,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
ID *id;
ListBase *lb;
char *str = NULL;
char *allocname;
if(bhead->code==ID_ID) {
ID *linkedid= (ID *)(bhead + 1); /* BHEAD+DATA dependancy */
@@ -3323,39 +3387,12 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
bhead = blo_nextbhead(fd, bhead);
switch( GS(id->name) ) {
case ID_OB: str= "ID_OB"; break;
case ID_SCE: str= "ID_SCE"; break;
case ID_LI: str= "ID_LI"; break;
case ID_ME: str= "ID_ME"; break;
case ID_CU: str= "ID_CU"; break;
case ID_MB: str= "ID_MB"; break;
case ID_MA: str= "ID_MA"; break;
case ID_TE: str= "ID_TE"; break;
case ID_IM: str= "ID_IM"; break;
case ID_IK: str= "ID_IK"; break;
case ID_WV: str= "ID_WV"; break;
case ID_LT: str= "ID_LT"; break;
case ID_SE: str= "ID_SE"; break;
case ID_LF: str= "ID_LF"; break;
case ID_LA: str= "ID_LA"; break;
case ID_CA: str= "ID_CA"; break;
case ID_IP: str= "ID_IP"; break;
case ID_KE: str= "ID_KE"; break;
case ID_WO: str= "ID_WO"; break;
case ID_SCR: str= "ID_SCR"; break;
case ID_VF: str= "ID_VF"; break;
case ID_TXT : str= "ID_TXT"; break;
case ID_SO: str= "ID_SO"; break;
case ID_SAMPLE: str= "ID_SAMPLE"; break;
case ID_GR: str= "ID_GR"; break;
case ID_SEQ: str= "ID_SEQ"; break;
case ID_AR: str= "ID_AR"; break;
case ID_AC: str= "ID_AC"; break;
}
/* need a name for the mallocN, just for debugging and sane prints on leaks */
allocname= dataname(GS(id->name));
/* read all data */
while(bhead && bhead->code==DATA) {
void *data= read_struct(fd, bhead, str);
void *data= read_struct(fd, bhead, allocname);
if (data) {
oldnewmap_insert(fd->datamap, bhead->old, data, 0);
@@ -3432,6 +3469,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
case ID_AC:
direct_link_action(fd, (bAction*)id);
break;
case ID_NT:
direct_link_nodetree(fd, (bNodeTree*)id);
break;
}
oldnewmap_free_unused(fd->datamap);
@@ -5221,6 +5261,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_armature(fd, main);
lib_link_action(fd, main);
lib_link_vfont(fd, main);
lib_link_nodetree(fd, main); /* has to be done after materials, it will verify group nodes */
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
@@ -5425,6 +5466,16 @@ static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
expand_doit(fd, mainvar, tex->ipo);
}
static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
{
bNode *node;
for(node= ntree->nodes.first; node; node= node->next)
if(node->id)
expand_doit(fd, mainvar, node->id);
}
static void expand_material(FileData *fd, Main *mainvar, Material *ma)
{
MaterialLayer *ml;
@@ -5444,12 +5495,8 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma)
expand_doit(fd, mainvar, ml->mat);
}
if(ma->nodetree) {
bNode *node;
for(node= ma->nodetree->nodes.first; node; node= node->next)
if(node->id)
expand_doit(fd, mainvar, node->id);
}
if(ma->nodetree)
expand_nodetree(fd, mainvar, ma->nodetree);
}
static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la)
@@ -5862,6 +5909,9 @@ static void expand_main(FileData *fd, Main *mainvar)
case ID_GR:
expand_group(fd, mainvar, (Group *)id);
break;
case ID_NT:
expand_nodetree(fd, mainvar, (bNodeTree *)id);
break;
}
doit= 1;

View File

@@ -362,15 +362,13 @@ static void writedata(WriteData *wd, int filecode, int len, void *adr) /* do not
if(len) mywrite(wd, adr, len);
}
/* this is only direct data */
/* this is only direct data, tree itself should have been written */
static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
bNodeLink *link;
writestruct(wd, DATA, "bNodeTree", 1, ntree);
/* for link_list() speed, we write per list */
for(node= ntree->nodes.first; node; node= node->next)
@@ -1044,9 +1042,12 @@ static void write_materials(WriteData *wd, ListBase *idbase)
for (ml=ma->layers.first; ml; ml=ml->next)
writestruct(wd, DATA, "MaterialLayer", 1, ml);
if(ma->nodetree)
/* nodetree is integral part of material, no libdata */
if(ma->nodetree) {
writestruct(wd, DATA, "bNodeTree", 1, ma->nodetree);
write_nodetree(wd, ma->nodetree);
}
}
ma= ma->id.next;
}
}
@@ -1428,8 +1429,8 @@ static void write_actions(WriteData *wd, ListBase *idbase)
{
bAction *act;
bActionChannel *chan;
act=idbase->first;
while (act) {
for(act=idbase->first; act; act= act->id.next) {
if (act->id.us>0 || wd->current) {
writestruct(wd, ID_AC, "bAction", 1, act);
@@ -1438,7 +1439,6 @@ static void write_actions(WriteData *wd, ListBase *idbase)
write_constraint_channels(wd, &chan->constraintChannels);
}
}
act=act->id.next;
}
}
@@ -1530,8 +1530,7 @@ static void write_groups(WriteData *wd, ListBase *idbase)
Group *group;
GroupObject *go;
group= idbase->first;
while(group) {
for(group= idbase->first; group; group= group->id.next) {
if(group->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_GR, "Group", 1, group);
@@ -1542,7 +1541,18 @@ static void write_groups(WriteData *wd, ListBase *idbase)
go= go->next;
}
}
group= group->id.next;
}
}
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);
}
}
}
@@ -1603,6 +1613,7 @@ static int write_file_handle(int handle, MemFile *compare, MemFile *current, int
write_materials(wd, &G.main->mat);
write_textures (wd, &G.main->tex);
write_meshs (wd, &G.main->mesh);
write_nodetrees(wd, &G.main->nodetree);
write_libraries(wd, G.main->next);
write_global(wd);

View File

@@ -272,7 +272,7 @@ typedef enum {
ICON_SYNTAX_OFF,
ICON_BLANK52,
ICON_BLANK53,
ICON_BLANK54,
ICON_PLUS,
ICON_VIEWMOVE,
ICON_HOME,
ICON_CLIPUV_DEHLT,
@@ -462,7 +462,7 @@ enum {
TH_NODE_IN_OUT,
TH_NODE_OPERATOR,
TH_NODE_GENERATOR,
TH_NODE_FREE,
TH_NODE_GROUP,
};
/* XXX WARNING: previous is saved in file, so do not change order! */

View File

@@ -52,6 +52,8 @@ void node_deselectall(struct SpaceNode *snode, int swap);
void node_transform_ext(int mode, int unused);
void node_shader_default(struct Material *ma);
int node_has_hidden_sockets(struct bNode *node);
/* ************* drawnode.c *************** */
void node_draw_link(struct SpaceNode *snode, struct bNodeLink *link);

View File

@@ -126,6 +126,7 @@ typedef struct Library {
#define ID_AR MAKE_ID2('A', 'R')
#define ID_AC MAKE_ID2('A', 'C')
#define ID_SCRIPT MAKE_ID2('P', 'Y')
#define ID_NT MAKE_ID2('N', 'T')
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
#define ID_SEQ MAKE_ID2('S', 'Q')

View File

@@ -37,6 +37,7 @@ struct ID;
struct SpaceNode;
struct bNodeLink;
struct bNodeType;
struct bNodeGroup;
struct uiBlock;
#define NODE_MAXSTR 32
@@ -55,10 +56,21 @@ typedef struct bNodeSocket {
char name[32];
bNodeStack ns; /* custom data for inputs, only UI writes in this */
short type, flag, limit, stack_index;
short type, flag; /* type is copy from socket type struct */
short limit, stack_index; /* limit for dependency sort, stack_index for exec */
short intern; /* intern = tag for group nodes */
short stack_index_ext; /* for groups, to find the caller stack index */
int pad1;
float locx, locy;
struct bNodeLink *link; /* input link to parent, max one! set in nodeSolveOrder() */
/* internal data to retrieve relations and groups */
int own_index, to_index; /* group socket identifiers, to find matching pairs after reading files */
struct bNodeSocket *tosock; /* group-node sockets point to the internal group counterpart sockets, set after read file */
struct bNodeLink *link; /* a link pointer, set in nodeSolveOrder() */
} bNodeSocket;
@@ -69,6 +81,10 @@ typedef struct bNodeSocket {
#define SOCK_IMAGE 3
/* sock->flag, first bit is select */
#define SOCK_HIDDEN 2
/* only used now for groups... */
#define SOCK_IN_USE 4
#
#
typedef struct bNodePreview {
@@ -114,6 +130,7 @@ typedef struct bNode {
#define NODE_ACTIVE 16
#define NODE_ACTIVE_ID 32
#define NODE_DO_OUTPUT 64
#define NODE_GROUP_EDIT 128
typedef struct bNodeLink {
struct bNodeLink *next, *prev;
@@ -124,14 +141,19 @@ typedef struct bNodeLink {
} bNodeLink;
/* the basis for a Node tree, all links and nodes reside internal here */
/* only re-usable node trees are in the library though, materials allocate own tree struct */
typedef struct bNodeTree {
ID id;
ListBase nodes, links;
void *data; /* custom data, set by execute caller, no read/write handling */
bNodeStack *stack; /* stack is only while executing */
bNodeStack *stack; /* stack is only while executing, no read/write */
int type, init; /* set init on fileread */
struct bNodeType **alltypes; /* type definitions, set on fileread */
int cur_index, pad; /* sockets in groups have unique identifiers, adding new sockets always will increase this counter */
struct bNodeType **alltypes; /* type definitions, set on fileread, no read/write */
struct bNodeType *owntype; /* for groups or dynamic trees, no read/write */
} bNodeTree;

View File

@@ -306,8 +306,8 @@ typedef struct SpaceNode {
float aspect;
void *curfont;
struct bNodeTree *nodetree;
int treetype, pad; /* treetype: same nodetree->type */
struct bNodeTree *nodetree, *edittree;
int treetype, pad; /* treetype: as same nodetree->type */
} SpaceNode;

View File

@@ -192,6 +192,8 @@ void ramp_spec_result(float *specr, float *specg, float *specb, ShadeInput *shi)
void matlayer_blend(struct MaterialLayer *ml, float blendfac, struct ShadeResult *target, struct ShadeResult *src);
void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col);
void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr);
/* --------------------------------------------------------------------- */
/* ray.c (2) */
/* --------------------------------------------------------------------- */

View File

@@ -52,6 +52,7 @@
#include "DNA_texture_types.h"
#include "BKE_global.h"
#include "BKE_node.h"
#include "BKE_texture.h"
#include "BLI_rand.h"
@@ -2266,6 +2267,38 @@ void matlayer_blend(MaterialLayer *ml, float blendfac, ShadeResult *target, Shad
ramp_blend(ml->blendmethod, &target->alpha, NULL, NULL, blendfac, &src->alpha);
}
/* also used as callback for nodes */
void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
{
shade_lamp_loop(shi, shr); /* clears shr */
if(shi->translucency!=0.0) {
ShadeResult shr_t;
VECCOPY(shi->vn, shi->vno);
VecMulf(shi->vn, -1.0);
VecMulf(shi->facenor, -1.0);
shade_lamp_loop(shi, &shr_t);
shr->diff[0]+= shi->translucency*shr_t.diff[0];
shr->diff[1]+= shi->translucency*shr_t.diff[1];
shr->diff[2]+= shi->translucency*shr_t.diff[2];
VecMulf(shi->vn, -1.0);
VecMulf(shi->facenor, -1.0);
}
if(R.r.mode & R_RAYTRACE) {
if(shi->ray_mirror!=0.0 || ((shi->mat->mode & MA_RAYTRANSP) && shr->alpha!=1.0)) {
ray_trace(shi, shr);
}
}
else {
/* doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this */
if(shi->mat->mode & MA_RAYTRANSP) shr->alpha= 1.0;
}
}
/* x,y: window coordinate from 0 to rectx,y */
/* return pointer to rendered face */
@@ -2293,14 +2326,12 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col, floa
}
else if( (facenr & 0x7FFFFF) <= R.totvlak) {
VertRen *v1;
Material *mat;
MaterialLayer *ml;
float alpha, fac, zcor;
vlr= RE_findOrAddVlak( (facenr-1) & 0x7FFFFF);
shi.vlr= vlr;
mat= shi.mat= vlr->mat;
shi.mat= vlr->mat;
shi.osatex= (shi.mat->texco & TEXCO_OSA);
@@ -2482,66 +2513,12 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col, floa
/* ------ main shading loop -------- */
VECCOPY(shi.vno, shi.vn);
if(1) { //shi.mat->ml_flag & ML_RENDER) {
shade_lamp_loop(&shi, &shr); /* clears shr */
if(shi.translucency!=0.0) {
ShadeResult shr_t;
VECCOPY(shi.vn, shi.vno);
VecMulf(shi.vn, -1.0);
VecMulf(shi.facenor, -1.0);
shade_lamp_loop(&shi, &shr_t);
shr.diff[0]+= shi.translucency*shr_t.diff[0];
shr.diff[1]+= shi.translucency*shr_t.diff[1];
shr.diff[2]+= shi.translucency*shr_t.diff[2];
VecMulf(shi.vn, -1.0);
VecMulf(shi.facenor, -1.0);
}
if(R.r.mode & R_RAYTRACE) {
if(shi.ray_mirror!=0.0 || ((shi.mat->mode & MA_RAYTRANSP) && shr.alpha!=1.0)) {
ray_trace(&shi, &shr);
}
if(shi.mat->nodetree && shi.mat->use_nodes) {
ntreeShaderExecTree(shi.mat->nodetree, &shi, &shr);
}
else {
/* doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this */
if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0;
shade_material_loop(&shi, &shr);
}
}
else {
memset(&shr, 0, sizeof(ShadeResult));
shr.alpha= 1.0f;
}
for(ml= shi.mat->layers.first; ml; ml= ml->next) {
if(ml->mat && (ml->flag & ML_RENDER)) {
ShadeResult shrlay;
shi.mat= ml->mat;
shi.layerfac= ml->blendfac;
VECCOPY(shi.vn, shi.vno);
if(ml->flag & ML_NEG_NORMAL)
VecMulf(shi.vn, -1.0);
shade_lamp_loop(&shi, &shrlay); /* clears shrlay */
if(R.r.mode & R_RAYTRACE) {
if(shi.ray_mirror!=0.0 || ((shi.mat->mode & MA_RAYTRANSP) && shr.alpha!=1.0)) {
ray_trace(&shi, &shr);
}
}
else {
/* doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this */
if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0;
}
matlayer_blend(ml, shi.layerfac, &shr, &shrlay);
}
}
shi.mat= mat;
/* after shading and composit layers */
if(shr.spec[0]<0.0f) shr.spec[0]= 0.0f;

View File

@@ -2665,6 +2665,8 @@ void RE_freeRotateBlenderScene(void)
free_mesh_orco_hash();
end_radio_render();
end_render_materials();
if(R.wrld.aosphere) {
MEM_freeN(R.wrld.aosphere);
R.wrld.aosphere= NULL;
@@ -2882,6 +2884,7 @@ void RE_rotateBlenderScene(void)
}
init_render_textures();
init_render_materials();
set_node_shader_lamp_loop(shade_material_loop);
/* imat objects, OB_DO_IMAT can be set in init_render_materials
has to be done here, since displace can have texture using Object map-input */

File diff suppressed because it is too large Load Diff

View File

@@ -105,9 +105,9 @@ static void snode_drawstring(SpaceNode *snode, char *str, int okwidth)
/* ************** Socket callbacks *********** */
/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
static uiBlock *socket_vector_menu(void *sock_v)
static uiBlock *socket_vector_menu(void *butpoin_v)
{
bNodeSocket *sock= sock_v;
float *butpoin= butpoin_v;
uiBlock *block;
block= uiNewBlock(&curarea->uiblocks, "socket menu", UI_EMBOSS, UI_HELV, curarea->win);
@@ -116,9 +116,9 @@ static uiBlock *socket_vector_menu(void *sock_v)
uiDefBut(block, LABEL, 0, "", -4, -4, 188, 68, NULL, 0, 0, 0, 0, "");
uiBlockBeginAlign(block);
uiDefButF(block, NUMSLI, 0, "X ", 0,40,180,20, sock->ns.vec, -1.0, 1.0, 10, 0, "");
uiDefButF(block, NUMSLI, 0, "Y ", 0,20,180,20, sock->ns.vec+1, -1.0, 1.0, 10, 0, "");
uiDefButF(block, NUMSLI, 0, "Z ", 0,0,180,20, sock->ns.vec+2, -1.0, 1.0, 10, 0, "");
uiDefButF(block, NUMSLI, 0, "X ", 0,40,180,20, butpoin, -1.0, 1.0, 10, 0, "");
uiDefButF(block, NUMSLI, 0, "Y ", 0,20,180,20, butpoin+1, -1.0, 1.0, 10, 0, "");
uiDefButF(block, NUMSLI, 0, "Z ", 0,0,180,20, butpoin+2, -1.0, 1.0, 10, 0, "");
uiBlockSetDirection(block, UI_TOP);
@@ -127,8 +127,7 @@ static uiBlock *socket_vector_menu(void *sock_v)
return block;
}
/* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
/* ****************** GENERAL CALLBACKS FOR NODES ***************** */
static void node_ID_title_cb(void *node_v, void *unused_v)
{
@@ -144,6 +143,41 @@ static void node_ID_title_cb(void *node_v, void *unused_v)
}
}
static int node_buts_group(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
{
if(block && node->id) {
uiBut *bt;
short width;
uiBlockBeginAlign(block);
/* name button */
width= (short)(butr->xmax-butr->xmin - (node->id->us>1?19.0f:0.0f));
bt= uiDefBut(block, TEX, B_NOP, "NT:",
butr->xmin, butr->ymin, width, 19,
node->id->name+2, 0.0, 19.0, 0, 0, "NodeTree name");
uiButSetFunc(bt, node_ID_title_cb, node, NULL);
/* user amount */
if(node->id->us>1) {
char str1[32];
sprintf(str1, "%d", node->id->us);
bt= uiDefBut(block, BUT, B_NOP, str1,
butr->xmax-19, butr->ymin, 19, 19,
NULL, 0, 0, 0, 0, "Displays number of users. Click to make a single-user copy.");
//uiButSetFunc(bt, node_mat_alone_cb, node, NULL);
}
uiBlockEndAlign(block);
}
return 19;
}
/* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
static void node_mat_alone_cb(void *node_v, void *unused)
{
bNode *node= node_v;
@@ -170,7 +204,10 @@ static void node_browse_mat_cb(void *ntree_v, void *node_v)
ma->id.us--;
ma= copy_material(ma);
ma->use_nodes= 0;
if(ma->nodetree) ntreeFreeTree(ma->nodetree);
if(ma->nodetree) {
ntreeFreeTree(ma->nodetree);
MEM_freeN(ma->nodetree);
}
ma->nodetree= NULL;
node->id= (ID *)ma;
}
@@ -371,6 +408,9 @@ static int node_shader_buts_valtorgb(uiBlock *block, bNodeTree *ntree, bNode *no
static void node_shader_set_butfunc(bNodeType *ntype)
{
switch(ntype->type) {
case NODE_GROUP: /* note, generic type, but put here because we call this function anyway */
ntype->butfunc= node_buts_group;
break;
case SH_NODE_MATERIAL:
ntype->butfunc= node_shader_buts_material;
break;
@@ -548,18 +588,21 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
}
/* based on settings in node, sets drawing rect info */
static void node_update(bNode *node)
/* based on settings in node, sets drawing rect info. each redraw! */
static void node_update_hidden(bNode *node)
{
bNodeSocket *nsock;
if(node->flag & NODE_HIDDEN) {
float rad, drad, hiddenrad= HIDDEN_RAD;
int totin, totout, tot;
int totin=0, totout=0, tot;
/* calculate minimal radius */
totin= BLI_countlist(&node->inputs);
totout= BLI_countlist(&node->outputs);
for(nsock= node->inputs.first; nsock; nsock= nsock->next)
if(!(nsock->flag & SOCK_HIDDEN))
totin++;
for(nsock= node->outputs.first; nsock; nsock= nsock->next)
if(!(nsock->flag & SOCK_HIDDEN))
totout++;
tot= MAX2(totin, totout);
if(tot>4) {
hiddenrad += 5.0*(float)(tot-4);
@@ -570,34 +613,50 @@ static void node_update(bNode *node)
node->totr.ymax= node->locy + (hiddenrad - 0.5f*NODE_DY);
node->totr.ymin= node->totr.ymax - 2*hiddenrad;
/* output connectors */
/* output sockets */
rad=drad= M_PI/(1.0f + (float)totout);
for(nsock= node->outputs.first; nsock; nsock= nsock->next, rad+= drad) {
for(nsock= node->outputs.first; nsock; nsock= nsock->next) {
if(!(nsock->flag & SOCK_HIDDEN)) {
nsock->locx= node->totr.xmax - hiddenrad + sin(rad)*hiddenrad;
nsock->locy= node->totr.ymin + hiddenrad + cos(rad)*hiddenrad;
rad+= drad;
}
}
/* input connectors */
/* input sockets */
rad=drad= - M_PI/(1.0f + (float)totin);
for(nsock= node->inputs.first; nsock; nsock= nsock->next, rad+= drad) {
for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
if(!(nsock->flag & SOCK_HIDDEN)) {
nsock->locx= node->totr.xmin + hiddenrad + sin(rad)*hiddenrad;
nsock->locy= node->totr.ymin + hiddenrad + cos(rad)*hiddenrad;
rad+= drad;
}
}
else {
}
/* based on settings in node, sets drawing rect info. each redraw! */
static void node_update(bNode *node)
{
bNodeSocket *nsock;
float dy= node->locy;
/* header */
dy-= NODE_DY;
/* output connectors */
/* little bit space in top */
if(node->outputs.first)
dy-= NODE_DYS/2;
/* output sockets */
for(nsock= node->outputs.first; nsock; nsock= nsock->next) {
if(!(nsock->flag & SOCK_HIDDEN)) {
nsock->locx= node->locx + node->width;
nsock->locy= dy - NODE_DYS;
dy-= NODE_DY;
}
}
node->prvr.xmin= node->butr.xmin= node->locx + NODE_DYS;
node->prvr.xmax= node->butr.xmax= node->locx + node->width- NODE_DYS;
@@ -618,17 +677,73 @@ static void node_update(bNode *node)
dy= node->butr.ymin - NODE_DYS/2;
}
/* input connectors */
/* input sockets */
for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
if(!(nsock->flag & SOCK_HIDDEN)) {
nsock->locx= node->locx;
nsock->locy= dy - NODE_DYS;
dy-= NODE_DY;
}
}
/* little bit space in end */
if(node->inputs.first || (node->flag & (NODE_OPTIONS|NODE_PREVIEW))==0 )
dy-= NODE_DYS/2;
node->totr.xmin= node->locx;
node->totr.xmax= node->locx + node->width;
node->totr.ymax= node->locy;
node->totr.ymin= dy;
}
/* based on settings in node, sets drawing rect info. each redraw! */
/* note: this assumes only 1 group at a time is drawn (linked data) */
/* in node->totr the entire boundbox for the group is stored */
static void node_update_group(bNode *gnode)
{
bNodeTree *ngroup= (bNodeTree *)gnode->id;
bNode *node;
bNodeSocket *nsock;
rctf *rect= &gnode->totr;
int counter;
/* center them, is a bit of abuse of locx and locy though */
for(node= ngroup->nodes.first; node; node= node->next) {
node->locx+= gnode->locx;
node->locy+= gnode->locy;
if(node->flag & NODE_HIDDEN)
node_update_hidden(node);
else
node_update(node);
node->locx-= gnode->locx;
node->locy-= gnode->locy;
}
counter= 1;
for(node= ngroup->nodes.first; node; node= node->next) {
if(counter) {
*rect= node->totr;
counter= 0;
}
else
BLI_union_rctf(rect, &node->totr);
}
if(counter==1) return; /* should be prevented? */
rect->xmin-= NODE_DY;
rect->ymin-= NODE_DY;
rect->xmax+= NODE_DY;
rect->ymax+= NODE_DY;
/* output sockets */
for(nsock= gnode->outputs.first; nsock; nsock= nsock->next) {
nsock->locx= rect->xmax;
nsock->locy= nsock->tosock->locy;
}
/* input sockets */
for(nsock= gnode->inputs.first; nsock; nsock= nsock->next) {
nsock->locx= rect->xmin;
nsock->locy= nsock->tosock->locy;
}
}
@@ -663,10 +778,12 @@ static int node_get_colorid(bNode *node)
return TH_NODE_GENERATOR;
if(node->typeinfo->nclass==NODE_CLASS_OPERATOR)
return TH_NODE_OPERATOR;
if(node->typeinfo->nclass==NODE_CLASS_GROUP)
return TH_NODE_GROUP;
return TH_NODE;
}
static void node_basis_draw(ScrArea *sa, SpaceNode *snode, bNode *node)
static void node_draw_basis(ScrArea *sa, SpaceNode *snode, bNode *node)
{
bNodeSocket *sock;
rctf *rct= &node->totr;
@@ -685,7 +802,7 @@ static void node_basis_draw(ScrArea *sa, SpaceNode *snode, bNode *node)
uiSetRoundBox(3);
uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, BASIS_RAD);
/* show/hide icons */
/* show/hide icons, note this sequence is copied in editnode.c */
iconofs= rct->xmax;
if(node->typeinfo->flag & NODE_PREVIEW) {
@@ -698,14 +815,34 @@ static void node_basis_draw(ScrArea *sa, SpaceNode *snode, bNode *node)
iconofs-= 18.0f;
glEnable(GL_BLEND);
BIF_icon_set_aspect(icon_id, snode->aspect);
BIF_icon_draw_blended(iconofs, rct->ymax-NODE_DY+2, icon_id, 0, -50);
BIF_icon_draw_blended(iconofs, rct->ymax-NODE_DY+2, icon_id, 0, -60);
glDisable(GL_BLEND);
}
if(node->type == NODE_GROUP) {
iconofs-= 18.0f;
glEnable(GL_BLEND);
BIF_icon_set_aspect(ICON_NODE, snode->aspect);
BIF_icon_draw_blended(iconofs, rct->ymax-NODE_DY+2, ICON_NODE, 0, -60);
glDisable(GL_BLEND);
}
if(node->typeinfo->flag & NODE_OPTIONS) {
iconofs-= 18.0f;
glEnable(GL_BLEND);
BIF_icon_set_aspect(ICON_BUTS, snode->aspect);
BIF_icon_draw_blended(iconofs, rct->ymax-NODE_DY+2, ICON_BUTS, 0, -50);
BIF_icon_draw_blended(iconofs, rct->ymax-NODE_DY+2, ICON_BUTS, 0, -60);
glDisable(GL_BLEND);
}
if(node->outputs.first) {
int shade;
/* socket selector */
iconofs-= 18.0f;
if(node_has_hidden_sockets(node))
shade= -40;
else
shade= -90;
glEnable(GL_BLEND);
BIF_icon_set_aspect(ICON_PLUS, snode->aspect);
BIF_icon_draw_blended(iconofs, rct->ymax-NODE_DY+2, ICON_PLUS, 0, shade);
glDisable(GL_BLEND);
}
@@ -755,23 +892,29 @@ static void node_basis_draw(ScrArea *sa, SpaceNode *snode, bNode *node)
/* socket inputs, label buttons */
for(sock= node->inputs.first; sock; sock= sock->next) {
if(!(sock->flag & SOCK_HIDDEN)) {
socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT);
if(node->block && sock->link==NULL) {
float *butpoin= sock->ns.vec;
if(node->type==NODE_GROUP && sock->tosock)
butpoin= sock->tosock->ns.vec;
if(sock->type==SOCK_VALUE) {
uiDefButF(node->block, NUM, B_NODE_EXEC, sock->name,
(short)node->locx+NODE_DYS, (short)(sock->locy)-7, (short)node->width-NODE_DY, 17,
sock->ns.vec, 0.0f, 1.0f, 10, 2, "");
(short)sock->locx+NODE_DYS, (short)(sock->locy)-9, (short)node->width-NODE_DY, 17,
butpoin, 0.0f, 1.0f, 10, 2, "");
}
else if(sock->type==SOCK_VECTOR) {
uiDefBlockBut(node->block, socket_vector_menu, sock, sock->name,
(short)node->locx+NODE_DYS, (short)sock->locy-7, (short)node->width-NODE_DY, 17,
uiDefBlockBut(node->block, socket_vector_menu, butpoin, sock->name,
(short)sock->locx+NODE_DYS, (short)sock->locy-9, (short)node->width-NODE_DY, 17,
"");
}
else if(node->block && sock->type==SOCK_RGBA) {
uiDefButF(node->block, COL, B_NODE_EXEC, "",
(short)(node->locx+NODE_DYS), (short)sock->locy-6, (short)(node->width-NODE_DY), 15,
sock->ns.vec, 0, 0, 0, 0, "");
(short)(sock->locx+NODE_DYS), (short)sock->locy-8, (short)(node->width-NODE_DY), 15,
butpoin, 0, 0, 0, 0, "");
}
}
else {
@@ -780,9 +923,11 @@ static void node_basis_draw(ScrArea *sa, SpaceNode *snode, bNode *node)
BIF_DrawString(snode->curfont, sock->name, 0);
}
}
}
/* socket outputs */
for(sock= node->outputs.first; sock; sock= sock->next) {
if(!(sock->flag & SOCK_HIDDEN)) {
socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT);
BIF_ThemeColor(TH_TEXT);
@@ -795,6 +940,7 @@ static void node_basis_draw(ScrArea *sa, SpaceNode *snode, bNode *node)
ui_rasterpos_safe(sock->locx-8.0f-slen, sock->locy-5.0f, snode->aspect);
BIF_DrawString(snode->curfont, sock->name+ofs, 0);
}
}
/* preview */
if(node->flag & NODE_PREVIEW)
@@ -811,7 +957,7 @@ static void node_basis_draw(ScrArea *sa, SpaceNode *snode, bNode *node)
}
void node_hidden_draw(SpaceNode *snode, bNode *node)
void node_draw_hidden(SpaceNode *snode, bNode *node)
{
bNodeSocket *sock;
rctf *rct= &node->totr;
@@ -865,25 +1011,19 @@ void node_hidden_draw(SpaceNode *snode, bNode *node)
fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f);
fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f);
/* icon */
// if(node->id) {
// glEnable(GL_BLEND);
// BIF_icon_set_aspect(node->id->icon_id, snode->aspect);
// BIF_icon_draw(rct->xmin+hiddenrad, -1.0f+rct->ymin+hiddenrad/2, node->id->icon_id);
// glDisable(GL_BLEND);
// }
/* sockets */
for(sock= node->inputs.first; sock; sock= sock->next) {
if(!(sock->flag & SOCK_HIDDEN))
socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT);
}
for(sock= node->outputs.first; sock; sock= sock->next) {
if(!(sock->flag & SOCK_HIDDEN))
socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT);
}
}
/* note; this is used for fake links in groups too */
void node_draw_link(SpaceNode *snode, bNodeLink *link)
{
float vec[4][3];
@@ -901,6 +1041,10 @@ void node_draw_link(SpaceNode *snode, bNodeLink *link)
BIF_ThemeColor(TH_WIRE);
}
else {
/* a bit ugly... but thats how we detect the internal group links */
if(link->fromnode==link->tonode)
BIF_ThemeColorBlend(TH_BACK, TH_WIRE, 0.25f);
else {
/* check cyclic */
if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF)
@@ -908,6 +1052,7 @@ void node_draw_link(SpaceNode *snode, bNodeLink *link)
else
BIF_ThemeColor(TH_REDALERT);
}
}
vec[0][2]= vec[1][2]= vec[2][2]= vec[3][2]= 0.0; /* only 2d spline, set the Z to 0*/
@@ -957,6 +1102,127 @@ void node_draw_link(SpaceNode *snode, bNodeLink *link)
}
}
static void node_draw_nodetree(ScrArea *sa, SpaceNode *snode, bNodeTree *ntree)
{
bNode *node;
bNodeLink *link;
if(ntree==NULL) return; /* groups... */
/* node lines */
glEnable(GL_BLEND);
glEnable( GL_LINE_SMOOTH );
for(link= ntree->links.first; link; link= link->next)
node_draw_link(snode, link);
glDisable(GL_BLEND);
glDisable( GL_LINE_SMOOTH );
/* not selected first */
for(node= ntree->nodes.first; node; node= node->next) {
node->block= NULL; /* were freed */
if(!(node->flag & SELECT)) {
if(node->flag & NODE_GROUP_EDIT);
else if(node->flag & NODE_HIDDEN)
node_draw_hidden(snode, node);
else
node_draw_basis(sa, snode, node);
}
}
/* selected */
for(node= ntree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
if(node->flag & NODE_GROUP_EDIT);
else if(node->flag & NODE_HIDDEN)
node_draw_hidden(snode, node);
else
node_draw_basis(sa, snode, node);
}
}
}
/* fake links from groupnode to internal nodes */
static void node_draw_group_links(SpaceNode *snode, bNode *gnode)
{
bNodeLink fakelink;
bNodeSocket *sock;
glEnable(GL_BLEND);
glEnable( GL_LINE_SMOOTH );
fakelink.tonode= fakelink.fromnode= gnode;
for(sock= gnode->inputs.first; sock; sock= sock->next) {
if(!(sock->flag & SOCK_HIDDEN)) {
if(sock->tosock) {
fakelink.fromsock= sock;
fakelink.tosock= sock->tosock;
node_draw_link(snode, &fakelink);
}
}
}
for(sock= gnode->outputs.first; sock; sock= sock->next) {
if(!(sock->flag & SOCK_HIDDEN)) {
if(sock->tosock) {
fakelink.tosock= sock;
fakelink.fromsock= sock->tosock;
node_draw_link(snode, &fakelink);
}
}
}
glDisable(GL_BLEND);
glDisable( GL_LINE_SMOOTH );
}
/* groups are, on creation, centered around 0,0 */
static void node_draw_group(ScrArea *sa, SpaceNode *snode, bNode *gnode)
{
bNodeTree *ngroup= (bNodeTree *)gnode->id;
bNodeSocket *sock;
rctf rect= gnode->totr;
/* backdrop header */
glEnable(GL_BLEND);
uiSetRoundBox(3);
BIF_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
gl_round_box(GL_POLYGON, rect.xmin, rect.ymax, rect.xmax, rect.ymax+NODE_DY, BASIS_RAD);
/* backdrop body */
BIF_ThemeColorShadeAlpha(TH_BACK, -8, -70);
uiSetRoundBox(12);
gl_round_box(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD);
/* selection outline */
uiSetRoundBox(15);
glColor4ub(200, 200, 200, 140);
glEnable( GL_LINE_SMOOTH );
gl_round_box(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax+NODE_DY, BASIS_RAD);
glDisable( GL_LINE_SMOOTH );
glDisable(GL_BLEND);
/* backdrop title */
BIF_ThemeColor(TH_TEXT_HI);
ui_rasterpos_safe(rect.xmin+8.0f, rect.ymax+5.0f, snode->aspect);
BIF_DrawString(snode->curfont, ngroup->id.name+2, 0);
/* links from groupsockets to the internal nodes */
node_draw_group_links(snode, gnode);
/* group sockets */
for(sock= gnode->inputs.first; sock; sock= sock->next)
if(!(sock->flag & SOCK_HIDDEN))
socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT);
for(sock= gnode->outputs.first; sock; sock= sock->next)
if(!(sock->flag & SOCK_HIDDEN))
socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT);
/* and finally the whole tree */
node_draw_nodetree(sa, snode, ngroup);
}
void drawnodespace(ScrArea *sa, void *spacedata)
{
@@ -992,39 +1258,23 @@ void drawnodespace(ScrArea *sa, void *spacedata)
if(snode->nodetree) {
bNode *node;
bNodeLink *link;
/* for now, we set drawing coordinates on each redraw */
for(node= snode->nodetree->nodes.first; node; node= node->next)
for(node= snode->nodetree->nodes.first; node; node= node->next) {
if(node->flag & NODE_GROUP_EDIT)
node_update_group(node);
else if(node->flag & NODE_HIDDEN)
node_update_hidden(node);
else
node_update(node);
}
/* node lines */
glEnable(GL_BLEND);
glEnable( GL_LINE_SMOOTH );
for(link= snode->nodetree->links.first; link; link= link->next)
node_draw_link(snode, link);
glDisable(GL_BLEND);
glDisable( GL_LINE_SMOOTH );
node_draw_nodetree(sa, snode, snode->nodetree);
/* not selected first */
/* active group */
for(node= snode->nodetree->nodes.first; node; node= node->next) {
node->block= NULL; /* were freed */
if(!(node->flag & SELECT)) {
if(node->flag & NODE_HIDDEN)
node_hidden_draw(snode, node);
else
node_basis_draw(sa, snode, node);
}
}
/* selected */
for(node= snode->nodetree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
if(node->flag & NODE_HIDDEN)
node_hidden_draw(snode, node);
else
node_basis_draw(sa, snode, node);
}
if(node->flag & NODE_GROUP_EDIT)
node_draw_group(sa, snode, node);
}
}

View File

@@ -163,10 +163,10 @@ void node_shader_default(Material *ma)
ma->nodetree= ntreeAddTree(NTREE_SHADER);
out= nodeAddNodeType(ma->nodetree, SH_NODE_OUTPUT);
out= nodeAddNodeType(ma->nodetree, SH_NODE_OUTPUT, NULL);
out->locx= 300.0f; out->locy= 300.0f;
in= nodeAddNodeType(ma->nodetree, SH_NODE_MATERIAL);
in= nodeAddNodeType(ma->nodetree, SH_NODE_MATERIAL, NULL);
in->locx= 10.0f; in->locy= 300.0f;
nodeSetActive(ma->nodetree, in);
@@ -178,10 +178,11 @@ void node_shader_default(Material *ma)
ntreeSolveOrder(ma->nodetree); /* needed for pointers */
}
/* even called for each redraw now, so keep it fast :) */
/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
void snode_set_context(SpaceNode *snode)
{
Object *ob= OBACT;
bNode *node= NULL;
snode->nodetree= NULL;
snode->id= snode->from= NULL;
@@ -197,6 +198,90 @@ void snode_set_context(SpaceNode *snode)
}
}
}
/* find editable group */
if(snode->nodetree)
for(node= snode->nodetree->nodes.first; node; node= node->next)
if(node->flag & NODE_GROUP_EDIT)
break;
if(node && node->id)
snode->edittree= (bNodeTree *)node->id;
else
snode->edittree= snode->nodetree;
}
static bNode *snode_get_editgroup(SpaceNode *snode)
{
bNode *gnode;
/* get the groupnode */
for(gnode= snode->nodetree->nodes.first; gnode; gnode= gnode->next)
if(gnode->flag & NODE_GROUP_EDIT)
break;
return gnode;
}
static void node_make_group_editable(SpaceNode *snode, bNode *gnode)
{
bNode *node;
/* make sure nothing has group editing on */
for(node= snode->nodetree->nodes.first; node; node= node->next)
node->flag &= ~NODE_GROUP_EDIT;
if(gnode==NULL) {
/* with NULL argument we do a toggle */
if(snode->edittree==snode->nodetree)
gnode= nodeGetActive(snode->nodetree);
}
if(gnode && gnode->type==NODE_GROUP && gnode->id) {
gnode->flag |= NODE_GROUP_EDIT;
snode->edittree= (bNodeTree *)gnode->id;
/* deselect all other nodes, so we can also do grabbing of entire subtree */
for(node= snode->nodetree->nodes.first; node; node= node->next)
node->flag &= ~SELECT;
gnode->flag |= SELECT;
}
else
snode->edittree= snode->nodetree;
allqueue(REDRAWNODE, 0);
}
static void node_ungroup(SpaceNode *snode)
{
bNode *gnode;
gnode= nodeGetActive(snode->edittree);
if(gnode->type!=NODE_GROUP)
error("Not a group");
else {
if(nodeGroupUnGroup(snode->edittree, gnode)) {
ntreeSolveOrder(snode->edittree);
BIF_undo_push("Deselect all nodes");
allqueue(REDRAWNODE, 0);
}
else
error("Can't ungroup");
}
}
/* when links in groups change, inputs/outputs change, nodes added/deleted... */
static void snode_verify_groups(SpaceNode *snode)
{
bNode *gnode;
gnode= snode_get_editgroup(snode);
/* does all materials */
if(gnode)
nodeVerifyGroup((bNodeTree *)gnode->id);
}
/* ************************** Node generic ************** */
@@ -260,7 +345,7 @@ static bNode *visible_node(SpaceNode *snode, rctf *rct)
{
bNode *tnode;
for(next_node(snode->nodetree); (tnode=next_node(NULL));) {
for(next_node(snode->edittree); (tnode=next_node(NULL));) {
if(BLI_isect_rctf(&tnode->totr, rct, NULL))
break;
}
@@ -276,7 +361,7 @@ static void snode_home(ScrArea *sa, SpaceNode *snode)
snode->v2d.cur.xmax= sa->winx;
snode->v2d.cur.xmax= sa->winy;
for(node= snode->nodetree->nodes.first; node; node= node->next) {
for(node= snode->edittree->nodes.first; node; node= node->next) {
if(first) {
first= 0;
snode->v2d.cur= node->totr;
@@ -308,9 +393,10 @@ static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **
rect.ymax = rect.ymin + 2*NODE_SOCKSIZE+6;
/* check if we click in a socket */
for(node= snode->nodetree->nodes.first; node; node= node->next) {
for(node= snode->edittree->nodes.first; node; node= node->next) {
if(in_out & SOCK_IN) {
for(sock= node->inputs.first; sock; sock= sock->next) {
if(!(sock->flag & SOCK_HIDDEN)) {
if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
if(node == visible_node(snode, &rect)) {
*nodep= node;
@@ -320,8 +406,10 @@ static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **
}
}
}
}
if(in_out & SOCK_OUT) {
for(sock= node->outputs.first; sock; sock= sock->next) {
if(!(sock->flag & SOCK_HIDDEN)) {
if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
if(node == visible_node(snode, &rect)) {
*nodep= node;
@@ -332,13 +420,15 @@ static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **
}
}
}
}
return 0;
}
/* ********************* transform ****************** */
/* releases on event, only intern (for extern see below) */
static void transform_nodes(SpaceNode *snode, char mode, char *undostr)
/* we need argument ntree to allow operations on edittree or nodetree */
static void transform_nodes(bNodeTree *ntree, char mode, char *undostr)
{
bNode *node;
float mxstart, mystart, mx, my, *oldlocs, *ol;
@@ -346,14 +436,14 @@ static void transform_nodes(SpaceNode *snode, char mode, char *undostr)
short mval[2], mvalo[2];
/* count total */
for(node= snode->nodetree->nodes.first; node; node= node->next)
for(node= ntree->nodes.first; node; node= node->next)
if(node->flag & SELECT) tot++;
if(tot==0) return;
/* store oldlocs */
ol= oldlocs= MEM_mallocN(sizeof(float)*2*tot, "oldlocs transform");
for(node= snode->nodetree->nodes.first; node; node= node->next) {
for(node= ntree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
ol[0]= node->locx; ol[1]= node->locy;
ol+= 2;
@@ -375,7 +465,7 @@ static void transform_nodes(SpaceNode *snode, char mode, char *undostr)
mvalo[0]= mval[0];
mvalo[1]= mval[1];
for(ol= oldlocs, node= snode->nodetree->nodes.first; node; node= node->next) {
for(ol= oldlocs, node= ntree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
node->locx= ol[0] + mx-mxstart;
node->locy= ol[1] + my-mystart;
@@ -416,7 +506,7 @@ static void transform_nodes(SpaceNode *snode, char mode, char *undostr)
}
if(cancel) {
for(ol= oldlocs, node= snode->nodetree->nodes.first; node; node= node->next) {
for(ol= oldlocs, node= ntree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
node->locx= ol[0];
node->locy= ol[1];
@@ -435,7 +525,9 @@ static void transform_nodes(SpaceNode *snode, char mode, char *undostr)
/* external call, also for callback */
void node_transform_ext(int mode, int unused)
{
transform_nodes(curarea->spacedata.first, 'g', "Translate node");
SpaceNode *snode= curarea->spacedata.first;
transform_nodes(snode->edittree, 'g', "Translate node");
}
@@ -519,11 +611,11 @@ void node_deselectall(SpaceNode *snode, int swap)
bNode *node;
if(swap) {
for(node= snode->nodetree->nodes.first; node; node= node->next)
for(node= snode->edittree->nodes.first; node; node= node->next)
if(node->flag & SELECT)
break;
if(node==NULL) {
for(node= snode->nodetree->nodes.first; node; node= node->next)
for(node= snode->edittree->nodes.first; node; node= node->next)
node->flag |= SELECT;
allqueue(REDRAWNODE, 0);
return;
@@ -531,7 +623,7 @@ void node_deselectall(SpaceNode *snode, int swap)
/* else pass on to deselect */
}
for(node= snode->nodetree->nodes.first; node; node= node->next)
for(node= snode->edittree->nodes.first; node; node= node->next)
node->flag &= ~SELECT;
allqueue(REDRAWNODE, 0);
@@ -540,19 +632,81 @@ void node_deselectall(SpaceNode *snode, int swap)
void node_set_active(SpaceNode *snode, bNode *node)
{
nodeSetActive(snode->nodetree, node);
nodeSetActive(snode->edittree, node);
if(node->type!=NODE_GROUP) {
/* tree specific activate calls */
if(snode->treetype==NTREE_SHADER) {
/* when we select a material, active texture is cleared, for buttons */
if(node->id && GS(node->id->name)==ID_MA)
nodeClearActiveID(snode->nodetree, ID_TE);
nodeClearActiveID(snode->edittree, ID_TE);
if(node->id)
BIF_preview_changed(-1); /* temp hack to force texture preview to update */
allqueue(REDRAWBUTSSHADING, 1);
}
}
}
int node_has_hidden_sockets(bNode *node)
{
bNodeSocket *sock;
for(sock= node->inputs.first; sock; sock= sock->next)
if(sock->flag & SOCK_HIDDEN)
return 1;
for(sock= node->outputs.first; sock; sock= sock->next)
if(sock->flag & SOCK_HIDDEN)
return 1;
return 0;
}
static void node_hide_unhide_sockets(SpaceNode *snode, bNode *node)
{
bNodeSocket *sock;
/* unhide all */
if( node_has_hidden_sockets(node) ) {
for(sock= node->inputs.first; sock; sock= sock->next)
sock->flag &= ~SOCK_HIDDEN;
for(sock= node->outputs.first; sock; sock= sock->next)
sock->flag &= ~SOCK_HIDDEN;
}
else {
bNode *gnode= snode_get_editgroup(snode);
/* hiding inside group should not break links in other group users */
if(gnode) {
nodeGroupSocketUseFlags((bNodeTree *)gnode->id);
for(sock= node->inputs.first; sock; sock= sock->next)
if(!(sock->flag & SOCK_IN_USE))
if(sock->link==NULL)
sock->flag |= SOCK_HIDDEN;
for(sock= node->outputs.first; sock; sock= sock->next)
if(!(sock->flag & SOCK_IN_USE))
if(nodeCountSocketLinks(snode->edittree, sock)==0)
sock->flag |= SOCK_HIDDEN;
}
else {
/* hide unused sockets */
for(sock= node->inputs.first; sock; sock= sock->next) {
if(sock->link==NULL)
sock->flag |= SOCK_HIDDEN;
}
for(sock= node->outputs.first; sock; sock= sock->next) {
if(nodeCountSocketLinks(snode->edittree, sock)==0)
sock->flag |= SOCK_HIDDEN;
}
}
}
allqueue(REDRAWNODE, 1);
snode_verify_groups(snode);
BIF_undo_push("Hide/Unhide sockets");
}
static int do_header_node(SpaceNode *snode, bNode *node, float mx, float my)
@@ -578,13 +732,27 @@ static int do_header_node(SpaceNode *snode, bNode *node, float mx, float my)
}
totr.xmin-=18.0f;
}
if(node->type == NODE_GROUP) {
if(BLI_in_rctf(&totr, mx, my)) {
node_make_group_editable(snode, node);
return 1;
}
totr.xmin-=18.0f;
}
if(node->typeinfo->flag & NODE_OPTIONS) {
if(BLI_in_rctf(&totr, mx, my)) {
node->flag ^= NODE_OPTIONS;
allqueue(REDRAWNODE, 0);
return 1;
}
totr.xmin-=18.0f;
}
if(node->outputs.first) {
if(BLI_in_rctf(&totr, mx, my)) {
node_hide_unhide_sockets(snode, node);
}
}
totr= node->totr;
totr.xmin= totr.xmax-10.0f;
@@ -627,7 +795,7 @@ static int node_mouse_select(SpaceNode *snode, unsigned short event)
getmouseco_areawin(mval);
areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
for(next_node(snode->nodetree); (node=next_node(NULL));) {
for(next_node(snode->edittree); (node=next_node(NULL));) {
/* first check for the headers or scaling widget */
if(node->flag & NODE_HIDDEN) {
@@ -668,6 +836,34 @@ static int node_mouse_select(SpaceNode *snode, unsigned short event)
return 0;
}
/* return 0, nothing done */
static int node_mouse_groupheader(SpaceNode *snode)
{
bNode *gnode;
float mx, my;
short mval[2];
gnode= snode_get_editgroup(snode);
if(gnode==NULL) return 0;
getmouseco_areawin(mval);
areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
/* click in header or outside? */
if(BLI_in_rctf(&gnode->totr, mx, my)==0) {
rctf rect= gnode->totr;
rect.ymax += NODE_DY;
if(BLI_in_rctf(&rect, mx, my)==0)
node_make_group_editable(snode, NULL); /* toggles, so exits editmode */
else
transform_nodes(snode->nodetree, 'g', "Move group");
return 1;
}
return 0;
}
static int node_socket_hilights(SpaceNode *snode, int in_out)
{
bNode *node;
@@ -675,13 +871,13 @@ static int node_socket_hilights(SpaceNode *snode, int in_out)
float mx, my;
short mval[2], redraw= 0;
if(snode->nodetree==NULL) return 0;
if(snode->edittree==NULL) return 0;
getmouseco_areawin(mval);
areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
/* deselect socks */
for(node= snode->nodetree->nodes.first; node; node= node->next) {
for(node= snode->edittree->nodes.first; node; node= node->next) {
for(sock= node->inputs.first; sock; sock= sock->next) {
if(sock->flag & SELECT) {
sock->flag &= ~SELECT;
@@ -723,7 +919,7 @@ void node_border_select(SpaceNode *snode)
mval[1]= rect.ymax;
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
for(node= snode->nodetree->nodes.first; node; node= node->next) {
for(node= snode->edittree->nodes.first; node; node= node->next) {
if(BLI_isect_rctf(&rectf, &node->totr, NULL)) {
if(val==LEFTMOUSE)
node->flag |= SELECT;
@@ -741,19 +937,26 @@ void node_border_select(SpaceNode *snode)
/* can be called from menus too, but they should do own undopush and redraws */
bNode *node_add_shadernode(SpaceNode *snode, int type, float locx, float locy)
{
bNode *node= NULL;
bNode *node= NULL, *gnode;
node_deselectall(snode, 0);
node= nodeAddNodeType(snode->nodetree, type);
node= nodeAddNodeType(snode->edittree, type, NULL);
/* generics */
if(node) {
node->locx= locx;
node->locy= locy;
node->locy= locy + 60.0f; // arbitrary.. so its visible
node->flag |= SELECT;
gnode= snode_get_editgroup(snode);
if(gnode) {
node->locx -= gnode->locx;
node->locy -= gnode->locy;
}
node_set_active(snode, node);
snode_verify_groups(snode);
}
return node;
}
@@ -770,7 +973,7 @@ static void node_add_menu(SpaceNode *snode)
getmouseco_areawin(mval);
areamouseco_to_ipoco(G.v2d, mval, &locx, &locy);
node_add_shadernode(snode, event, locx, locy+40.0f);
node_add_shadernode(snode, event, locx, locy);
snode_handle_recalc(snode);
@@ -780,18 +983,20 @@ static void node_add_menu(SpaceNode *snode)
void node_adduplicate(SpaceNode *snode)
{
ntreeCopyTree(snode->nodetree, 1); /* 1 == internally selected nodes */
ntreeSolveOrder(snode->nodetree);
ntreeCopyTree(snode->edittree, 1); /* 1 == internally selected nodes */
ntreeSolveOrder(snode->edittree);
snode_verify_groups(snode);
snode_handle_recalc(snode);
transform_nodes(snode, 'g', "Duplicate");
transform_nodes(snode->edittree, 'g', "Duplicate");
}
static void node_insert_convertor(SpaceNode *snode, bNodeLink *link)
{
bNode *newnode= NULL;
if(snode->nodetree->type==NTREE_SHADER) {
if(snode->edittree->type==NTREE_SHADER) {
if(link->fromsock->type==SOCK_RGBA && link->tosock->type==SOCK_VALUE) {
newnode= node_add_shadernode(snode, SH_NODE_RGBTOBW, 0.0f, 0.0f);
}
@@ -805,7 +1010,7 @@ static void node_insert_convertor(SpaceNode *snode, bNodeLink *link)
newnode->locx= 0.5f*(link->fromsock->locx + link->tosock->locx);
newnode->locy= 0.5f*(link->fromsock->locy + link->tosock->locy) + HIDDEN_RAD;
nodeAddLink(snode->nodetree, newnode, newnode->outputs.first, link->tonode, link->tosock);
nodeAddLink(snode->edittree, newnode, newnode->outputs.first, link->tonode, link->tosock);
link->tonode= newnode;
link->tosock= newnode->inputs.first;
}
@@ -824,9 +1029,9 @@ static int node_add_link_drag(SpaceNode *snode, bNode *node, bNodeSocket *sock,
/* we make a temporal link */
if(in_out==SOCK_OUT)
link= nodeAddLink(snode->nodetree, node, sock, NULL, NULL);
link= nodeAddLink(snode->edittree, node, sock, NULL, NULL);
else
link= nodeAddLink(snode->nodetree, NULL, NULL, node, sock);
link= nodeAddLink(snode->edittree, NULL, NULL, node, sock);
getmouseco_areawin(mvalo);
while (get_mbut() & L_MOUSE) {
@@ -840,11 +1045,11 @@ static int node_add_link_drag(SpaceNode *snode, bNode *node, bNodeSocket *sock,
if(in_out==SOCK_OUT) {
if(find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
if(nodeFindLink(snode->nodetree, sock, tsock)==NULL) {
if(nodeFindLink(snode->edittree, sock, tsock)==NULL) {
if(tnode!=node && link->tonode!=tnode && link->tosock!= tsock) {
link->tonode= tnode;
link->tosock= tsock;
ntreeSolveOrder(snode->nodetree); /* for interactive red line warning */
ntreeSolveOrder(snode->edittree); /* for interactive red line warning */
}
}
}
@@ -855,12 +1060,12 @@ static int node_add_link_drag(SpaceNode *snode, bNode *node, bNodeSocket *sock,
}
else {
if(find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
if(nodeFindLink(snode->nodetree, sock, tsock)==NULL) {
if(nodeCountSocketLinks(snode->nodetree, tsock) < tsock->limit) {
if(nodeFindLink(snode->edittree, sock, tsock)==NULL) {
if(nodeCountSocketLinks(snode->edittree, tsock) < tsock->limit) {
if(tnode!=node && link->fromnode!=tnode && link->fromsock!= tsock) {
link->fromnode= tnode;
link->fromsock= tsock;
ntreeSolveOrder(snode->nodetree); /* for interactive red line warning */
ntreeSolveOrder(snode->edittree); /* for interactive red line warning */
}
}
}
@@ -879,29 +1084,29 @@ static int node_add_link_drag(SpaceNode *snode, bNode *node, bNodeSocket *sock,
}
if(link->tonode==NULL || link->fromnode==NULL) {
nodeRemLink(snode->nodetree, link);
nodeRemLink(snode->edittree, link);
}
else {
bNodeLink *tlink;
/* we might need to remove a link */
if(in_out==SOCK_OUT) {
if(nodeCountSocketLinks(snode->nodetree, link->tosock) > tsock->limit) {
if(nodeCountSocketLinks(snode->edittree, link->tosock) > tsock->limit) {
for(tlink= snode->nodetree->links.first; tlink; tlink= tlink->next) {
for(tlink= snode->edittree->links.first; tlink; tlink= tlink->next) {
if(link!=tlink && tlink->tosock==link->tosock)
break;
}
if(tlink) {
/* is there a free input socket with same type? */
for(tsock= tlink->tonode->inputs.first; tsock; tsock= tsock->next) {
if(tsock->type==sock->type)
if(nodeCountSocketLinks(snode->nodetree, tsock) < tsock->limit)
if(tsock->type==tlink->fromsock->type)
if(nodeCountSocketLinks(snode->edittree, tsock) < tsock->limit)
break;
}
if(tsock)
tlink->tosock= tsock;
else {
nodeRemLink(snode->nodetree, tlink);
nodeRemLink(snode->edittree, tlink);
}
}
}
@@ -910,12 +1115,14 @@ static int node_add_link_drag(SpaceNode *snode, bNode *node, bNodeSocket *sock,
/* and last trick: insert a convertor when types dont match */
if(link->tosock->type!=link->fromsock->type) {
node_insert_convertor(snode, link);
ntreeSolveOrder(snode->nodetree); /* so nice do it twice! well, the sort-order can only handle 1 added link at a time */
ntreeSolveOrder(snode->edittree); /* so nice do it twice! well, the sort-order can only handle 1 added link at a time */
}
}
ntreeSolveOrder(snode->nodetree);
ntreeSolveOrder(snode->edittree);
snode_verify_groups(snode);
snode_handle_recalc(snode);
allqueue(REDRAWNODE, 0);
BIF_undo_push("Add link");
@@ -931,36 +1138,36 @@ static int node_add_link(SpaceNode *snode)
/* output indicated? */
if(find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
if(nodeCountSocketLinks(snode->nodetree, sock)<sock->limit)
if(nodeCountSocketLinks(snode->edittree, sock)<sock->limit)
return node_add_link_drag(snode, node, sock, SOCK_OUT);
else {
/* find if we break a link */
for(link= snode->nodetree->links.first; link; link= link->next) {
for(link= snode->edittree->links.first; link; link= link->next) {
if(link->fromsock==sock)
break;
}
if(link) {
node= link->tonode;
sock= link->tosock;
nodeRemLink(snode->nodetree, link);
nodeRemLink(snode->edittree, link);
return node_add_link_drag(snode, node, sock, SOCK_IN);
}
}
}
/* or an input? */
else if(find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
if(nodeCountSocketLinks(snode->nodetree, sock)<sock->limit)
if(nodeCountSocketLinks(snode->edittree, sock)<sock->limit)
return node_add_link_drag(snode, node, sock, SOCK_IN);
else {
/* find if we break a link */
for(link= snode->nodetree->links.first; link; link= link->next) {
for(link= snode->edittree->links.first; link; link= link->next) {
if(link->tosock==sock)
break;
}
if(link) {
node= link->fromnode;
sock= link->fromsock;
nodeRemLink(snode->nodetree, link);
nodeRemLink(snode->edittree, link);
return node_add_link_drag(snode, node, sock, SOCK_OUT);
}
}
@@ -973,12 +1180,13 @@ static void node_delete(SpaceNode *snode)
{
bNode *node, *next;
for(node= snode->nodetree->nodes.first; node; node= next) {
for(node= snode->edittree->nodes.first; node; node= next) {
next= node->next;
if(node->flag & SELECT)
nodeFreeNode(snode->nodetree, node);
nodeFreeNode(snode->edittree, node);
}
snode_verify_groups(snode);
snode_handle_recalc(snode);
BIF_undo_push("Delete nodes");
allqueue(REDRAWNODE, 1);
@@ -989,7 +1197,7 @@ static void node_hide(SpaceNode *snode)
bNode *node;
int nothidden=0, ishidden=0;
for(node= snode->nodetree->nodes.first; node; node= node->next) {
for(node= snode->edittree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
if(node->flag & NODE_HIDDEN)
ishidden++;
@@ -997,7 +1205,7 @@ static void node_hide(SpaceNode *snode)
nothidden++;
}
}
for(node= snode->nodetree->nodes.first; node; node= node->next) {
for(node= snode->edittree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
if( (ishidden && nothidden) || ishidden==0)
node->flag |= NODE_HIDDEN;
@@ -1013,8 +1221,20 @@ static void node_hide(SpaceNode *snode)
static void node_border_link_delete(SpaceNode *snode)
{
rcti rect;
short val, mval[2];
short val, mval[2], mvalo[2];
/* to make this work more friendly, we first wait for a mouse move */
getmouseco_areawin(mvalo);
while (get_mbut() & L_MOUSE) {
getmouseco_areawin(mval);
if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1])
break;
else BIF_wait_for_statechange();
}
if((get_mbut() & L_MOUSE)==0)
return;
/* now change cursor and draw border */
setcursor_space(SPACE_NODE, CURSOR_VPAINT);
if ( (val = get_border(&rect, 2)) ) {
@@ -1040,7 +1260,7 @@ static void node_border_link_delete(SpaceNode *snode)
glPushName(-1);
/* draw links */
for(link= snode->nodetree->links.first; link; link= link->next) {
for(link= snode->edittree->links.first; link; link= link->next) {
glLoadName(code++);
node_draw_link(snode, link);
}
@@ -1050,17 +1270,18 @@ static void node_border_link_delete(SpaceNode *snode)
if(hits>0) {
int a;
for(a=0; a<hits; a++) {
bNodeLink *link= BLI_findlink(&snode->nodetree->links, buffer[ (4 * a) + 3]);
bNodeLink *link= BLI_findlink(&snode->edittree->links, buffer[ (4 * a) + 3]);
if(link)
link->tonode= NULL; /* first tag for delete, otherwise indices are wrong */
}
for(link= snode->nodetree->links.first; link; link= next) {
for(link= snode->edittree->links.first; link; link= next) {
next= link->next;
if(link->tonode==NULL) {
nodeRemLink(snode->nodetree, link);
nodeRemLink(snode->edittree, link);
}
}
ntreeSolveOrder(snode->nodetree);
ntreeSolveOrder(snode->edittree);
snode_verify_groups(snode);
snode_handle_recalc(snode);
}
allqueue(REDRAWNODE, 0);
@@ -1069,8 +1290,9 @@ static void node_border_link_delete(SpaceNode *snode)
}
setcursor_space(SPACE_NODE, CURSOR_STD);
}
/* ********************** */
static void convert_nodes(SpaceNode *snode)
@@ -1087,12 +1309,12 @@ static void convert_nodes(SpaceNode *snode)
for(ml= mat->layers.first; ml; ml= ml->next) {
if(ml->mat) {
node= nodeAddNodeType(snode->nodetree, SH_NODE_MATERIAL);
node= nodeAddNodeType(snode->nodetree, SH_NODE_MATERIAL, NULL);
node->id= (ID *)ml->mat;
node->locx= locx; locx+= 100;
node->locy= 300;
bnode= nodeAddNodeType(snode->nodetree, SH_NODE_MIX_RGB);
bnode= nodeAddNodeType(snode->nodetree, SH_NODE_MIX_RGB, NULL);
bnode->custom1= ml->blendmethod;
bnode->locx= locx; locx+= 100;
bnode->locy= 200;
@@ -1119,6 +1341,26 @@ static void convert_nodes(SpaceNode *snode)
allqueue(REDRAWNODE, 0);
}
void node_make_group(SpaceNode *snode)
{
bNode *gnode;
if(snode->edittree!=snode->nodetree) {
error("Can not add a new Group in a Group");
return;
}
gnode= nodeMakeGroupFromSelected(snode->nodetree);
if(gnode==NULL) {
error("Can not make Group");
}
else {
nodeSetActive(snode->nodetree, gnode);
ntreeSolveOrder(snode->nodetree);
allqueue(REDRAWNODE, 0);
BIF_undo_push("Make Node Group");
}
}
/* ******************** main event loop ****************** */
@@ -1139,7 +1381,7 @@ int node_uiDoBlocks(SpaceNode *snode, ListBase *lb, short event)
rect.xmax = rect.xmin + 4.0f;
rect.ymax = rect.ymin + 4.0f;
for(node= snode->nodetree->nodes.first; node; node= node->next) {
for(node= snode->edittree->nodes.first; node; node= node->next) {
if(node->block) {
if(node == visible_node(snode, &rect)) {
@@ -1171,6 +1413,7 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
switch(event) {
case LEFTMOUSE:
if(node_add_link(snode)==0)
if(node_mouse_groupheader(snode)==0)
if(node_mouse_select(snode, event)==0)
node_border_link_delete(snode);
break;
@@ -1217,6 +1460,9 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
snode_home(sa, snode);
doredraw= 1;
break;
case TABKEY:
node_make_group_editable(snode, NULL);
break;
case AKEY:
if(G.qual==LR_SHIFTKEY)
@@ -1233,7 +1479,7 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
case CKEY: /* sort again, showing cyclics */
if(G.qual==LR_ALTKEY)
convert_nodes(snode); /* temporal for layers */
ntreeSolveOrder(snode->nodetree);
ntreeSolveOrder(snode->edittree);
doredraw= 1;
break;
case DKEY:
@@ -1241,7 +1487,16 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
node_adduplicate(snode);
break;
case GKEY:
transform_nodes(snode, 'g', "Translate Node");
if(G.qual==LR_CTRLKEY) {
if(okee("Make Group"))
node_make_group(snode);
}
else if(G.qual==LR_ALTKEY) {
if(okee("Ungroup"))
node_ungroup(snode);
}
else
transform_nodes(snode->edittree, 'g', "Translate Node");
break;
case HKEY:
node_hide(snode);

View File

@@ -2447,7 +2447,7 @@ void main_to_filelist(SpaceFile *sfile)
if( sfile->dir[0]==0) {
/* make directories */
sfile->totfile= 22;
sfile->totfile= 23;
sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
for(a=0; a<sfile->totfile; a++) {
@@ -2477,6 +2477,8 @@ void main_to_filelist(SpaceFile *sfile)
sfile->filelist[19].relname= BLI_strdup("Text");
sfile->filelist[20].relname= BLI_strdup("Armature");
sfile->filelist[21].relname= BLI_strdup("Action");
sfile->filelist[22].relname= BLI_strdup("NodeTree");
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
}
else {

View File

@@ -209,7 +209,7 @@ static int ray_previewrender(int x, int y, float *vec, float *vn, short pr_rec
if(hitface > -1) {
CalcNormFloat(rcubev[rcubi[hitface][0]], rcubev[rcubi[hitface][1]], rcubev[rcubi[hitface][2]], vn);
CalcNormFloat(rcubev[rcubi[hitface][2]], rcubev[rcubi[hitface][1]], rcubev[rcubi[hitface][0]], vn);
vec[0]= (minlabda*(ray1[0]-ray2[0])+ray2[0])/4.1;
vec[1]= (minlabda*(ray1[1]-ray2[1])+ray2[1])/4.1;
@@ -807,7 +807,7 @@ static void texture_preview_pixel(Tex *tex, int x, int y, char *rect, short pr_r
}
}
static float pr1_lamp[3]= {2.3, -2.4, -4.6};
static float pr1_lamp[3]= {2.3, -2.4, -4.6}; /* note; is not used! */
static float pr2_lamp[3]= {-8.8, -5.6, -1.5};
static float pr1_col[3]= {0.8, 0.8, 0.8};
static float pr2_col[3]= {0.5, 0.6, 0.7};
@@ -857,14 +857,8 @@ static void shade_lamp_loop_preview(ShadeInput *shi, ShadeResult *shr)
if((mat->mode & MA_RAYMIRROR)==0) shi->ray_mirror= 0.0f;
memset(shr, 0, sizeof(ShadeResult));
/* normals flipped in render for smooth... */
if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0f);
do_material_tex(shi);
/* normals flipped in render... */
if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0f);
shr->alpha= shi->alpha;
if(mat->mode & (MA_ZTRA|MA_RAYTRANSP))
@@ -885,8 +879,8 @@ static void shade_lamp_loop_preview(ShadeInput *shi, ShadeResult *shr)
shi->ref[1]= (shi->view[1]+inp*shi->vn[1]);
shi->ref[2]= (shi->view[2]+inp*shi->vn[2]);
/* normals in render are pointing different... rhm */
if(shi->pr_type==MA_SPHERE)
shi->ref[1]= -shi->ref[1];
// if(shi->pr_type==MA_SPHERE)
// shi->ref[1]= -shi->ref[1];
}
for(a=0; a<2; a++) {
@@ -1036,10 +1030,10 @@ static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y, char
mat= shi->mat;
v1= 1.0/pr_rectx;
v1= 0.5/pr_rectx;
shi->view[0]= v1*x;
shi->view[1]= v1*y;
shi->view[2]= 1.0f;
shi->view[2]= -1.0f;
Normalise(shi->view);
shi->xs= x + pr_rectx/2;
@@ -1088,9 +1082,9 @@ static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y, char
/* nothing */
}
if(mat->texco & (TEXCO_NORM)) {
shi->orn[0]= shi->vn[0];
shi->orn[1]= shi->vn[1];
shi->orn[2]= shi->vn[2];
//shi->orn[0]= shi->vn[0];
//shi->orn[1]= shi->vn[1];
//shi->orn[2]= shi->vn[2];
}
/* Clear displase vec for preview */
@@ -1237,38 +1231,29 @@ void BIF_previewrender(struct ID *id, struct RenderInfo *ri, struct ScrArea *are
shi.osatex= 0;
if(mat) {
MaterialLayer *ml;
/* rendervars */
init_render_world();
init_render_material(mat);
init_render_material(mat); /* does nodes too */
/* also clears imats */
preview_init_render_textures(mat->mtex);
for(ml= mat->layers.first; ml; ml= ml->next) {
if(ml->mat && (ml->flag & ML_RENDER)) {
init_render_material(ml->mat);
preview_init_render_textures(ml->mat->mtex);
mat->texco |= ml->mat->texco;
}
}
/* do the textures for nodes */
if(mat->nodetree && mat->use_nodes) {
bNode *node;
for(node=mat->nodetree->nodes.first; node; node= node->next) {
if(node->id && GS(node->id->name)==ID_MA) {
Material *ma= (Material *)node->id;
init_render_material(ma);
preview_init_render_textures(ma->mtex);
mat->texco |= ma->texco;
}
}
/* signal to node editor to store previews or not */
if(pr_method==PR_ICON_RENDER) {
ntreeBeginExecTree(mat->nodetree, 0, 0);
shi.do_preview= 0;
}
else {
ntreeBeginExecTree(mat->nodetree, ri->pr_rectx, ri->pr_recty);
ntreeInitPreview(mat->nodetree, ri->pr_rectx, ri->pr_recty);
shi.do_preview= 1;
}
}
@@ -1341,14 +1326,8 @@ void BIF_previewrender(struct ID *id, struct RenderInfo *ri, struct ScrArea *are
radsq= (ri->pr_rectx/2)*(ri->pr_recty/2);
if(mat) {
if(mat->pr_type==MA_SPHERE) {
pr1_lamp[0]= 2.3; pr1_lamp[1]= -2.4; pr1_lamp[2]= -4.6;
pr2_lamp[0]= -8.8; pr2_lamp[1]= -5.6; pr2_lamp[2]= -1.5;
}
else {
pr1_lamp[0]= 1.9; pr1_lamp[1]= 3.1; pr1_lamp[2]= -8.5;
pr2_lamp[0]= 1.2; pr2_lamp[1]= -18; pr2_lamp[2]= 3.2;
}
pr1_lamp[0]= -2.3; pr1_lamp[1]= 2.4; pr1_lamp[2]= 4.6;
pr2_lamp[0]= 8.8; pr2_lamp[1]= 5.6; pr2_lamp[2]= 1.5;
}
if (pr_method==PR_DRAW_RENDER)
@@ -1380,14 +1359,14 @@ void BIF_previewrender(struct ID *id, struct RenderInfo *ri, struct ScrArea *are
if(mat->pr_type==MA_SPHERE) {
if(xsq+ysq <= radsq) {
shi.vn[0]= x;
shi.vn[1]= y;
shi.vn[2]= sqrt( (float)(radsq-xsq-ysq) );
shi.vn[0]= -x;
shi.vn[1]= -y;
shi.vn[2]= -sqrt( (float)(radsq-xsq-ysq) );
Normalise(shi.vn);
vec[0]= shi.vn[0];
vec[1]= shi.vn[2];
vec[2]= -shi.vn[1];
vec[1]= shi.vn[1];
vec[2]= -shi.vn[2];
if(mat->mode & MA_TANGENT_V) {
float tmp[3];
@@ -1424,7 +1403,7 @@ void BIF_previewrender(struct ID *id, struct RenderInfo *ri, struct ScrArea *are
vec[2]= 0.0;
shi.vn[0]= shi.vn[1]= 0.0f;
shi.vn[2]= 1.0f;
shi.vn[2]= -1.0f;
shade_preview_pixel(&shi, vec, x, y, (char *)rect, ri->pr_rectx, ri->pr_recty);
}
@@ -1482,8 +1461,10 @@ void BIF_previewrender(struct ID *id, struct RenderInfo *ri, struct ScrArea *are
*/
}
if(mat && mat->nodetree && mat->use_nodes) {
ntreeEndExecTree(mat->nodetree);
if(mat) {
end_render_material(mat);
if(mat->nodetree && mat->use_nodes)
if(ri->cury>=ri->pr_recty)
allqueue(REDRAWNODE, 0);
}

View File

@@ -283,7 +283,7 @@ char *BIF_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp= ts->syntaxb; break;
case TH_NODE_GENERATOR:
cp= ts->syntaxv; break;
case TH_NODE_FREE:
case TH_NODE_GROUP:
cp= ts->syntaxc; break;
}
@@ -484,7 +484,7 @@ void BIF_InitTheme(void)
SETCOL(btheme->tnode.syntaxn, 95, 110, 145, 255); /* in/output */
SETCOL(btheme->tnode.syntaxb, 135, 125, 120, 255); /* operator */
SETCOL(btheme->tnode.syntaxv, 120, 120, 120, 255); /* generator */
SETCOL(btheme->tnode.syntaxc, 120, 120, 120, 255); /* free */
SETCOL(btheme->tnode.syntaxc, 120, 145, 120, 255); /* group */
}
@@ -619,7 +619,7 @@ char *BIF_ThemeColorsPup(int spacetype)
sprintf(str, "In/Out Node %%x%d|", TH_NODE_IN_OUT); strcat(cp, str);
sprintf(str, "Generator Node %%x%d|", TH_NODE_GENERATOR); strcat(cp, str);
sprintf(str, "Operator Node %%x%d|", TH_NODE_OPERATOR); strcat(cp, str);
// sprintf(str, " %%x%d|", TH_NODE_FREE); strcat(cp, str);
sprintf(str, "Group Node %%x%d|", TH_NODE_GROUP); strcat(cp, str);
}
}
return cp;

View File

@@ -799,6 +799,8 @@ int blenderqread(unsigned short event, short val)
set_editflag_editipo();
else if(curarea->spacetype==SPACE_SEQ)
enter_meta();
else if(curarea->spacetype==SPACE_NODE)
return 1;
else if(G.vd) {
/* also when Alt-E */
if(G.obedit==NULL) {

View File

@@ -279,7 +279,7 @@ static void init_userdef_file(void)
SETCOL(btheme->tnode.syntaxn, 95, 110, 145, 255); /* in/output */
SETCOL(btheme->tnode.syntaxb, 135, 125, 120, 255); /* operator */
SETCOL(btheme->tnode.syntaxv, 120, 120, 120, 255); /* generator */
SETCOL(btheme->tnode.syntaxc, 120, 120, 120, 255); /* free */
SETCOL(btheme->tnode.syntaxc, 120, 145, 120, 255); /* group */
}
}
}