diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-11-03 18:32:26 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-11-03 18:32:26 +0400 |
commit | e02b23b81ab05579c0ee11ee3a1acb283643e528 (patch) | |
tree | 59b14c01bcb4c274d57c89a42e5a5d80c41ff06d /source/blender | |
parent | 615fe0295fe13c229d7376b02a50ac110b636c47 (diff) |
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.
Diffstat (limited to 'source/blender')
21 files changed, 562 insertions, 12 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index cd1875f848b..29e03f66bcc 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -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 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 8738251fa78..cbe3b7dd231 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -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); diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index b9ca3c9cc63..5995e69a73a 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -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) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8aa879a354b..a6e95541d9c 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 2ccefad4506..d7c62837008 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -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) ) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 420f0f1c413..f25fed3f6bb 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -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; } } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index f21f343ea2b..95dbe7e7b46 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -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; +} + diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 36ebddc8d22..45509e02226 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -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 diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 560ef9e8a29..64e5f67a348 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -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) diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index d4df449a41b..23f4e948794 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -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)); } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index aa382632b7b..bebe2ba20d5 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -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 */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index a9dbbe4273f..5f667db4425 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -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; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index be9a2d8c613..85df288b38b 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -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) diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index 6d97e959112..c45c9b71442 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -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", "" ) diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 7a638e9e40b..56497e96c67 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -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"); diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 19b3df8affe..323a534c989 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -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 diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 7585ed0d61c..66ab15ce29f 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -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); diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 76bc3b12690..b7dc83d7d79 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -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")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_script.c b/source/blender/nodes/shader/nodes/node_shader_script.c new file mode 100644 index 00000000000..52d39363de6 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_script.c @@ -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); +} diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 2376aeca55e..20024eab633 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -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); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 94146467145..076cad05c84 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -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 */ |