Render API: shader script node for custom shaders.

* Shader script node added, which stores either a link to a text datablock or
  file on disk, and has functions to add and remove sockets.
* Callback RenderEngine.update_script_node(self, node) added for render engines
  to compile the shader and update the node with new sockets.

Thanks to Thomas, Lukas and Dalai for the implementation.
This commit is contained in:
2012-11-03 14:32:26 +00:00
parent 615fe0295f
commit e02b23b81a
22 changed files with 572 additions and 17 deletions

View File

@@ -56,12 +56,17 @@ class TEXT_HT_header(Header):
row.prop(st, "show_syntax_highlight", text="")
if text:
row = layout.row()
row.operator("text.run_script")
osl = text.name.endswith(".osl") or text.name.endswith(".oso")
row = layout.row()
row.active = text.name.endswith(".py")
row.prop(text, "use_module")
if osl:
row = layout.row()
row.operator("node.shader_script_update")
else:
row = layout.row()
row.operator("text.run_script")
row = layout.row()
row.prop(text, "use_module")
row = layout.row()
if text.filepath:

View File

@@ -245,6 +245,7 @@ typedef struct bNodeType {
#define NODE_CLASS_PARTICLES 25
#define NODE_CLASS_TRANSFORM 30
#define NODE_CLASS_COMBINE 31
#define NODE_CLASS_SCRIPT 32
#define NODE_CLASS_SHADER 40
#define NODE_CLASS_LAYOUT 100
@@ -551,6 +552,7 @@ struct ShadeResult;
#define SH_NODE_PARTICLE_INFO 168
#define SH_NODE_TEX_BRICK 169
#define SH_NODE_BUMP 170
#define SH_NODE_SCRIPT 171
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1

View File

@@ -2288,6 +2288,7 @@ static void registerShaderNodes(bNodeTreeType *ttype)
register_node_type_sh_tex_coord(ttype);
register_node_type_sh_particle_info(ttype);
register_node_type_sh_bump(ttype);
register_node_type_sh_script(ttype);
register_node_type_sh_background(ttype);
register_node_type_sh_bsdf_anisotropic(ttype);

View File

@@ -55,12 +55,15 @@
#include "DNA_text_types.h"
#include "DNA_userdef_types.h"
#include "DNA_object_types.h"
#include "DNA_node_types.h"
#include "DNA_material_types.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_text.h"
#include "BKE_node.h"
#ifdef WITH_PYTHON
@@ -531,6 +534,9 @@ void BKE_text_unlink(Main *bmain, Text *text)
bController *cont;
bActuator *act;
bConstraint *con;
bNodeTree *ntree;
bNode *node;
Material *mat;
short update;
for (ob = bmain->object.first; ob; ob = ob->id.next) {
@@ -582,6 +588,26 @@ void BKE_text_unlink(Main *bmain, Text *text)
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
/* nodes */
for (mat = bmain->mat.first; mat; mat = mat->id.next) {
ntree = mat->nodetree;
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_SCRIPT) {
Text *ntext = (Text *)node->id;
if (ntext == text) node->id = NULL;
}
}
}
for (ntree = bmain->nodetree.first; ntree; ntree = ntree->id.next) {
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_SCRIPT) {
Text *ntext = (Text *)node->id;
if (ntext == text) node->id = NULL;
}
}
}
/* text space */
for (scr = bmain->screen.first; scr; scr = scr->id.next) {
for (area = scr->areabase.first; area; area = area->next) {

View File

@@ -2429,8 +2429,18 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
if (node->storage) {
/* could be handlerized at some point */
if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
direct_link_curvemapping(fd, node->storage);
if (ntree->type==NTREE_SHADER) {
if (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB) {
direct_link_curvemapping(fd, node->storage);
}
else if (node->type==SH_NODE_SCRIPT) {
NodeShaderScript *nss = (NodeShaderScript *) node->storage;
nss->bytecode = newdataadr(fd, nss->bytecode);
nss->prop = newdataadr(fd, nss->prop);
if (nss->prop)
IDP_DirectLinkProperty(nss->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
}
else if (ntree->type==NTREE_COMPOSIT) {
if (ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
direct_link_curvemapping(fd, node->storage);

View File

@@ -728,6 +728,16 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
/* could be handlerized at some point, now only 1 exception still */
if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
write_curvemapping(wd, node->storage);
else if (ntree->type==NTREE_SHADER && node->type==SH_NODE_SCRIPT) {
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
if (nss->bytecode)
writedata(wd, DATA, strlen(nss->bytecode)+1, nss->bytecode);
/* Write ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
if (nss->prop)
IDP_WriteProperty(nss->prop, wd);
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
else if (ntree->type==NTREE_COMPOSIT && ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
write_curvemapping(wd, node->storage);
else if (ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) )

View File

@@ -1384,6 +1384,34 @@ static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), Point
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
}
static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *row;
row = uiLayoutRow(layout, FALSE);
uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
row = uiLayoutRow(layout, TRUE);
if(RNA_enum_get(ptr, "mode") == NODE_SCRIPT_INTERNAL)
uiItemR(row, ptr, "script", 0, "", ICON_NONE);
else
uiItemR(row, ptr, "filepath", 0,"", ICON_NONE);
uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update");
}
static void node_shader_buts_script_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
uiItemS(layout);
node_shader_buts_script(layout, C, ptr);
/* not implemented yet
if(RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL)
uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE);*/
}
/* only once called */
static void node_shader_set_butfunc(bNodeType *ntype)
{
@@ -1467,6 +1495,10 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_BSDF_GLASS:
ntype->uifunc = node_shader_buts_glossy;
break;
case SH_NODE_SCRIPT:
ntype->uifunc = node_shader_buts_script;
ntype->uifuncbut = node_shader_buts_script_details;
break;
}
}

View File

@@ -35,6 +35,7 @@
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_text_types.h"
#include "DNA_world_types.h"
#include "BLI_math.h"
@@ -54,6 +55,7 @@
#include "BKE_scene.h"
#include "BKE_texture.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -2137,3 +2139,119 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************** Shader Script Update ******************/
typedef struct ScriptUpdateData {
RenderEngine *engine;
RenderEngineType *type;
Text *text;
int found;
} ScriptUpdateData;
static int node_shader_script_update_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
RenderEngineType *type = RE_engines_find(scene->r.engine);
bNode *node;
Text *text;
/* test if we have a render engine that supports shaders scripts */
if(!(type && type->update_script_node))
return 0;
/* see if we have a shader script node in context */
node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data;
if(node && node->type == SH_NODE_SCRIPT) {
NodeShaderScript *nss = node->storage;
if(node->id || nss->filepath[0])
return 1;
}
/* see if we have a text datablock in context */
text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
if(text)
return 1;
/* we don't check if text datablock is actually in use, too slow for poll */
return 0;
}
static void node_shader_script_update_text(void *data_, ID *UNUSED(id), bNodeTree *ntree)
{
ScriptUpdateData *data = (ScriptUpdateData *)data_;
bNode *node;
/* update each script that is using this text datablock */
for (node=ntree->nodes.first; node; node=node->next) {
if (node->type == NODE_GROUP){
node_shader_script_update_text(data_, NULL, (bNodeTree *)node->id);
}
else if (node->type == SH_NODE_SCRIPT && node->id == &data->text->id) {
data->type->update_script_node(data->engine, ntree, node);
data->found = TRUE;
}
}
}
static int node_shader_script_update_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ScriptUpdateData data;
PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript);
/* setup render engine */
data.type = RE_engines_find(scene->r.engine);
data.engine = RE_engine_create(data.type);
data.engine->reports = op->reports;
data.text = NULL;
data.found = FALSE;
if (nodeptr.data) {
/* update single node */
bNodeTree *ntree = nodeptr.id.data;
bNode *node = nodeptr.data;
data.type->update_script_node(data.engine, ntree, node);
data.found = TRUE;
}
else {
/* update all nodes using text datablock */
data.text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
if (data.text) {
bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
if (ntreetype && ntreetype->foreach_nodetree)
ntreetype->foreach_nodetree(bmain, &data, node_shader_script_update_text);
if (!data.found)
BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done.");
}
}
RE_engine_free(data.engine);
return (data.found)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
}
void NODE_OT_shader_script_update(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Script Node Update";
ot->description = "Update shader script node with new sockets and options from the script";
ot->idname = "NODE_OT_shader_script_update";
/* api callbacks */
ot->exec = node_shader_script_update_exec;
ot->poll = node_shader_script_update_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}

View File

@@ -206,6 +206,8 @@ void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
void NODE_OT_clipboard_copy(struct wmOperatorType *ot);
void NODE_OT_clipboard_paste(struct wmOperatorType *ot);
void NODE_OT_shader_script_update(struct wmOperatorType *ot);
extern const char *node_context_dir[];
// XXXXXX

View File

@@ -117,6 +117,8 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_clipboard_copy);
WM_operatortype_append(NODE_OT_clipboard_paste);
WM_operatortype_append(NODE_OT_shader_script_update);
}
void ED_operatormacros_node(void)

View File

@@ -292,8 +292,7 @@ static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR])
BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR);
if (node->inputs.first == NULL &&
node->outputs.first != node->outputs.last &&
!(node->typeinfo->flag & NODE_OPTIONS))
node->outputs.first != node->outputs.last)
{
BLI_snprintf(name, UI_MAX_NAME_STR, "%s | %s", IFACE_(node_name), IFACE_(sock->link->fromsock->name));
}

View File

@@ -703,6 +703,26 @@ typedef struct NodeTrackPosData {
char track_name[64];
} NodeTrackPosData;
typedef struct NodeShaderScript {
int mode;
int flag;
char filepath[1024]; /* 1024 = FILE_MAX */
char bytecode_hash[64];
char *bytecode;
IDProperty *prop;
} NodeShaderScript;
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
/* script node flag */
#define NODE_SCRIPT_AUTO_UPDATE 1
/* frame node flags */
#define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */
#define NODE_FRAME_RESIZEABLE 2 /* test flag, if frame can be resized by user */

View File

@@ -457,6 +457,7 @@ extern StructRNA RNA_ShaderNodeMath;
extern StructRNA RNA_ShaderNodeMixRGB;
extern StructRNA RNA_ShaderNodeNormal;
extern StructRNA RNA_ShaderNodeOutput;
extern StructRNA RNA_ShaderNodeScript;
extern StructRNA RNA_ShaderNodeRGB;
extern StructRNA RNA_ShaderNodeRGBCurve;
extern StructRNA RNA_ShaderNodeRGBToBW;

View File

@@ -35,12 +35,16 @@
#include "rna_internal_types.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_text_types.h"
#include "DNA_texture_types.h"
#include "BKE_animsys.h"
@@ -48,9 +52,9 @@
#include "BKE_node.h"
#include "BKE_image.h"
#include "BKE_texture.h"
#include "BKE_idprop.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "IMB_imbuf.h"
#include "WM_types.h"
@@ -206,6 +210,8 @@ EnumPropertyItem prop_wave_items[] = {
#include "BLI_linklist.h"
#include "BKE_global.h"
#include "ED_node.h"
#include "RE_pipeline.h"
@@ -995,6 +1001,125 @@ static void rna_NodeOutputFileSlotLayer_name_set(PointerRNA *ptr, const char *va
}
}
static bNodeSocket *rna_ShaderNodeScript_find_socket(bNode *node, const char *name, int is_output)
{
bNodeSocket *sock;
if (is_output) {
for (sock = node->outputs.first; sock; sock = sock->next)
if (strcmp(sock->name, name)==0)
return sock;
}
else {
for (sock = node->inputs.first; sock; sock = sock->next)
if (strcmp(sock->name, name)==0)
return sock;
}
return NULL;
}
static void rna_ShaderNodeScript_remove_socket(ID *id, bNode *node, bNodeSocket *sock)
{
bNodeTree *ntree = (bNodeTree *)id;
nodeRemoveSocket(ntree, node, sock);
ED_node_generic_update(G.main, ntree, node);
}
static bNodeSocket *rna_ShaderNodeScript_add_socket(ID *id, bNode *node, const char *name, int type, int is_output)
{
bNodeTree *ntree = (bNodeTree *)id;
bNodeSocket *sock;
/* replace existing socket with the same name, to keep it unique */
sock = rna_ShaderNodeScript_find_socket(node, name, is_output);
if (sock)
nodeRemoveSocket(ntree, node, sock);
sock = nodeAddSocket(ntree, node, (is_output ? SOCK_OUT : SOCK_IN), name, type);
ED_node_generic_update(G.main, ntree, node);
return sock;
}
static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value)
{
bNode *node = (bNode *)ptr->data;
NodeShaderScript *nss = node->storage;
if (nss->mode != value) {
nss->mode = value;
nss->filepath[0] = '\0';
nss->flag &= ~NODE_SCRIPT_AUTO_UPDATE;
/* replace text datablock by filepath */
if (node->id) {
Text *text = (Text*)node->id;
if(value == NODE_SCRIPT_EXTERNAL && text->name) {
BLI_strncpy(nss->filepath, text->name, sizeof(nss->filepath));
BLI_path_rel(nss->filepath, G.main->name);
}
id_us_min(node->id);
node->id = NULL;
}
/* remove any bytecode */
if(nss->bytecode) {
MEM_freeN(nss->bytecode);
nss->bytecode = NULL;
}
nss->bytecode_hash[0] = '\0';
}
}
static void rna_ShaderNodeScript_bytecode_get(PointerRNA *ptr, char *value)
{
bNode *node = (bNode *)ptr->data;
NodeShaderScript *nss = node->storage;
strcpy(value, (nss->bytecode)? nss->bytecode: "");
}
static int rna_ShaderNodeScript_bytecode_length(PointerRNA *ptr)
{
bNode *node = (bNode *)ptr->data;
NodeShaderScript *nss = node->storage;
return (nss->bytecode) ? strlen(nss->bytecode) : 0;
}
static void rna_ShaderNodeScript_bytecode_set(PointerRNA *ptr, const char *value)
{
bNode *node = (bNode *)ptr->data;
NodeShaderScript *nss = node->storage;
if (nss->bytecode)
MEM_freeN(nss->bytecode);
if (value && value[0])
nss->bytecode = BLI_strdup(value);
else
nss->bytecode = NULL;
}
static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, int create)
{
bNode *node = (bNode *)ptr->data;
NodeShaderScript *nss = node->storage;
if (create && !nss->prop) {
IDPropertyTemplate val = {0};
nss->prop = IDP_New(IDP_GROUP, &val, "RNA_ShaderNodeScript ID properties");
}
return nss->prop;
}
#else
static EnumPropertyItem prop_image_layer_items[] = {
@@ -1035,6 +1160,12 @@ static EnumPropertyItem node_glossy_items[] = {
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem node_script_mode_items[] = {
{NODE_SCRIPT_INTERNAL, "INTERNAL", 0, "Internal", "Use internal text datablock"},
{NODE_SCRIPT_EXTERNAL, "EXTERNAL", 0, "External", "Use external .osl or oso file"},
{0, NULL, 0, NULL, NULL}
};
#define MaxNodes 50000
enum
@@ -1707,6 +1838,76 @@ static void def_glossy(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_sh_script(StructRNA *srna)
{
FunctionRNA *func;
PropertyRNA *prop, *parm;
prop = RNA_def_property(srna, "script", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Text");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Script", "Internal shader script to define the shader");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
RNA_def_struct_sdna_from(srna, "NodeShaderScript", "storage");
RNA_def_struct_idprops_func(srna, "rna_ShaderNodeScript_idprops");
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
RNA_def_property_ui_text(prop, "File Path", "Shader script path");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeScript_mode_set", NULL);
RNA_def_property_enum_items(prop, node_script_mode_items);
RNA_def_property_ui_text(prop, "Script Source", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "use_auto_update", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SCRIPT_AUTO_UPDATE);
RNA_def_property_ui_text(prop, "Auto Update", "Automatically updates the shader when the .osl file changes - external scripts only");
prop = RNA_def_property(srna, "bytecode", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ShaderNodeScript_bytecode_get",
"rna_ShaderNodeScript_bytecode_length", "rna_ShaderNodeScript_bytecode_set");
RNA_def_property_ui_text(prop, "Bytecode", "Compile bytecode for shader script node");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "bytecode_hash", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Bytecode Hash", "Hash of compile bytecode, for quick equality checking");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
/* needs to be reset to avoid bad pointer type in API functions below */
RNA_def_struct_sdna_from(srna, "bNode", NULL);
/* API functions */
func = RNA_def_function(srna, "find_socket", "rna_ShaderNodeScript_find_socket");
RNA_def_function_ui_description(func, "Find a socket by name");
parm = RNA_def_string(func, "name", "", 0, "Socket name", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
/*parm =*/ RNA_def_boolean(func, "is_output", FALSE, "Output", "Whether the socket is an output");
parm = RNA_def_pointer(func, "result", "NodeSocket", "", "");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "add_socket", "rna_ShaderNodeScript_add_socket");
RNA_def_function_ui_description(func, "Add a socket socket");
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
parm = RNA_def_string(func, "name", "", 0, "Name", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_enum(func, "type", node_socket_type_items, SOCK_FLOAT, "Type", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
/*parm =*/ RNA_def_boolean(func, "is_output", FALSE, "Output", "Whether the socket is an output");
parm = RNA_def_pointer(func, "result", "NodeSocket", "", "");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove_socket", "rna_ShaderNodeScript_remove_socket");
RNA_def_function_ui_description(func, "Remove a socket socket");
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
parm = RNA_def_pointer(func, "sock", "NodeSocket", "Socket", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
}
/* -- Compositor Nodes ------------------------------------------------------ */
static void def_cmp_alpha_over(StructRNA *srna)

View File

@@ -82,7 +82,8 @@ DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LI
DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" )
DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" )
DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" )
DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", BumpNode, "Bump", "" )
DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", BumpNode, "Bump", "" )
DefNode( ShaderNode, SH_NODE_SCRIPT, def_sh_script, "SCRIPT", Script, "Script", "" )
DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" )
DefNode( ShaderNode, SH_NODE_TEX_SKY, def_sh_tex_sky, "TEX_SKY", TexSky, "Sky Texture", "" )

View File

@@ -129,6 +129,24 @@ static void engine_view_draw(RenderEngine *engine, const struct bContext *contex
RNA_parameter_list_free(&list);
}
static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node)
{
extern FunctionRNA rna_RenderEngine_update_script_node_func;
PointerRNA ptr, nodeptr;
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
RNA_pointer_create((ID*)ntree, &RNA_Node, node, &nodeptr);
func = &rna_RenderEngine_update_script_node_func;
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "node", &nodeptr);
engine->type->ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
}
/* RenderEngine registration */
static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type)
@@ -149,7 +167,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
RenderEngineType *et, dummyet = {NULL};
RenderEngine dummyengine = {NULL};
PointerRNA dummyptr;
int have_function[4];
int have_function[5];
/* setup dummy engine & engine type to store static properties in */
dummyengine.type = &dummyet;
@@ -188,6 +206,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
et->render = (have_function[1]) ? engine_render : NULL;
et->view_update = (have_function[2]) ? engine_view_update : NULL;
et->view_draw = (have_function[3]) ? engine_view_draw : NULL;
et->update_script_node = (have_function[4]) ? engine_update_script_node : NULL;
BLI_addtail(&R_engines, et);
@@ -300,6 +319,13 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
RNA_def_pointer(func, "context", "Context", "", "");
/* shader script callbacks */
func = RNA_def_function(srna, "update_script_node", NULL);
RNA_def_function_ui_description(func, "Compile shader script node");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
prop = RNA_def_pointer(func, "node", "Node", "", "");
RNA_def_property_flag(prop, PROP_RNAPTR);
/* tag for redraw */
RNA_def_function(srna, "tag_redraw", "engine_tag_redraw");
RNA_def_function_ui_description(func, "Request redraw for viewport rendering");

View File

@@ -165,6 +165,7 @@ set(SRC
shader/nodes/node_shader_light_path.c
shader/nodes/node_shader_light_falloff.c
shader/nodes/node_shader_object_info.c
shader/nodes/node_shader_script.c
shader/nodes/node_shader_particle_info.c
shader/nodes/node_shader_mix_shader.c
shader/nodes/node_shader_add_shader.c

View File

@@ -80,6 +80,7 @@ void register_node_type_sh_fresnel(struct bNodeTreeType *ttype);
void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype);
void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype);
void register_node_type_sh_particle_info(struct bNodeTreeType *ttype);
void register_node_type_sh_script(struct bNodeTreeType *ttype);
void register_node_type_sh_background(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_diffuse(struct bNodeTreeType *ttype);

View File

@@ -87,10 +87,11 @@ static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback f
func(calldata, NODE_CLASS_SHADER, N_("Shader"));
func(calldata, NODE_CLASS_TEXTURE, N_("Texture"));
}
func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}

View File

@@ -0,0 +1,85 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2005 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/nodes/shader/nodes/node_shader_script.c
* \ingroup shdnodes
*/
#include "BKE_idprop.h"
#include "node_shader_util.h"
/* **************** Script ******************** */
static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
{
NodeShaderScript *nss = MEM_callocN(sizeof(NodeShaderScript), "shader script node");
node->storage = nss;
}
static void node_free_script(bNode *node)
{
NodeShaderScript *nss = node->storage;
if (nss) {
if (nss->bytecode)
MEM_freeN(nss->bytecode);
MEM_freeN(nss);
}
if (nss->prop) {
IDP_FreeProperty(nss->prop);
MEM_freeN(nss->prop);
}
}
static void node_copy_script(bNode *orig_node, bNode *new_node)
{
NodeShaderScript *orig_nss = orig_node->storage;
NodeShaderScript *new_nss = MEM_dupallocN(orig_nss);
if(orig_nss->bytecode)
new_nss->bytecode = MEM_dupallocN(orig_nss->bytecode);
if (orig_nss->prop)
new_nss->prop = IDP_CopyProperty(orig_nss->prop);
new_node->storage = new_nss;
}
void register_node_type_sh_script(bNodeTreeType *ttype)
{
static bNodeType ntype;
node_type_base(ttype, &ntype, SH_NODE_SCRIPT, "Script", NODE_CLASS_SCRIPT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_init(&ntype, init);
node_type_storage(&ntype, "NodeShaderScript", node_free_script, node_copy_script);
nodeRegisterType(ttype, &ntype);
}

View File

@@ -35,6 +35,8 @@
#include "DNA_listBase.h"
#include "RNA_types.h"
struct bNode;
struct bNodeTree;
struct Object;
struct Render;
struct RenderEngine;
@@ -75,6 +77,8 @@ typedef struct RenderEngineType {
void (*view_update)(struct RenderEngine *engine, const struct bContext *context);
void (*view_draw)(struct RenderEngine *engine, const struct bContext *context);
void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node);
/* RNA integration */
ExtensionRNA ext;
} RenderEngineType;
@@ -94,6 +98,8 @@ typedef struct RenderEngine {
char *text;
int resolution_x, resolution_y;
struct ReportList *reports;
} RenderEngine;
RenderEngine *RE_engine_create(RenderEngineType *type);

View File

@@ -64,7 +64,7 @@
static RenderEngineType internal_render_type = {
NULL, NULL,
"BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -73,7 +73,7 @@ static RenderEngineType internal_render_type = {
static RenderEngineType internal_game_type = {
NULL, NULL,
"BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -292,7 +292,12 @@ void RE_engine_update_progress(RenderEngine *engine, float progress)
void RE_engine_report(RenderEngine *engine, int type, const char *msg)
{
BKE_report(engine->re->reports, type, msg);
Render *re = engine->re;
if (re)
BKE_report(engine->re->reports, type, msg);
else if(engine->reports)
BKE_report(engine->reports, type, msg);
}
/* Render */