Add Chromium-only Blender WebEngine parity work
This commit is contained in:
68
blender-5.2.0/source/blender/nodes/texture/CMakeLists.txt
Normal file
68
blender-5.2.0/source/blender/nodes/texture/CMakeLists.txt
Normal file
@@ -0,0 +1,68 @@
|
||||
# SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(INC
|
||||
.
|
||||
..
|
||||
../intern
|
||||
../../editors/include
|
||||
../../makesrna
|
||||
# RNA_prototypes.hh
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
nodes/node_texture_at.cc
|
||||
nodes/node_texture_bricks.cc
|
||||
nodes/node_texture_checker.cc
|
||||
nodes/node_texture_combine_color.cc
|
||||
nodes/node_texture_common.cc
|
||||
nodes/node_texture_coord.cc
|
||||
nodes/node_texture_curves.cc
|
||||
nodes/node_texture_distance.cc
|
||||
nodes/node_texture_hueSatVal.cc
|
||||
nodes/node_texture_image.cc
|
||||
nodes/node_texture_invert.cc
|
||||
nodes/node_texture_math.cc
|
||||
nodes/node_texture_mixRgb.cc
|
||||
nodes/node_texture_output.cc
|
||||
nodes/node_texture_proc.cc
|
||||
nodes/node_texture_rotate.cc
|
||||
nodes/node_texture_scale.cc
|
||||
nodes/node_texture_separate_color.cc
|
||||
nodes/node_texture_texture.cc
|
||||
nodes/node_texture_translate.cc
|
||||
nodes/node_texture_valToNor.cc
|
||||
nodes/node_texture_valToRgb.cc
|
||||
nodes/node_texture_viewer.cc
|
||||
|
||||
node_texture_register.cc
|
||||
node_texture_tree.cc
|
||||
node_texture_util.cc
|
||||
|
||||
node_texture_register.hh
|
||||
node_texture_util.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
PRIVATE bf::blenkernel
|
||||
PRIVATE bf::blenlib
|
||||
PRIVATE bf::blentranslation
|
||||
PRIVATE bf::bmesh
|
||||
PRIVATE bf::depsgraph
|
||||
PRIVATE bf::dna
|
||||
PRIVATE bf::imbuf
|
||||
PRIVATE bf::intern::guardedalloc
|
||||
bf_nodes
|
||||
PRIVATE bf::render
|
||||
PRIVATE bf::windowmanager
|
||||
)
|
||||
|
||||
blender_add_lib(bf_nodes_texture "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# RNA_prototypes.hh
|
||||
add_dependencies(bf_nodes_texture bf_rna)
|
||||
@@ -0,0 +1,52 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "NOD_register.hh"
|
||||
|
||||
#include "node_texture_register.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
void register_texture_nodes()
|
||||
{
|
||||
register_node_tree_type_tex();
|
||||
|
||||
register_node_type_tex_group();
|
||||
|
||||
register_node_type_tex_at();
|
||||
register_node_type_tex_bricks();
|
||||
register_node_type_tex_checker();
|
||||
register_node_type_tex_combine_color();
|
||||
register_node_type_tex_coord();
|
||||
register_node_type_tex_curve_rgb();
|
||||
register_node_type_tex_curve_time();
|
||||
register_node_type_tex_distance();
|
||||
register_node_type_tex_hue_sat();
|
||||
register_node_type_tex_image();
|
||||
register_node_type_tex_invert();
|
||||
register_node_type_tex_math();
|
||||
register_node_type_tex_mix_rgb();
|
||||
register_node_type_tex_output();
|
||||
register_node_type_tex_proc_blend();
|
||||
register_node_type_tex_proc_clouds();
|
||||
register_node_type_tex_proc_distnoise();
|
||||
register_node_type_tex_proc_magic();
|
||||
register_node_type_tex_proc_marble();
|
||||
register_node_type_tex_proc_musgrave();
|
||||
register_node_type_tex_proc_noise();
|
||||
register_node_type_tex_proc_stucci();
|
||||
register_node_type_tex_proc_voronoi();
|
||||
register_node_type_tex_proc_wood();
|
||||
register_node_type_tex_rgbtobw();
|
||||
register_node_type_tex_rotate();
|
||||
register_node_type_tex_scale();
|
||||
register_node_type_tex_separate_color();
|
||||
register_node_type_tex_texture();
|
||||
register_node_type_tex_translate();
|
||||
register_node_type_tex_valtonor();
|
||||
register_node_type_tex_valtorgb();
|
||||
register_node_type_tex_viewer();
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,47 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace blender {
|
||||
|
||||
void register_node_tree_type_tex();
|
||||
|
||||
void register_node_type_tex_group();
|
||||
|
||||
void register_node_type_tex_at();
|
||||
void register_node_type_tex_bricks();
|
||||
void register_node_type_tex_checker();
|
||||
void register_node_type_tex_combine_color();
|
||||
void register_node_type_tex_coord();
|
||||
void register_node_type_tex_curve_rgb();
|
||||
void register_node_type_tex_curve_time();
|
||||
void register_node_type_tex_distance();
|
||||
void register_node_type_tex_hue_sat();
|
||||
void register_node_type_tex_image();
|
||||
void register_node_type_tex_invert();
|
||||
void register_node_type_tex_math();
|
||||
void register_node_type_tex_mix_rgb();
|
||||
void register_node_type_tex_output();
|
||||
void register_node_type_tex_proc_blend();
|
||||
void register_node_type_tex_proc_clouds();
|
||||
void register_node_type_tex_proc_distnoise();
|
||||
void register_node_type_tex_proc_magic();
|
||||
void register_node_type_tex_proc_marble();
|
||||
void register_node_type_tex_proc_musgrave();
|
||||
void register_node_type_tex_proc_noise();
|
||||
void register_node_type_tex_proc_stucci();
|
||||
void register_node_type_tex_proc_voronoi();
|
||||
void register_node_type_tex_proc_wood();
|
||||
void register_node_type_tex_rgbtobw();
|
||||
void register_node_type_tex_rotate();
|
||||
void register_node_type_tex_scale();
|
||||
void register_node_type_tex_separate_color();
|
||||
void register_node_type_tex_texture();
|
||||
void register_node_type_tex_translate();
|
||||
void register_node_type_tex_valtonor();
|
||||
void register_node_type_tex_valtorgb();
|
||||
void register_node_type_tex_viewer();
|
||||
|
||||
} // namespace blender
|
||||
356
blender-5.2.0/source/blender/nodes/texture/node_texture_tree.cc
Normal file
356
blender-5.2.0/source/blender/nodes/texture/node_texture_tree.cc
Normal file
@@ -0,0 +1,356 @@
|
||||
/* SPDX-FileCopyrightText: 2007 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup nodes
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_linestyle.h"
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_paint.hh"
|
||||
#include "BKE_texture.h"
|
||||
|
||||
#include "NOD_texture.h"
|
||||
#include "node_common.h"
|
||||
#include "node_exec.hh"
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
#include "RNA_prototypes.hh"
|
||||
|
||||
#include "UI_resources.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static void texture_get_from_context(const bContext *C,
|
||||
bke::bNodeTreeType * /*treetype*/,
|
||||
bNodeTree **r_ntree,
|
||||
ID **r_id,
|
||||
ID **r_from)
|
||||
{
|
||||
const Main *bmain = CTX_data_main(C);
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
BKE_view_layer_synced_ensure(*bmain, scene, view_layer);
|
||||
Object *ob = BKE_view_layer_active_object_get(view_layer);
|
||||
Tex *tx = nullptr;
|
||||
|
||||
if (snode->texfrom == SNODE_TEX_BRUSH) {
|
||||
Brush *brush = nullptr;
|
||||
|
||||
if (ob && (ob->mode & OB_MODE_SCULPT)) {
|
||||
brush = BKE_paint_brush(&scene->toolsettings->sculpt->paint);
|
||||
}
|
||||
else {
|
||||
brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
|
||||
}
|
||||
|
||||
if (brush) {
|
||||
*r_from = reinterpret_cast<ID *>(brush);
|
||||
tx = give_current_brush_texture(brush);
|
||||
if (tx) {
|
||||
*r_id = &tx->id;
|
||||
*r_ntree = tx->nodetree;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (snode->texfrom == SNODE_TEX_LINESTYLE) {
|
||||
FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer);
|
||||
if (linestyle) {
|
||||
*r_from = id_cast<ID *>(linestyle);
|
||||
tx = give_current_linestyle_texture(linestyle);
|
||||
if (tx) {
|
||||
*r_id = &tx->id;
|
||||
*r_ntree = tx->nodetree;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void foreach_nodeclass(void *calldata, bke::bNodeClassCallback func)
|
||||
{
|
||||
func(calldata, NODE_CLASS_INPUT, N_("Input"));
|
||||
func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
|
||||
func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
|
||||
func(calldata, NODE_CLASS_PATTERN, N_("Patterns"));
|
||||
func(calldata, NODE_CLASS_TEXTURE, N_("Textures"));
|
||||
func(calldata, NODE_CLASS_CONVERTER, N_("Converter"));
|
||||
func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
|
||||
func(calldata, NODE_CLASS_GROUP, N_("Group"));
|
||||
func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
|
||||
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
|
||||
}
|
||||
|
||||
/* XXX muting disabled in previews because of threading issues with the main execution
|
||||
* it works here, but disabled for consistency
|
||||
*/
|
||||
#if 1
|
||||
static void localize(bNodeTree *localtree, bNodeTree * /*ntree*/)
|
||||
{
|
||||
bNode *node, *node_next;
|
||||
|
||||
/* replace muted nodes and reroute nodes by internal links */
|
||||
for (node = static_cast<bNode *>(localtree->nodes.first); node; node = node_next) {
|
||||
node_next = node->next;
|
||||
|
||||
if (node->is_muted() || node->is_reroute()) {
|
||||
bke::node_internal_relink(*localtree, *node);
|
||||
bke::node_tree_free_local_node(*localtree, *node);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void localize(bNodeTree * /*localtree*/, bNodeTree * /*ntree*/) {}
|
||||
#endif
|
||||
|
||||
static void update(bNodeTree *ntree)
|
||||
{
|
||||
ntree_update_reroute_nodes(ntree);
|
||||
}
|
||||
|
||||
static bool texture_node_tree_socket_type_valid(bke::bNodeTreeType * /*ntreetype*/,
|
||||
bke::bNodeSocketType *socket_type)
|
||||
{
|
||||
return bke::node_is_static_socket_type(*socket_type) &&
|
||||
ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA);
|
||||
}
|
||||
|
||||
bke::bNodeTreeType *ntreeType_Texture;
|
||||
|
||||
void register_node_tree_type_tex()
|
||||
{
|
||||
bke::bNodeTreeType *tt = ntreeType_Texture = MEM_new<bke::bNodeTreeType>(__func__);
|
||||
|
||||
tt->type = NTREE_TEXTURE;
|
||||
tt->idname = "TextureNodeTree"_ustr;
|
||||
tt->group_idname = "TextureNodeGroup"_ustr;
|
||||
tt->ui_name = N_("Texture Node Editor");
|
||||
tt->ui_icon = ICON_NODE_TEXTURE; /* Defined in `drawnode.cc`. */
|
||||
tt->ui_description = N_("Edit textures using nodes");
|
||||
/* Don't define this yet since we don't know which exact catalog name to use yet. Otherwise this
|
||||
* has to be kept for compatibility. */
|
||||
// tt->asset_catalog_path_prefix = "Textures";
|
||||
|
||||
tt->foreach_nodeclass = foreach_nodeclass;
|
||||
tt->update = update;
|
||||
tt->localize = localize;
|
||||
tt->get_from_context = texture_get_from_context;
|
||||
tt->valid_socket_type = texture_node_tree_socket_type_valid;
|
||||
|
||||
tt->rna_ext.srna = RNA_TextureNodeTree;
|
||||
|
||||
bke::node_tree_type_add(*tt);
|
||||
}
|
||||
|
||||
/**** Material/Texture trees ****/
|
||||
|
||||
bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread)
|
||||
{
|
||||
ListBaseT<bNodeThreadStack> *lb = &exec->threadstack[thread];
|
||||
bNodeThreadStack *nts;
|
||||
|
||||
for (nts = static_cast<bNodeThreadStack *>(lb->first); nts; nts = nts->next) {
|
||||
if (!nts->used) {
|
||||
nts->used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nts) {
|
||||
nts = MEM_new_zeroed<bNodeThreadStack>("bNodeThreadStack");
|
||||
nts->stack = MEM_dupalloc(exec->stack);
|
||||
nts->used = true;
|
||||
BLI_addtail(lb, nts);
|
||||
}
|
||||
|
||||
return nts;
|
||||
}
|
||||
|
||||
void ntreeReleaseThreadStack(bNodeThreadStack *nts)
|
||||
{
|
||||
nts->used = false;
|
||||
}
|
||||
|
||||
bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
|
||||
{
|
||||
bNodeStack *nsin[MAX_SOCKET] = {nullptr}; /* arbitrary... watch this */
|
||||
bNodeStack *nsout[MAX_SOCKET] = {nullptr}; /* arbitrary... watch this */
|
||||
bNodeExec *nodeexec;
|
||||
bNode *node;
|
||||
int n;
|
||||
|
||||
/* nodes are presorted, so exec is in order of list */
|
||||
|
||||
for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
|
||||
node = nodeexec->node;
|
||||
if (node->runtime->need_exec) {
|
||||
node_get_stack(node, nts->stack, nsin, nsout);
|
||||
/* Handle muted nodes...
|
||||
* If the mute func is not set, assume the node should never be muted,
|
||||
* and hence execute it!
|
||||
*/
|
||||
if (node->typeinfo->exec_fn && !node->is_muted()) {
|
||||
node->typeinfo->exec_fn(callerdata, thread, node, &nodeexec->data, nsin, nsout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* signal to that all went OK, for render */
|
||||
return true;
|
||||
}
|
||||
|
||||
bNodeTreeExec *ntreeTexBeginExecTree_internal(bNodeExecContext *context,
|
||||
bNodeTree *ntree,
|
||||
bNodeInstanceKey parent_key)
|
||||
{
|
||||
bNodeTreeExec *exec;
|
||||
|
||||
/* common base initialization */
|
||||
exec = ntree_exec_begin(context, ntree, parent_key);
|
||||
|
||||
/* allocate the thread stack listbase array */
|
||||
exec->threadstack = MEM_new_array_zeroed<ListBaseT<bNodeThreadStack>>(BLENDER_MAX_THREADS,
|
||||
"thread stack array");
|
||||
|
||||
for (bNode &node : exec->nodetree->nodes) {
|
||||
node.runtime->need_exec = 1;
|
||||
}
|
||||
|
||||
return exec;
|
||||
}
|
||||
|
||||
bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree)
|
||||
{
|
||||
bNodeExecContext context;
|
||||
bNodeTreeExec *exec;
|
||||
|
||||
/* XXX hack: prevent exec data from being generated twice.
|
||||
* this should be handled by the renderer!
|
||||
*/
|
||||
if (ntree->runtime->execdata) {
|
||||
return ntree->runtime->execdata;
|
||||
}
|
||||
|
||||
exec = ntreeTexBeginExecTree_internal(&context, ntree, bke::NODE_INSTANCE_KEY_BASE);
|
||||
|
||||
/* XXX this should not be necessary, but is still used for compositor/shading/texture nodes,
|
||||
* which only store the ntree pointer. Should be fixed at some point!
|
||||
*/
|
||||
ntree->runtime->execdata = exec;
|
||||
|
||||
return exec;
|
||||
}
|
||||
|
||||
/* free texture delegates */
|
||||
static void tex_free_delegates(bNodeTreeExec *exec)
|
||||
{
|
||||
bNodeStack *ns;
|
||||
int th, a;
|
||||
|
||||
for (th = 0; th < BLENDER_MAX_THREADS; th++) {
|
||||
for (bNodeThreadStack &nts : exec->threadstack[th]) {
|
||||
for (ns = nts.stack, a = 0; a < exec->stacksize; a++, ns++) {
|
||||
if (ns->data && !ns->is_copy) {
|
||||
MEM_delete(static_cast<TexDelegate *>(ns->data));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ntreeTexEndExecTree_internal(bNodeTreeExec *exec)
|
||||
{
|
||||
int a;
|
||||
|
||||
if (exec->threadstack) {
|
||||
tex_free_delegates(exec);
|
||||
|
||||
for (a = 0; a < BLENDER_MAX_THREADS; a++) {
|
||||
for (bNodeThreadStack &nts : exec->threadstack[a]) {
|
||||
if (nts.stack) {
|
||||
MEM_delete(nts.stack);
|
||||
}
|
||||
}
|
||||
BLI_freelistN(&exec->threadstack[a]);
|
||||
}
|
||||
|
||||
MEM_delete(exec->threadstack);
|
||||
exec->threadstack = nullptr;
|
||||
}
|
||||
|
||||
ntree_exec_end(exec);
|
||||
}
|
||||
|
||||
void ntreeTexEndExecTree(bNodeTreeExec *exec)
|
||||
{
|
||||
if (exec) {
|
||||
/* exec may get freed, so assign ntree */
|
||||
bNodeTree *ntree = exec->nodetree;
|
||||
ntreeTexEndExecTree_internal(exec);
|
||||
|
||||
/* XXX: clear node-tree back-pointer to exec data,
|
||||
* same problem as noted in #ntreeBeginExecTree. */
|
||||
ntree->runtime->execdata = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int ntreeTexExecTree(bNodeTree *ntree,
|
||||
TexResult *target,
|
||||
const float co[3],
|
||||
const short thread,
|
||||
const Tex * /*tex*/,
|
||||
short which_output,
|
||||
int cfra,
|
||||
int preview,
|
||||
MTex *mtex)
|
||||
{
|
||||
TexCallData data;
|
||||
int retval = TEX_INT;
|
||||
bNodeThreadStack *nts = nullptr;
|
||||
bNodeTreeExec *exec = ntree->runtime->execdata;
|
||||
|
||||
data.co = co;
|
||||
data.target = target;
|
||||
data.do_preview = preview;
|
||||
data.do_manage = true;
|
||||
data.thread = thread;
|
||||
data.which_output = which_output;
|
||||
data.cfra = cfra;
|
||||
data.mtex = mtex;
|
||||
|
||||
/* ensure execdata is only initialized once */
|
||||
if (!exec) {
|
||||
BLI_thread_lock(LOCK_NODES);
|
||||
if (!ntree->runtime->execdata) {
|
||||
ntreeTexBeginExecTree(ntree);
|
||||
}
|
||||
BLI_thread_unlock(LOCK_NODES);
|
||||
|
||||
exec = ntree->runtime->execdata;
|
||||
}
|
||||
|
||||
nts = ntreeGetThreadStack(exec, thread);
|
||||
ntreeExecThreadNodes(exec, nts, &data, thread);
|
||||
ntreeReleaseThreadStack(nts);
|
||||
|
||||
retval |= TEX_RGB;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
170
blender-5.2.0/source/blender/nodes/texture/node_texture_util.cc
Normal file
170
blender-5.2.0/source/blender/nodes/texture/node_texture_util.cc
Normal file
@@ -0,0 +1,170 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup nodes
|
||||
*/
|
||||
|
||||
/*
|
||||
* HOW TEXTURE NODES WORK
|
||||
*
|
||||
* In contrast to Shader nodes, which place a color into the output
|
||||
* stack when executed, Texture nodes place a TexDelegate* there. To
|
||||
* obtain a color value from this, a node further up the chain reads
|
||||
* the TexDelegate* from its input stack, and uses tex_call_delegate to
|
||||
* retrieve the color from the delegate.
|
||||
*
|
||||
* comments: (ton)
|
||||
*
|
||||
* This system needs recode, a node system should rely on the stack, and
|
||||
* callbacks for nodes only should evaluate their own node, not recursively go
|
||||
* over other previous ones.
|
||||
*/
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
#include "NOD_texture.h"
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
#include <optional>
|
||||
|
||||
namespace blender {
|
||||
|
||||
bool tex_node_poll_default(const bke::bNodeType * /*ntype*/,
|
||||
const bNodeTree *ntree,
|
||||
const char **r_disabled_hint)
|
||||
{
|
||||
if (!STREQ(ntree->idname, "TextureNodeTree")) {
|
||||
*r_disabled_hint = RPT_("Not a texture node tree");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void tex_node_type_base(bke::bNodeType *ntype,
|
||||
UString idname,
|
||||
const std::optional<int16_t> legacy_type)
|
||||
{
|
||||
bke::node_type_base(*ntype, idname, legacy_type);
|
||||
|
||||
ntype->poll = tex_node_poll_default;
|
||||
ntype->insert_link = node_insert_link_default;
|
||||
}
|
||||
|
||||
static void tex_call_delegate(TexDelegate *dg, float *out, TexParams *params, short thread)
|
||||
{
|
||||
if (dg->node->runtime->need_exec) {
|
||||
dg->fn(out, params, dg->node, dg->in, thread);
|
||||
}
|
||||
}
|
||||
|
||||
static void tex_input(float *out, int num, bNodeStack *in, TexParams *params, short thread)
|
||||
{
|
||||
TexDelegate *dg = static_cast<TexDelegate *>(in->data);
|
||||
if (dg) {
|
||||
tex_call_delegate(dg, in->vec, params, thread);
|
||||
|
||||
if (in->hasoutput && in->sockettype == SOCK_FLOAT) {
|
||||
in->vec[1] = in->vec[2] = in->vec[0];
|
||||
}
|
||||
}
|
||||
memcpy(out, in->vec, num * sizeof(float));
|
||||
}
|
||||
|
||||
void tex_input_vec(float *out, bNodeStack *in, TexParams *params, short thread)
|
||||
{
|
||||
tex_input(out, 3, in, params, thread);
|
||||
}
|
||||
|
||||
void tex_input_rgba(float *out, bNodeStack *in, TexParams *params, short thread)
|
||||
{
|
||||
tex_input(out, 4, in, params, thread);
|
||||
|
||||
if (in->hasoutput && in->sockettype == SOCK_FLOAT) {
|
||||
out[1] = out[2] = out[0];
|
||||
out[3] = 1;
|
||||
}
|
||||
|
||||
if (in->hasoutput && in->sockettype == SOCK_VECTOR) {
|
||||
out[0] = out[0] * 0.5f + 0.5f;
|
||||
out[1] = out[1] * 0.5f + 0.5f;
|
||||
out[2] = out[2] * 0.5f + 0.5f;
|
||||
out[3] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
float tex_input_value(bNodeStack *in, TexParams *params, short thread)
|
||||
{
|
||||
float out[4];
|
||||
tex_input_vec(out, in, params, thread);
|
||||
return out[0];
|
||||
}
|
||||
|
||||
void params_from_cdata(TexParams *out, TexCallData *in)
|
||||
{
|
||||
out->co = in->co;
|
||||
out->previewco = in->co;
|
||||
out->cfra = in->cfra;
|
||||
out->mtex = in->mtex;
|
||||
}
|
||||
|
||||
void tex_output(bNode *node,
|
||||
bNodeExecData * /*execdata*/,
|
||||
bNodeStack **in,
|
||||
bNodeStack *out,
|
||||
TexFn texfn,
|
||||
TexCallData *cdata)
|
||||
{
|
||||
TexDelegate *dg;
|
||||
|
||||
if (node->is_muted()) {
|
||||
/* do not add a delegate if the node is muted */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!out->data) {
|
||||
/* Freed in tex_end_exec (node.cc) */
|
||||
dg = MEM_new_zeroed<TexDelegate>("tex delegate");
|
||||
out->data = dg;
|
||||
}
|
||||
else {
|
||||
dg = static_cast<TexDelegate *>(out->data);
|
||||
}
|
||||
|
||||
dg->cdata = cdata;
|
||||
dg->fn = texfn;
|
||||
dg->node = node;
|
||||
memcpy(dg->in, in, MAX_SOCKET * sizeof(bNodeStack *));
|
||||
dg->type = out->sockettype;
|
||||
}
|
||||
|
||||
void ntreeTexCheckCyclics(bNodeTree *ntree)
|
||||
{
|
||||
for (bNode &node : ntree->nodes) {
|
||||
|
||||
if (node.type_legacy == TEX_NODE_TEXTURE && node.id) {
|
||||
/* custom2 stops the node from rendering */
|
||||
if (node.custom1) {
|
||||
node.custom2 = 1;
|
||||
node.custom1 = 0;
|
||||
}
|
||||
else {
|
||||
Tex *tex = id_cast<Tex *>(node.id);
|
||||
|
||||
node.custom2 = 0;
|
||||
|
||||
node.custom1 = 1;
|
||||
if (tex->use_nodes && tex->nodetree) {
|
||||
ntreeTexCheckCyclics(tex->nodetree);
|
||||
}
|
||||
node.custom1 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,92 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup nodes
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_node_legacy_types.hh" // IWYU pragma: export
|
||||
|
||||
#include "node_texture_register.hh" // IWYU pragma: export
|
||||
|
||||
#include "BLT_translation.hh" // IWYU pragma: export
|
||||
|
||||
#include "RE_texture.h"
|
||||
|
||||
namespace blender {
|
||||
|
||||
struct bNodeThreadStack;
|
||||
|
||||
struct TexCallData {
|
||||
TexResult *target;
|
||||
/* float[3] */
|
||||
const float *co;
|
||||
|
||||
bool do_preview;
|
||||
bool do_manage;
|
||||
short thread;
|
||||
short which_output;
|
||||
int cfra;
|
||||
|
||||
const MTex *mtex;
|
||||
};
|
||||
|
||||
struct TexParams {
|
||||
const float *co;
|
||||
const float *previewco;
|
||||
int cfra;
|
||||
|
||||
/* optional. we don't really want these here, but image
|
||||
* textures need to do mapping & color correction */
|
||||
const MTex *mtex;
|
||||
};
|
||||
|
||||
using TexFn = void (*)(float *out, TexParams *params, bNode *node, bNodeStack **in, short thread);
|
||||
|
||||
struct TexDelegate {
|
||||
TexCallData *cdata;
|
||||
TexFn fn;
|
||||
bNode *node;
|
||||
bNodeStack *in[MAX_SOCKET];
|
||||
int type;
|
||||
};
|
||||
|
||||
bool tex_node_poll_default(const bke::bNodeType *ntype,
|
||||
const bNodeTree *ntree,
|
||||
const char **r_disabled_hint);
|
||||
void tex_node_type_base(bke::bNodeType *ntype,
|
||||
UString idname,
|
||||
std::optional<int16_t> legacy_type = std::nullopt);
|
||||
|
||||
void tex_input_rgba(float *out, bNodeStack *in, TexParams *params, short thread);
|
||||
void tex_input_vec(float *out, bNodeStack *in, TexParams *params, short thread);
|
||||
float tex_input_value(bNodeStack *in, TexParams *params, short thread);
|
||||
|
||||
void tex_output(bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack *out,
|
||||
TexFn texfn,
|
||||
TexCallData *data);
|
||||
|
||||
void params_from_cdata(TexParams *out, TexCallData *in);
|
||||
|
||||
bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread);
|
||||
void ntreeReleaseThreadStack(bNodeThreadStack *nts);
|
||||
bool ntreeExecThreadNodes(bNodeTreeExec *exec,
|
||||
bNodeThreadStack *nts,
|
||||
void *callerdata,
|
||||
int thread);
|
||||
|
||||
bNodeTreeExec *ntreeTexBeginExecTree_internal(bNodeExecContext *context,
|
||||
bNodeTree *ntree,
|
||||
bNodeInstanceKey parent_key);
|
||||
void ntreeTexEndExecTree_internal(bNodeTreeExec *exec);
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,57 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Texture"), 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{SOCK_VECTOR, N_("Coordinates"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE},
|
||||
{-1, ""},
|
||||
};
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Texture")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
TexParams np = *p;
|
||||
float new_co[3];
|
||||
np.co = new_co;
|
||||
|
||||
tex_input_vec(new_co, in[1], p, thread);
|
||||
tex_input_rgba(out, in[0], &np, thread);
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_at()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeAt"_ustr, TEX_NODE_AT);
|
||||
ntype.ui_name = "At";
|
||||
ntype.enum_name_legacy = "AT";
|
||||
ntype.nclass = NODE_CLASS_DISTORT;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,125 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BKE_material.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Bricks 1"), 0.596f, 0.282f, 0.0f, 1.0f},
|
||||
{SOCK_RGBA, N_("Bricks 2"), 0.632f, 0.504f, 0.05f, 1.0f},
|
||||
{SOCK_RGBA, N_("Mortar"), 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{SOCK_FLOAT, N_("Thickness"), 0.02f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_UNSIGNED},
|
||||
{SOCK_FLOAT, N_("Bias"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, N_("Brick Width"), 0.5f, 0.0f, 0.0f, 0.0f, 0.001f, 99.0f, PROP_UNSIGNED},
|
||||
{SOCK_FLOAT, N_("Row Height"), 0.25f, 0.0f, 0.0f, 0.0f, 0.001f, 99.0f, PROP_UNSIGNED},
|
||||
{-1, ""},
|
||||
};
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void init(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
node->custom3 = 0.5; /* offset */
|
||||
node->custom4 = 1.0; /* squash */
|
||||
}
|
||||
|
||||
static float noise(int n) /* fast integer noise */
|
||||
{
|
||||
int nn;
|
||||
n = (n >> 13) ^ n;
|
||||
nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
|
||||
return 0.5f * (float(nn) / 1073741824.0f);
|
||||
}
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
const float *co = p->co;
|
||||
|
||||
float x = co[0];
|
||||
float y = co[1];
|
||||
|
||||
int bricknum, rownum;
|
||||
float offset = 0;
|
||||
float ins_x, ins_y;
|
||||
float tint;
|
||||
|
||||
float bricks1[4];
|
||||
float bricks2[4];
|
||||
float mortar[4];
|
||||
|
||||
float mortar_thickness = tex_input_value(in[3], p, thread);
|
||||
float bias = tex_input_value(in[4], p, thread);
|
||||
float brick_width = tex_input_value(in[5], p, thread);
|
||||
float row_height = tex_input_value(in[6], p, thread);
|
||||
|
||||
tex_input_rgba(bricks1, in[0], p, thread);
|
||||
tex_input_rgba(bricks2, in[1], p, thread);
|
||||
tex_input_rgba(mortar, in[2], p, thread);
|
||||
|
||||
rownum = int(floor(y / row_height));
|
||||
|
||||
if (node->custom1 && node->custom2) {
|
||||
brick_width *= (rownum % node->custom2) ? 1.0f : node->custom4; /* squash */
|
||||
offset = (rownum % node->custom1) ? 0 : (brick_width * node->custom3); /* offset */
|
||||
}
|
||||
|
||||
bricknum = int(floor((x + offset) / brick_width));
|
||||
|
||||
ins_x = (x + offset) - brick_width * bricknum;
|
||||
ins_y = y - row_height * rownum;
|
||||
|
||||
tint = noise((rownum << 16) + (bricknum & 0xFFFF)) + bias;
|
||||
CLAMP(tint, 0.0f, 1.0f);
|
||||
|
||||
if (ins_x < mortar_thickness || ins_y < mortar_thickness ||
|
||||
ins_x > (brick_width - mortar_thickness) || ins_y > (row_height - mortar_thickness))
|
||||
{
|
||||
copy_v4_v4(out, mortar);
|
||||
}
|
||||
else {
|
||||
copy_v4_v4(out, bricks1);
|
||||
ramp_blend(MA_RAMP_BLEND, out, tint, bricks2);
|
||||
}
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_bricks()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeBricks"_ustr, TEX_NODE_BRICKS);
|
||||
ntype.ui_name = "Bricks";
|
||||
ntype.enum_name_legacy = "BRICKS";
|
||||
ntype.nclass = NODE_CLASS_PATTERN;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.default_width = bke::NodeWidth::_160;
|
||||
ntype.initfunc = init;
|
||||
ntype.exec_fn = exec;
|
||||
ntype.flag |= NODE_PREVIEW;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,70 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
#include <cmath>
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Color1"), 1.0f, 0.0f, 0.0f, 1.0f},
|
||||
{SOCK_RGBA, N_("Color2"), 1.0f, 1.0f, 1.0f, 1.0f},
|
||||
{SOCK_FLOAT, N_("Size"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 100.0f, PROP_UNSIGNED},
|
||||
{-1, ""},
|
||||
};
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
float x = p->co[0];
|
||||
float y = p->co[1];
|
||||
float z = p->co[2];
|
||||
float sz = tex_input_value(in[2], p, thread);
|
||||
|
||||
/* 0.00001 because of unit sized stuff */
|
||||
int xi = int(fabs(floor(0.00001f + x / sz)));
|
||||
int yi = int(fabs(floor(0.00001f + y / sz)));
|
||||
int zi = int(fabs(floor(0.00001f + z / sz)));
|
||||
|
||||
if ((xi % 2 == yi % 2) == (zi % 2)) {
|
||||
tex_input_rgba(out, in[0], p, thread);
|
||||
}
|
||||
else {
|
||||
tex_input_rgba(out, in[1], p, thread);
|
||||
}
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_checker()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeChecker"_ustr, TEX_NODE_CHECKER);
|
||||
ntype.ui_name = "Checker";
|
||||
ntype.enum_name_legacy = "CHECKER";
|
||||
ntype.nclass = NODE_CLASS_PATTERN;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
ntype.flag |= NODE_PREVIEW;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,84 @@
|
||||
/* SPDX-FileCopyrightText: 2022 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BLI_math_color.h"
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_FLOAT, N_("Red"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{SOCK_FLOAT, N_("Green"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{SOCK_FLOAT, N_("Blue"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{SOCK_FLOAT, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{-1, ""},
|
||||
};
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
out[i] = tex_input_value(in[i], p, thread);
|
||||
}
|
||||
/* Apply color space if required. */
|
||||
switch (node->custom1) {
|
||||
case NODE_COMBSEP_COLOR_RGB: {
|
||||
/* Pass */
|
||||
break;
|
||||
}
|
||||
case NODE_COMBSEP_COLOR_HSV: {
|
||||
hsv_to_rgb_v(out, out);
|
||||
break;
|
||||
}
|
||||
case NODE_COMBSEP_COLOR_HSL: {
|
||||
hsl_to_rgb_v(out, out);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
node_combsep_color_label(&node->inputs, NodeCombSepColorMode(node->custom1));
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_combine_color()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeCombineColor"_ustr, TEX_NODE_COMBINE_COLOR);
|
||||
ntype.ui_name = "Combine Color";
|
||||
ntype.enum_name_legacy = "COMBINE_COLOR";
|
||||
ntype.nclass = NODE_CLASS_OP_COLOR;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
ntype.updatefunc = update;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,170 @@
|
||||
/* SPDX-FileCopyrightText: 2006 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
#include "NOD_common.hh"
|
||||
#include "node_common.h"
|
||||
#include "node_exec.hh"
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static void copy_stack(bNodeStack *to, bNodeStack *from)
|
||||
{
|
||||
if (to != from) {
|
||||
copy_v4_v4(to->vec, from->vec);
|
||||
to->data = from->data;
|
||||
to->datatype = from->datatype;
|
||||
|
||||
/* tag as copy to prevent freeing */
|
||||
to->is_copy = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**** GROUP ****/
|
||||
|
||||
static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanceKey key)
|
||||
{
|
||||
bNodeTree *ngroup = id_cast<bNodeTree *>(node->id);
|
||||
void *exec;
|
||||
|
||||
if (!ngroup) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* initialize the internal node tree execution */
|
||||
exec = ntreeTexBeginExecTree_internal(context, ngroup, key);
|
||||
|
||||
return exec;
|
||||
}
|
||||
|
||||
static void group_freeexec(void *nodedata)
|
||||
{
|
||||
bNodeTreeExec *gexec = static_cast<bNodeTreeExec *>(nodedata);
|
||||
|
||||
ntreeTexEndExecTree_internal(gexec);
|
||||
}
|
||||
|
||||
/* Copy inputs to the internal stack.
|
||||
* This is a shallow copy, no buffers are duplicated here!
|
||||
*/
|
||||
static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack)
|
||||
{
|
||||
bNodeTree *ngroup = id_cast<bNodeTree *>(gnode->id);
|
||||
bNodeSocket *sock;
|
||||
bNodeStack *ns;
|
||||
int a;
|
||||
|
||||
for (bNode &node : ngroup->nodes) {
|
||||
if (node.is_group_input()) {
|
||||
for (sock = static_cast<bNodeSocket *>(node.outputs.first), a = 0; sock;
|
||||
sock = sock->next, a++)
|
||||
{
|
||||
if (in[a]) { /* shouldn't need to check this #36694. */
|
||||
ns = node_get_socket_stack(gstack, sock);
|
||||
if (ns) {
|
||||
copy_stack(ns, in[a]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy internal results to the external outputs.
|
||||
*/
|
||||
static void group_copy_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstack)
|
||||
{
|
||||
bNodeTree &ngroup = *reinterpret_cast<bNodeTree *>(gnode->id);
|
||||
|
||||
ngroup.ensure_topology_cache();
|
||||
bNode *group_output_node = ngroup.group_output_node();
|
||||
if (!group_output_node) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto [a, sock] : group_output_node->inputs.enumerate()) {
|
||||
if (!out[a]) {
|
||||
/* shouldn't need to check this #36694. */
|
||||
continue;
|
||||
}
|
||||
|
||||
bNodeStack *ns = node_get_socket_stack(gstack, &sock);
|
||||
if (ns) {
|
||||
copy_stack(out[a], ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void group_execute(void *data,
|
||||
int thread,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
bNodeTreeExec *exec = static_cast<bNodeTreeExec *>(execdata->data);
|
||||
bNodeThreadStack *nts;
|
||||
|
||||
if (!exec) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX same behavior as trunk: all nodes inside group are executed.
|
||||
* it's stupid, but just makes it work. compo redesign will do this better.
|
||||
*/
|
||||
for (bNode &inode : exec->nodetree->nodes) {
|
||||
inode.runtime->need_exec = 1;
|
||||
}
|
||||
|
||||
nts = ntreeGetThreadStack(exec, thread);
|
||||
|
||||
group_copy_inputs(node, in, nts->stack);
|
||||
ntreeExecThreadNodes(exec, nts, data, thread);
|
||||
group_copy_outputs(node, out, nts->stack);
|
||||
|
||||
ntreeReleaseThreadStack(nts);
|
||||
}
|
||||
|
||||
void register_node_type_tex_group()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
/* NOTE: Cannot use #sh_node_type_base for node group, because it would map the node type
|
||||
* to the shared #NODE_GROUP integer type id. */
|
||||
|
||||
bke::node_type_base_custom(ntype, "TextureNodeGroup", "Group", "GROUP", NODE_CLASS_GROUP);
|
||||
ntype.enum_name_legacy = "GROUP";
|
||||
ntype.type_legacy = NODE_GROUP;
|
||||
ntype.poll = tex_node_poll_default;
|
||||
ntype.poll_instance = node_group_poll_instance;
|
||||
ntype.insert_link = node_insert_link_default;
|
||||
ntype.rna_ext.srna = RNA_struct_find("TextureNodeGroup");
|
||||
BLI_assert(ntype.rna_ext.srna != nullptr);
|
||||
RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype);
|
||||
|
||||
ntype.minwidth = bke::NodeWidth::GroupMin;
|
||||
ntype.labelfunc = node_group_label;
|
||||
ntype.declare = nodes::node_group_declare;
|
||||
ntype.init_exec_fn = group_initexec;
|
||||
ntype.free_exec_fn = group_freeexec;
|
||||
ntype.exec_fn = group_execute;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,49 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_VECTOR, N_("Coordinates")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void vectorfn(
|
||||
float *out, TexParams *p, bNode * /*node*/, bNodeStack ** /*in*/, short /*thread*/)
|
||||
{
|
||||
copy_v3_v3(out, p->co);
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &vectorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_coord()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeCoordinates"_ustr, TEX_NODE_COORD);
|
||||
ntype.ui_name = "Coordinates";
|
||||
ntype.enum_name_legacy = "COORD";
|
||||
ntype.nclass = NODE_CLASS_INPUT;
|
||||
bke::node_type_socket_templates(&ntype, nullptr, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,126 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "BKE_colortools.hh"
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* **************** CURVE Time ******************** */
|
||||
|
||||
/* custom1 = start-frame, custom2 = end-frame. */
|
||||
static bke::bNodeSocketTemplate time_outputs[] = {{SOCK_FLOAT, N_("Value")}, {-1, ""}};
|
||||
|
||||
static void time_colorfn(
|
||||
float *out, TexParams *p, bNode *node, bNodeStack ** /*in*/, short /*thread*/)
|
||||
{
|
||||
/* stack order output: fac */
|
||||
float fac = 0.0f;
|
||||
|
||||
if (node->custom1 < node->custom2) {
|
||||
fac = (p->cfra - node->custom1) / float(node->custom2 - node->custom1);
|
||||
}
|
||||
|
||||
CurveMapping *mapping = static_cast<CurveMapping *>(node->storage);
|
||||
BKE_curvemapping_init(mapping);
|
||||
fac = BKE_curvemapping_evaluateF(mapping, 0, fac);
|
||||
out[0] = std::clamp(fac, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
static void time_exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &time_colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
static void time_init(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
node->custom1 = 1;
|
||||
node->custom2 = 250;
|
||||
node->storage = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void register_node_type_tex_curve_time()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeCurveTime"_ustr, TEX_NODE_CURVE_TIME);
|
||||
ntype.ui_name = "Time";
|
||||
ntype.enum_name_legacy = "CURVE_TIME";
|
||||
ntype.nclass = NODE_CLASS_INPUT;
|
||||
bke::node_type_socket_templates(&ntype, nullptr, time_outputs);
|
||||
ntype.default_width = bke::NodeWidth::_240;
|
||||
ntype.initfunc = time_init;
|
||||
bke::node_type_storage(ntype, "CurveMapping", node_free_curves, node_copy_curves);
|
||||
ntype.init_exec_fn = node_initexec_curves;
|
||||
ntype.exec_fn = time_exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
/* **************** CURVE RGB ******************** */
|
||||
static bke::bNodeSocketTemplate rgb_inputs[] = {
|
||||
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bke::bNodeSocketTemplate rgb_outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void rgb_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
float cin[4];
|
||||
tex_input_rgba(cin, in[0], p, thread);
|
||||
|
||||
BKE_curvemapping_evaluateRGBF(static_cast<CurveMapping *>(node->storage), out, cin);
|
||||
out[3] = cin[3];
|
||||
}
|
||||
|
||||
static void rgb_exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &rgb_colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
static void rgb_init(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
node->storage = BKE_curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void register_node_type_tex_curve_rgb()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeCurveRGB"_ustr, TEX_NODE_CURVE_RGB);
|
||||
ntype.ui_name = "RGB Curves";
|
||||
ntype.enum_name_legacy = "CURVE_RGB";
|
||||
ntype.nclass = NODE_CLASS_OP_COLOR;
|
||||
bke::node_type_socket_templates(&ntype, rgb_inputs, rgb_outputs);
|
||||
ntype.default_width = bke::NodeWidth::_240;
|
||||
ntype.initfunc = rgb_init;
|
||||
bke::node_type_storage(ntype, "CurveMapping", node_free_curves, node_copy_curves);
|
||||
ntype.init_exec_fn = node_initexec_curves;
|
||||
ntype.exec_fn = rgb_exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,59 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_VECTOR, N_("Coordinate 1"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE},
|
||||
{SOCK_VECTOR, N_("Coordinate 2"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_FLOAT, N_("Value")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void valuefn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
float co1[3], co2[3];
|
||||
|
||||
tex_input_vec(co1, in[0], p, thread);
|
||||
tex_input_vec(co2, in[1], p, thread);
|
||||
|
||||
*out = len_v3v3(co2, co1);
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &valuefn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_distance()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeDistance"_ustr, TEX_NODE_DISTANCE);
|
||||
ntype.ui_name = "Distance";
|
||||
ntype.enum_name_legacy = "DISTANCE";
|
||||
ntype.nclass = NODE_CLASS_CONVERTER;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,109 @@
|
||||
/* SPDX-FileCopyrightText: 2006 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_FLOAT, N_("Hue"), 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, PROP_NONE},
|
||||
{SOCK_FLOAT, N_("Saturation"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, N_("Value"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, N_("Factor"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE},
|
||||
{SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f},
|
||||
{-1, ""},
|
||||
};
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void do_hue_sat_fac(
|
||||
bNode * /*node*/, float *out, float hue, float sat, float val, float *in, float fac)
|
||||
{
|
||||
if (fac != 0 && (hue != 0.5f || sat != 1 || val != 1)) {
|
||||
float col[3], hsv[3], mfac = 1.0f - fac;
|
||||
|
||||
rgb_to_hsv(in[0], in[1], in[2], hsv, hsv + 1, hsv + 2);
|
||||
hsv[0] += (hue - 0.5f);
|
||||
if (hsv[0] > 1.0f) {
|
||||
hsv[0] -= 1.0f;
|
||||
}
|
||||
else if (hsv[0] < 0.0f) {
|
||||
hsv[0] += 1.0f;
|
||||
}
|
||||
hsv[1] *= sat;
|
||||
if (hsv[1] > 1.0f) {
|
||||
hsv[1] = 1.0f;
|
||||
}
|
||||
else if (hsv[1] < 0.0f) {
|
||||
hsv[1] = 0.0f;
|
||||
}
|
||||
hsv[2] *= val;
|
||||
if (hsv[2] > 1.0f) {
|
||||
hsv[2] = 1.0f;
|
||||
}
|
||||
else if (hsv[2] < 0.0f) {
|
||||
hsv[2] = 0.0f;
|
||||
}
|
||||
hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col + 1, col + 2);
|
||||
|
||||
out[0] = mfac * in[0] + fac * col[0];
|
||||
out[1] = mfac * in[1] + fac * col[1];
|
||||
out[2] = mfac * in[2] + fac * col[2];
|
||||
}
|
||||
else {
|
||||
copy_v4_v4(out, in);
|
||||
}
|
||||
}
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
float hue = tex_input_value(in[0], p, thread);
|
||||
float sat = tex_input_value(in[1], p, thread);
|
||||
float val = tex_input_value(in[2], p, thread);
|
||||
float fac = tex_input_value(in[3], p, thread);
|
||||
|
||||
float col[4];
|
||||
tex_input_rgba(col, in[4], p, thread);
|
||||
|
||||
hue += 0.5f; /* [-0.5, 0.5] -> [0, 1] */
|
||||
|
||||
do_hue_sat_fac(node, out, hue, sat, val, col, fac);
|
||||
|
||||
out[3] = col[3];
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_hue_sat()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeHueSaturation"_ustr, TEX_NODE_HUE_SAT);
|
||||
ntype.ui_name = "Hue/Saturation/Value";
|
||||
ntype.enum_name_legacy = "HUE_SAT";
|
||||
ntype.nclass = NODE_CLASS_OP_COLOR;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.default_width = bke::NodeWidth::_160;
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,119 @@
|
||||
/* SPDX-FileCopyrightText: 2006 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
#include "IMB_imbuf.hh"
|
||||
|
||||
#include "BKE_image.hh"
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Image")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack ** /*in*/, short /*thread*/)
|
||||
{
|
||||
float x = p->co[0];
|
||||
float y = p->co[1];
|
||||
Image *ima = id_cast<Image *>(node->id);
|
||||
ImageUser *iuser = static_cast<ImageUser *>(node->storage);
|
||||
|
||||
if (ima) {
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, nullptr);
|
||||
if (ibuf) {
|
||||
float xsize, ysize;
|
||||
float xoff, yoff;
|
||||
int px, py;
|
||||
|
||||
const float *result;
|
||||
|
||||
xsize = ibuf->x / 2;
|
||||
ysize = ibuf->y / 2;
|
||||
xoff = yoff = -1;
|
||||
|
||||
px = int((x - xoff) * xsize);
|
||||
py = int((y - yoff) * ysize);
|
||||
|
||||
if ((!xsize) || (!ysize)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ibuf->float_data()) {
|
||||
BLI_thread_lock(LOCK_IMAGE);
|
||||
if (!ibuf->float_data()) {
|
||||
IMB_float_from_byte(ibuf);
|
||||
}
|
||||
BLI_thread_unlock(LOCK_IMAGE);
|
||||
}
|
||||
|
||||
while (px < 0) {
|
||||
px += ibuf->x;
|
||||
}
|
||||
while (py < 0) {
|
||||
py += ibuf->y;
|
||||
}
|
||||
while (px >= ibuf->x) {
|
||||
px -= ibuf->x;
|
||||
}
|
||||
while (py >= ibuf->y) {
|
||||
py -= ibuf->y;
|
||||
}
|
||||
|
||||
result = ibuf->float_data() + py * ibuf->x * 4 + px * 4;
|
||||
copy_v4_v4(out, result);
|
||||
|
||||
BKE_image_release_ibuf(ima, ibuf, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
static void init(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
ImageUser *iuser = MEM_new<ImageUser>("node image user");
|
||||
node->storage = iuser;
|
||||
iuser->sfra = 1;
|
||||
iuser->flag |= IMA_ANIM_ALWAYS;
|
||||
}
|
||||
|
||||
void register_node_type_tex_image()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeImage"_ustr, TEX_NODE_IMAGE);
|
||||
ntype.ui_name = "Image";
|
||||
ntype.enum_name_legacy = "IMAGE";
|
||||
ntype.nclass = NODE_CLASS_INPUT;
|
||||
bke::node_type_socket_templates(&ntype, nullptr, outputs);
|
||||
ntype.initfunc = init;
|
||||
bke::node_type_storage(
|
||||
ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.exec_fn = exec;
|
||||
ntype.labelfunc = node_image_label;
|
||||
ntype.flag |= NODE_PREVIEW;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,63 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* **************** INVERT ******************** */
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
float col[4];
|
||||
|
||||
tex_input_rgba(col, in[0], p, thread);
|
||||
|
||||
col[0] = 1.0f - col[0];
|
||||
col[1] = 1.0f - col[1];
|
||||
col[2] = 1.0f - col[2];
|
||||
|
||||
copy_v3_v3(out, col);
|
||||
out[3] = col[3];
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_invert()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeInvert"_ustr, TEX_NODE_INVERT);
|
||||
ntype.ui_name = "Invert Color";
|
||||
ntype.enum_name_legacy = "INVERT";
|
||||
ntype.nclass = NODE_CLASS_OP_COLOR;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,403 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_rotation.h"
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* **************** SCALAR MATH ******************** */
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_FLOAT, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, N_("Value"), 0.0f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_FLOAT, N_("Value")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
float in0 = tex_input_value(in[0], p, thread);
|
||||
float in1 = tex_input_value(in[1], p, thread);
|
||||
|
||||
switch (node->custom1) {
|
||||
|
||||
case NODE_MATH_ADD:
|
||||
*out = in0 + in1;
|
||||
break;
|
||||
case NODE_MATH_SUBTRACT:
|
||||
*out = in0 - in1;
|
||||
break;
|
||||
case NODE_MATH_MULTIPLY:
|
||||
*out = in0 * in1;
|
||||
break;
|
||||
case NODE_MATH_DIVIDE: {
|
||||
if (in1 == 0) {
|
||||
/* We don't want to divide by zero. */
|
||||
*out = 0.0;
|
||||
}
|
||||
else {
|
||||
*out = in0 / in1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_SINE: {
|
||||
*out = sinf(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_COSINE: {
|
||||
*out = cosf(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_TANGENT: {
|
||||
*out = tanf(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_SINH: {
|
||||
*out = sinhf(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_COSH: {
|
||||
*out = coshf(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_TANH: {
|
||||
*out = tanhf(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ARCSINE: {
|
||||
/* Can't do the impossible... */
|
||||
if (in0 <= 1 && in0 >= -1) {
|
||||
*out = asinf(in0);
|
||||
}
|
||||
else {
|
||||
*out = 0.0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ARCCOSINE: {
|
||||
/* Can't do the impossible... */
|
||||
if (in0 <= 1 && in0 >= -1) {
|
||||
*out = acosf(in0);
|
||||
}
|
||||
else {
|
||||
*out = 0.0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ARCTANGENT: {
|
||||
*out = atan(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_POWER: {
|
||||
/* Only raise negative numbers by full integers */
|
||||
if (in0 >= 0) {
|
||||
out[0] = pow(in0, in1);
|
||||
}
|
||||
else {
|
||||
float y_mod_1 = fmod(in1, 1);
|
||||
if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
|
||||
*out = pow(in0, floor(in1 + 0.5f));
|
||||
}
|
||||
else {
|
||||
*out = 0.0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_LOGARITHM: {
|
||||
/* Don't want any imaginary numbers... */
|
||||
if (in0 > 0 && in1 > 0) {
|
||||
*out = log(in0) / log(in1);
|
||||
}
|
||||
else {
|
||||
*out = 0.0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_MINIMUM: {
|
||||
if (in0 < in1) {
|
||||
*out = in0;
|
||||
}
|
||||
else {
|
||||
*out = in1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_MAXIMUM: {
|
||||
if (in0 > in1) {
|
||||
*out = in0;
|
||||
}
|
||||
else {
|
||||
*out = in1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ROUND: {
|
||||
*out = (in0 < 0) ? int(in0 - 0.5f) : int(in0 + 0.5f);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_LESS_THAN: {
|
||||
if (in0 < in1) {
|
||||
*out = 1.0f;
|
||||
}
|
||||
else {
|
||||
*out = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_GREATER_THAN: {
|
||||
if (in0 > in1) {
|
||||
*out = 1.0f;
|
||||
}
|
||||
else {
|
||||
*out = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_MODULO: {
|
||||
if (in1 == 0.0f) {
|
||||
*out = 0.0f;
|
||||
}
|
||||
else {
|
||||
*out = fmod(in0, in1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_FLOORED_MODULO: {
|
||||
if (in1 == 0.0f) {
|
||||
*out = 0.0f;
|
||||
}
|
||||
else {
|
||||
*out = in0 - floorf(in0 / in1) * in1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_ABSOLUTE: {
|
||||
*out = fabsf(in0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_RADIANS: {
|
||||
*out = DEG2RADF(in0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_DEGREES: {
|
||||
*out = RAD2DEGF(in0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_ARCTAN2: {
|
||||
*out = atan2(in0, in1);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_SIGN: {
|
||||
*out = compatible_signf(in0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_EXPONENT: {
|
||||
*out = expf(in0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_FLOOR: {
|
||||
*out = floorf(in0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_CEIL: {
|
||||
*out = ceilf(in0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_FRACTION: {
|
||||
*out = in0 - floorf(in0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_SQRT: {
|
||||
if (in0 > 0.0f) {
|
||||
*out = sqrtf(in0);
|
||||
}
|
||||
else {
|
||||
*out = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_INV_SQRT: {
|
||||
if (in0 > 0.0f) {
|
||||
*out = 1.0f / sqrtf(in0);
|
||||
}
|
||||
else {
|
||||
*out = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_TRUNC: {
|
||||
if (in0 > 0.0f) {
|
||||
*out = floorf(in0);
|
||||
}
|
||||
else {
|
||||
*out = ceilf(in0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_SNAP: {
|
||||
if (in1 == 0) {
|
||||
*out = 0.0;
|
||||
}
|
||||
else {
|
||||
*out = floorf(in0 / in1) * in1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_WRAP: {
|
||||
float in2 = tex_input_value(in[2], p, thread);
|
||||
*out = wrapf(in0, in1, in2);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_PINGPONG: {
|
||||
*out = pingpongf(in0, in1);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_COMPARE: {
|
||||
float in2 = tex_input_value(in[2], p, thread);
|
||||
*out = (fabsf(in0 - in1) <= std::max(in2, 1e-5f)) ? 1.0f : 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_MULTIPLY_ADD: {
|
||||
float in2 = tex_input_value(in[2], p, thread);
|
||||
*out = in0 * in1 + in2;
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_SMOOTH_MIN: {
|
||||
float in2 = tex_input_value(in[2], p, thread);
|
||||
*out = smoothminf(in0, in1, in2);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_SMOOTH_MAX: {
|
||||
float in2 = tex_input_value(in[2], p, thread);
|
||||
*out = -smoothminf(-in0, -in1, in2);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
BLI_assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->custom2 & SHD_MATH_CLAMP) {
|
||||
CLAMP(*out, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_update(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
node_math_update(ntree, node);
|
||||
|
||||
bNodeSocket *sock1 = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 0));
|
||||
bNodeSocket *sock2 = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1));
|
||||
bNodeSocket *sock3 = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2));
|
||||
|
||||
node_sock_label_clear(sock1);
|
||||
node_sock_label_clear(sock2);
|
||||
node_sock_label_clear(sock3);
|
||||
|
||||
switch (node->custom1) {
|
||||
case NODE_MATH_WRAP:
|
||||
node_sock_label(sock2, "Max");
|
||||
node_sock_label(sock3, "Min");
|
||||
break;
|
||||
case NODE_MATH_MULTIPLY_ADD:
|
||||
node_sock_label(sock2, "Multiplier");
|
||||
node_sock_label(sock3, "Addend");
|
||||
break;
|
||||
case NODE_MATH_LESS_THAN:
|
||||
case NODE_MATH_GREATER_THAN:
|
||||
node_sock_label(sock2, "Threshold");
|
||||
break;
|
||||
case NODE_MATH_PINGPONG:
|
||||
node_sock_label(sock2, "Scale");
|
||||
break;
|
||||
case NODE_MATH_SNAP:
|
||||
node_sock_label(sock2, "Increment");
|
||||
break;
|
||||
case NODE_MATH_POWER:
|
||||
node_sock_label(sock1, "Base");
|
||||
node_sock_label(sock2, "Exponent");
|
||||
break;
|
||||
case NODE_MATH_LOGARITHM:
|
||||
node_sock_label(sock2, "Base");
|
||||
break;
|
||||
case NODE_MATH_DEGREES:
|
||||
node_sock_label(sock1, "Radians");
|
||||
break;
|
||||
case NODE_MATH_RADIANS:
|
||||
node_sock_label(sock1, "Degrees");
|
||||
break;
|
||||
case NODE_MATH_COMPARE:
|
||||
node_sock_label(sock3, "Epsilon");
|
||||
break;
|
||||
case NODE_MATH_SMOOTH_MAX:
|
||||
case NODE_MATH_SMOOTH_MIN:
|
||||
node_sock_label(sock3, "Distance");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &valuefn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_math()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeMath"_ustr, TEX_NODE_MATH);
|
||||
ntype.ui_name = "Math";
|
||||
ntype.enum_name_legacy = "MATH";
|
||||
ntype.nclass = NODE_CLASS_CONVERTER;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.labelfunc = node_math_label;
|
||||
ntype.exec_fn = exec;
|
||||
ntype.updatefunc = node_update;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,74 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
#include "BKE_material.hh"
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* **************** MIX RGB ******************** */
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_FLOAT, N_("Factor"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE},
|
||||
{SOCK_RGBA, N_("Color1"), 0.5f, 0.5f, 0.5f, 1.0f},
|
||||
{SOCK_RGBA, N_("Color2"), 0.5f, 0.5f, 0.5f, 1.0f},
|
||||
{-1, ""},
|
||||
};
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
float fac = tex_input_value(in[0], p, thread);
|
||||
float col1[4], col2[4];
|
||||
|
||||
tex_input_rgba(col1, in[1], p, thread);
|
||||
tex_input_rgba(col2, in[2], p, thread);
|
||||
|
||||
/* use alpha */
|
||||
if (node->custom2 & 1) {
|
||||
fac *= col2[3];
|
||||
}
|
||||
|
||||
CLAMP(fac, 0.0f, 1.0f);
|
||||
|
||||
copy_v4_v4(out, col1);
|
||||
ramp_blend(node->custom1, out, fac, col2);
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_mix_rgb()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeMixRGB"_ustr, TEX_NODE_MIX_RGB);
|
||||
ntype.ui_name = "Mix";
|
||||
ntype.enum_name_legacy = "MIX_RGB";
|
||||
ntype.nclass = NODE_CLASS_OP_COLOR;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.labelfunc = node_blend_label;
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,159 @@
|
||||
/* SPDX-FileCopyrightText: 2006 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* **************** COMPOSITE ******************** */
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
/* applies to render pipeline */
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData * /*execdata*/,
|
||||
bNodeStack **in,
|
||||
bNodeStack ** /*out*/)
|
||||
{
|
||||
TexCallData *cdata = static_cast<TexCallData *>(data);
|
||||
TexResult *target = cdata->target;
|
||||
|
||||
if (cdata->do_preview) {
|
||||
TexParams params;
|
||||
params_from_cdata(¶ms, cdata);
|
||||
|
||||
tex_input_rgba(target->trgba, in[0], ¶ms, cdata->thread);
|
||||
}
|
||||
else {
|
||||
/* 0 means don't care, so just use first */
|
||||
if (cdata->which_output == node->custom1 || (cdata->which_output == 0 && node->custom1 == 1)) {
|
||||
TexParams params;
|
||||
params_from_cdata(¶ms, cdata);
|
||||
|
||||
tex_input_rgba(target->trgba, in[0], ¶ms, cdata->thread);
|
||||
|
||||
target->tin = (target->trgba[0] + target->trgba[1] + target->trgba[2]) / 3.0f;
|
||||
target->talpha = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void unique_name(bNode *node)
|
||||
{
|
||||
TexNodeOutput *tno = static_cast<TexNodeOutput *>(node->storage);
|
||||
char new_name[sizeof(tno->name)];
|
||||
int new_len = 0;
|
||||
int suffix;
|
||||
bNode *i;
|
||||
const char *name = tno->name;
|
||||
|
||||
new_name[0] = '\0';
|
||||
i = node;
|
||||
while (i->prev) {
|
||||
i = i->prev;
|
||||
}
|
||||
for (; i; i = i->next) {
|
||||
if (i == node || i->type_legacy != TEX_NODE_OUTPUT ||
|
||||
!STREQ(name, ((TexNodeOutput *)(i->storage))->name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (new_name[0] == '\0') {
|
||||
int len = strlen(name);
|
||||
if (len >= 4 && sscanf(name + len - 4, ".%03d", &suffix) == 1) {
|
||||
new_len = len;
|
||||
}
|
||||
else {
|
||||
suffix = 0;
|
||||
new_len = len + 4;
|
||||
new_len = std::min<ulong>(new_len, sizeof(tno->name) - 1);
|
||||
}
|
||||
|
||||
STRNCPY(new_name, name);
|
||||
name = new_name;
|
||||
}
|
||||
int name_ofs = new_len - 4;
|
||||
BLI_snprintf(new_name + name_ofs, sizeof(new_name) - name_ofs, ".%03d", ++suffix);
|
||||
}
|
||||
|
||||
if (new_name[0] != '\0') {
|
||||
STRNCPY(tno->name, new_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void assign_index(bNode *node)
|
||||
{
|
||||
bNode *tnode;
|
||||
int index = 1;
|
||||
|
||||
tnode = node;
|
||||
while (tnode->prev) {
|
||||
tnode = tnode->prev;
|
||||
}
|
||||
|
||||
check_index:
|
||||
for (; tnode; tnode = tnode->next) {
|
||||
if (tnode->type_legacy == TEX_NODE_OUTPUT && tnode != node) {
|
||||
if (tnode->custom1 == index) {
|
||||
index++;
|
||||
goto check_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node->custom1 = index;
|
||||
}
|
||||
|
||||
static void init(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
TexNodeOutput *tno = MEM_new<TexNodeOutput>("TEX_output");
|
||||
node->storage = tno;
|
||||
|
||||
STRNCPY(tno->name, "Default");
|
||||
unique_name(node);
|
||||
assign_index(node);
|
||||
}
|
||||
|
||||
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
|
||||
{
|
||||
node_copy_standard_storage(dest_ntree, dest_node, src_node);
|
||||
unique_name(dest_node);
|
||||
assign_index(dest_node);
|
||||
}
|
||||
|
||||
void register_node_type_tex_output()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeOutput"_ustr, TEX_NODE_OUTPUT);
|
||||
ntype.ui_name = "Output";
|
||||
ntype.enum_name_legacy = "OUTPUT";
|
||||
ntype.nclass = NODE_CLASS_OUTPUT;
|
||||
bke::node_type_socket_templates(&ntype, inputs, nullptr);
|
||||
ntype.default_width = bke::NodeWidth::_160;
|
||||
ntype.initfunc = init;
|
||||
bke::node_type_storage(ntype, "TexNodeOutput", node_free_standard_storage, copy);
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
ntype.flag |= NODE_PREVIEW;
|
||||
ntype.no_muting = true;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,282 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BKE_material.hh"
|
||||
#include "BKE_texture.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
#include "RE_texture.h"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/*
|
||||
* In this file: wrappers to use procedural textures as nodes
|
||||
*/
|
||||
|
||||
static bke::bNodeSocketTemplate outputs_both[] = {{SOCK_RGBA, N_("Color"), 1.0f, 0.0f, 0.0f, 1.0f},
|
||||
{-1, ""}};
|
||||
static bke::bNodeSocketTemplate outputs_color_only[] = {{SOCK_RGBA, N_("Color")}, {-1, ""}};
|
||||
|
||||
/* Inputs common to all, #defined because nodes will need their own inputs too */
|
||||
#define I 2 /* count */
|
||||
#define COMMON_INPUTS \
|
||||
{SOCK_RGBA, "Color 1", 0.0f, 0.0f, 0.0f, 1.0f}, {SOCK_RGBA, "Color 2", 1.0f, 1.0f, 1.0f, 1.0f}
|
||||
|
||||
/* Calls multitex and copies the result to the outputs.
|
||||
* Called by xxx_exec, which handles inputs. */
|
||||
static void do_proc(float *result,
|
||||
TexParams *p,
|
||||
const float col1[4],
|
||||
const float col2[4],
|
||||
Tex *tex,
|
||||
const short thread)
|
||||
{
|
||||
TexResult texres;
|
||||
int textype;
|
||||
|
||||
textype = multitex_nodes(tex, p->co, &texres, thread, 0, p->mtex, nullptr);
|
||||
|
||||
if (textype & TEX_RGB) {
|
||||
copy_v4_v4(result, texres.trgba);
|
||||
}
|
||||
else {
|
||||
copy_v4_v4(result, col1);
|
||||
ramp_blend(MA_RAMP_BLEND, result, texres.tin, col2);
|
||||
}
|
||||
}
|
||||
|
||||
using MapFn = void (*)(Tex *tex, bNodeStack **in, TexParams *p, const short thread);
|
||||
|
||||
static void texfn(
|
||||
float *result, TexParams *p, bNode *node, bNodeStack **in, MapFn map_inputs, short thread)
|
||||
{
|
||||
Tex tex = dna::shallow_copy(*(static_cast<Tex *>(node->storage)));
|
||||
float col1[4], col2[4];
|
||||
tex_input_rgba(col1, in[0], p, thread);
|
||||
tex_input_rgba(col2, in[1], p, thread);
|
||||
|
||||
map_inputs(&tex, in, p, thread);
|
||||
|
||||
do_proc(result, p, col1, col2, &tex, thread);
|
||||
}
|
||||
|
||||
static int count_outputs(bNode *node)
|
||||
{
|
||||
return node->outputs.count();
|
||||
}
|
||||
|
||||
/* Boilerplate generators */
|
||||
|
||||
#define ProcNoInputs(name) \
|
||||
static void name##_map_inputs( \
|
||||
Tex * /*tex*/, bNodeStack ** /*in*/, TexParams * /*p*/, short /*thread*/) \
|
||||
{ \
|
||||
}
|
||||
|
||||
#define ProcDef(name) \
|
||||
static void name##_colorfn( \
|
||||
float *result, TexParams *p, bNode *node, bNodeStack **in, short thread) \
|
||||
{ \
|
||||
texfn(result, p, node, in, &name##_map_inputs, thread); \
|
||||
} \
|
||||
static void name##_exec(void *data, \
|
||||
int /*thread*/, \
|
||||
bNode *node, \
|
||||
bNodeExecData *execdata, \
|
||||
bNodeStack **in, \
|
||||
bNodeStack **out) \
|
||||
{ \
|
||||
int outs = count_outputs(node); \
|
||||
if (outs >= 1) { \
|
||||
tex_output(node, execdata, in, out[0], &name##_colorfn, static_cast<TexCallData *>(data)); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* --- VORONOI -- */
|
||||
static bke::bNodeSocketTemplate voronoi_inputs[] = {
|
||||
COMMON_INPUTS,
|
||||
{SOCK_FLOAT, N_("W1"), 1.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, N_("W2"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, N_("W3"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, N_("W4"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
|
||||
|
||||
{SOCK_FLOAT, N_("iScale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.01f, 10.0f, PROP_UNSIGNED},
|
||||
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 4.0f, PROP_UNSIGNED},
|
||||
|
||||
{-1, ""}};
|
||||
static void voronoi_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
|
||||
{
|
||||
tex->vn_w1 = tex_input_value(in[I + 0], p, thread);
|
||||
tex->vn_w2 = tex_input_value(in[I + 1], p, thread);
|
||||
tex->vn_w3 = tex_input_value(in[I + 2], p, thread);
|
||||
tex->vn_w4 = tex_input_value(in[I + 3], p, thread);
|
||||
|
||||
tex->ns_outscale = tex_input_value(in[I + 4], p, thread);
|
||||
tex->noisesize = tex_input_value(in[I + 5], p, thread);
|
||||
}
|
||||
ProcDef(voronoi);
|
||||
|
||||
/* --- BLEND -- */
|
||||
static bke::bNodeSocketTemplate blend_inputs[] = {COMMON_INPUTS, {-1, ""}};
|
||||
ProcNoInputs(blend);
|
||||
ProcDef(blend);
|
||||
|
||||
/* -- MAGIC -- */
|
||||
static bke::bNodeSocketTemplate magic_inputs[] = {
|
||||
COMMON_INPUTS,
|
||||
{SOCK_FLOAT, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
|
||||
{-1, ""}};
|
||||
static void magic_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
|
||||
{
|
||||
tex->turbul = tex_input_value(in[I + 0], p, thread);
|
||||
}
|
||||
ProcDef(magic);
|
||||
|
||||
/* --- MARBLE --- */
|
||||
static bke::bNodeSocketTemplate marble_inputs[] = {
|
||||
COMMON_INPUTS,
|
||||
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
|
||||
{SOCK_FLOAT, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
|
||||
{-1, ""}};
|
||||
static void marble_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
|
||||
{
|
||||
tex->noisesize = tex_input_value(in[I + 0], p, thread);
|
||||
tex->turbul = tex_input_value(in[I + 1], p, thread);
|
||||
}
|
||||
ProcDef(marble);
|
||||
|
||||
/* --- CLOUDS --- */
|
||||
static bke::bNodeSocketTemplate clouds_inputs[] = {
|
||||
COMMON_INPUTS,
|
||||
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
|
||||
{-1, ""}};
|
||||
static void clouds_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
|
||||
{
|
||||
tex->noisesize = tex_input_value(in[I + 0], p, thread);
|
||||
}
|
||||
ProcDef(clouds);
|
||||
|
||||
/* --- DISTORTED NOISE --- */
|
||||
static bke::bNodeSocketTemplate distnoise_inputs[] = {
|
||||
COMMON_INPUTS,
|
||||
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
|
||||
{SOCK_FLOAT, N_("Distortion"), 1.00f, 0.0f, 0.0f, 0.0f, 0.0000f, 10.0f, PROP_UNSIGNED},
|
||||
{-1, ""}};
|
||||
static void distnoise_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
|
||||
{
|
||||
tex->noisesize = tex_input_value(in[I + 0], p, thread);
|
||||
tex->dist_amount = tex_input_value(in[I + 1], p, thread);
|
||||
}
|
||||
ProcDef(distnoise);
|
||||
|
||||
/* --- WOOD --- */
|
||||
static bke::bNodeSocketTemplate wood_inputs[] = {
|
||||
COMMON_INPUTS,
|
||||
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
|
||||
{SOCK_FLOAT, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
|
||||
{-1, ""}};
|
||||
static void wood_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
|
||||
{
|
||||
tex->noisesize = tex_input_value(in[I + 0], p, thread);
|
||||
tex->turbul = tex_input_value(in[I + 1], p, thread);
|
||||
}
|
||||
ProcDef(wood);
|
||||
|
||||
/* --- MUSGRAVE --- */
|
||||
static bke::bNodeSocketTemplate musgrave_inputs[] = {
|
||||
COMMON_INPUTS,
|
||||
{SOCK_FLOAT, N_("H"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
|
||||
{SOCK_FLOAT, N_("Lacunarity"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 6.0f, PROP_UNSIGNED},
|
||||
{SOCK_FLOAT, N_("Octaves"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 8.0f, PROP_UNSIGNED},
|
||||
|
||||
{SOCK_FLOAT, N_("iScale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f, PROP_UNSIGNED},
|
||||
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
|
||||
{-1, ""}};
|
||||
static void musgrave_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
|
||||
{
|
||||
tex->mg_H = tex_input_value(in[I + 0], p, thread);
|
||||
tex->mg_lacunarity = tex_input_value(in[I + 1], p, thread);
|
||||
tex->mg_octaves = tex_input_value(in[I + 2], p, thread);
|
||||
tex->ns_outscale = tex_input_value(in[I + 3], p, thread);
|
||||
tex->noisesize = tex_input_value(in[I + 4], p, thread);
|
||||
}
|
||||
ProcDef(musgrave);
|
||||
|
||||
/* --- NOISE --- */
|
||||
static bke::bNodeSocketTemplate noise_inputs[] = {COMMON_INPUTS, {-1, ""}};
|
||||
ProcNoInputs(noise);
|
||||
ProcDef(noise);
|
||||
|
||||
/* --- STUCCI --- */
|
||||
static bke::bNodeSocketTemplate stucci_inputs[] = {
|
||||
COMMON_INPUTS,
|
||||
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
|
||||
{SOCK_FLOAT, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
|
||||
{-1, ""}};
|
||||
static void stucci_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
|
||||
{
|
||||
tex->noisesize = tex_input_value(in[I + 0], p, thread);
|
||||
tex->turbul = tex_input_value(in[I + 1], p, thread);
|
||||
}
|
||||
ProcDef(stucci);
|
||||
|
||||
/* --- */
|
||||
|
||||
static void init(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
Tex *tex = MEM_new<Tex>("Tex");
|
||||
node->storage = tex;
|
||||
|
||||
BKE_texture_default(tex);
|
||||
tex->type = eTex_Type(node->type_legacy - TEX_NODE_PROC);
|
||||
|
||||
if (tex->type == TEX_WOOD) {
|
||||
tex->stype = TEX_BANDNOISE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Node type definitions */
|
||||
#define TexDef(TEXTYPE, idname, outputs, name, Name, EnumNameLegacy) \
|
||||
void register_node_type_tex_proc_##name(void) \
|
||||
{ \
|
||||
static bke::bNodeType ntype; \
|
||||
\
|
||||
tex_node_type_base(&ntype, UString(idname), TEX_NODE_PROC + TEXTYPE); \
|
||||
ntype.ui_name = Name; \
|
||||
ntype.enum_name_legacy = EnumNameLegacy; \
|
||||
ntype.nclass = NODE_CLASS_TEXTURE; \
|
||||
bke::node_type_socket_templates(&ntype, name##_inputs, outputs); \
|
||||
ntype.default_width = bke::NodeWidth::_160; \
|
||||
ntype.initfunc = init; \
|
||||
bke::node_type_storage(ntype, "Tex", node_free_standard_storage, node_copy_standard_storage); \
|
||||
ntype.exec_fn = name##_exec; \
|
||||
ntype.flag |= NODE_PREVIEW; \
|
||||
\
|
||||
bke::node_register_type(ntype); \
|
||||
}
|
||||
|
||||
#define C outputs_color_only
|
||||
#define CV outputs_both
|
||||
|
||||
TexDef(TEX_VORONOI, "TextureNodeTexVoronoi", CV, voronoi, "Voronoi", "TEX_VORONOI");
|
||||
TexDef(TEX_BLEND, "TextureNodeTexBlend", C, blend, "Blend", "TEX_BLEND");
|
||||
TexDef(TEX_MAGIC, "TextureNodeTexMagic", C, magic, "Magic", "TEX_MAGIC");
|
||||
TexDef(TEX_MARBLE, "TextureNodeTexMarble", CV, marble, "Marble", "TEX_MARBLE");
|
||||
TexDef(TEX_CLOUDS, "TextureNodeTexClouds", CV, clouds, "Clouds", "TEX_CLOUDS");
|
||||
TexDef(TEX_WOOD, "TextureNodeTexWood", CV, wood, "Wood", "TEX_WOOD");
|
||||
TexDef(TEX_MUSGRAVE, "TextureNodeTexMusgrave", CV, musgrave, "Musgrave", "TEX_MUSGRAVE");
|
||||
TexDef(TEX_NOISE, "TextureNodeTexNoise", C, noise, "Noise", "TEX_NOISE");
|
||||
TexDef(TEX_STUCCI, "TextureNodeTexStucci", CV, stucci, "Stucci", "TEX_STUCCI");
|
||||
TexDef(
|
||||
TEX_DISTNOISE, "TextureNodeTexDistNoise", CV, distnoise, "Distorted Noise", "TEX_DISTNOISE");
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,90 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{SOCK_FLOAT, N_("Turns"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE},
|
||||
{SOCK_VECTOR, N_("Axis"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void rotate(float new_co[3], float a, const float ax[3], const float co[3])
|
||||
{
|
||||
float para[3];
|
||||
float perp[3];
|
||||
float cp[3];
|
||||
|
||||
float cos_a = cosf(a * float(2 * M_PI));
|
||||
float sin_a = sinf(a * float(2 * M_PI));
|
||||
|
||||
/* `x' = xcosa + n(n.x)(1-cosa) + (x*n)sina`. */
|
||||
|
||||
mul_v3_v3fl(perp, co, cos_a);
|
||||
mul_v3_v3fl(para, ax, dot_v3v3(co, ax) * (1 - cos_a));
|
||||
|
||||
cross_v3_v3v3(cp, ax, co);
|
||||
mul_v3_fl(cp, sin_a);
|
||||
|
||||
new_co[0] = para[0] + perp[0] + cp[0];
|
||||
new_co[1] = para[1] + perp[1] + cp[1];
|
||||
new_co[2] = para[2] + perp[2] + cp[2];
|
||||
}
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
float new_co[3], a, ax[3];
|
||||
|
||||
a = tex_input_value(in[1], p, thread);
|
||||
tex_input_vec(ax, in[2], p, thread);
|
||||
|
||||
rotate(new_co, a, ax, p->co);
|
||||
|
||||
{
|
||||
TexParams np = *p;
|
||||
np.co = new_co;
|
||||
tex_input_rgba(out, in[0], &np, thread);
|
||||
}
|
||||
}
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_rotate()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeRotate"_ustr, TEX_NODE_ROTATE);
|
||||
ntype.ui_name = "Rotate";
|
||||
ntype.enum_name_legacy = "ROTATE";
|
||||
ntype.nclass = NODE_CLASS_DISTORT;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,65 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
#include "BKE_node.hh"
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{SOCK_VECTOR, N_("Scale"), 1.0f, 1.0f, 1.0f, 0.0f, -10.0f, 10.0f, PROP_XYZ},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
float scale[3], new_co[3];
|
||||
TexParams np = *p;
|
||||
|
||||
np.co = new_co;
|
||||
|
||||
tex_input_vec(scale, in[1], p, thread);
|
||||
|
||||
mul_v3_v3v3(new_co, p->co, scale);
|
||||
|
||||
tex_input_rgba(out, in[0], &np, thread);
|
||||
}
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_scale()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeScale"_ustr, TEX_NODE_SCALE);
|
||||
ntype.ui_name = "Scale";
|
||||
ntype.enum_name_legacy = "SCALE";
|
||||
ntype.nclass = NODE_CLASS_DISTORT;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,110 @@
|
||||
/* SPDX-FileCopyrightText: 2022 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BLI_math_color.h"
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{-1, ""},
|
||||
};
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_FLOAT, N_("Red")},
|
||||
{SOCK_FLOAT, N_("Green")},
|
||||
{SOCK_FLOAT, N_("Blue")},
|
||||
{SOCK_FLOAT, N_("Alpha")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void apply_color_space(float *out, NodeCombSepColorMode type)
|
||||
{
|
||||
switch (type) {
|
||||
case NODE_COMBSEP_COLOR_RGB: {
|
||||
/* Pass */
|
||||
break;
|
||||
}
|
||||
case NODE_COMBSEP_COLOR_HSV: {
|
||||
rgb_to_hsv_v(out, out);
|
||||
break;
|
||||
}
|
||||
case NODE_COMBSEP_COLOR_HSL: {
|
||||
rgb_to_hsl_v(out, out);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void valuefn_r(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
tex_input_rgba(out, in[0], p, thread);
|
||||
apply_color_space(out, NodeCombSepColorMode(node->custom1));
|
||||
*out = out[0];
|
||||
}
|
||||
|
||||
static void valuefn_g(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
tex_input_rgba(out, in[0], p, thread);
|
||||
apply_color_space(out, NodeCombSepColorMode(node->custom1));
|
||||
*out = out[1];
|
||||
}
|
||||
|
||||
static void valuefn_b(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
tex_input_rgba(out, in[0], p, thread);
|
||||
apply_color_space(out, NodeCombSepColorMode(node->custom1));
|
||||
*out = out[2];
|
||||
}
|
||||
|
||||
static void valuefn_a(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
tex_input_rgba(out, in[0], p, thread);
|
||||
*out = out[3];
|
||||
}
|
||||
|
||||
static void update(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
node_combsep_color_label(&node->outputs, NodeCombSepColorMode(node->custom1));
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
TexCallData *tex_call_data = static_cast<TexCallData *>(data);
|
||||
tex_output(node, execdata, in, out[0], &valuefn_r, tex_call_data);
|
||||
tex_output(node, execdata, in, out[1], &valuefn_g, tex_call_data);
|
||||
tex_output(node, execdata, in, out[2], &valuefn_b, tex_call_data);
|
||||
tex_output(node, execdata, in, out[3], &valuefn_a, tex_call_data);
|
||||
}
|
||||
|
||||
void register_node_type_tex_separate_color()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeSeparateColor"_ustr, TEX_NODE_SEPARATE_COLOR);
|
||||
ntype.ui_name = "Separate Color";
|
||||
ntype.enum_name_legacy = "SEPARATE_COLOR";
|
||||
ntype.nclass = NODE_CLASS_OP_COLOR;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
ntype.updatefunc = update;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,91 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
#include "BKE_material.hh"
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
|
||||
#include "RE_texture.h"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Color1"), 1.0f, 1.0f, 1.0f, 1.0f},
|
||||
{SOCK_RGBA, N_("Color2"), 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
Tex *nodetex = id_cast<Tex *>(node->id);
|
||||
static float red[] = {1, 0, 0, 1};
|
||||
static float white[] = {1, 1, 1, 1};
|
||||
float co[3];
|
||||
|
||||
copy_v3_v3(co, p->co);
|
||||
|
||||
if (node->custom2 || node->runtime->need_exec == 0) {
|
||||
/* this node refers to its own texture tree! */
|
||||
copy_v4_v4(out, (fabsf(co[0] - co[1]) < 0.01f) ? white : red);
|
||||
}
|
||||
else if (nodetex) {
|
||||
TexResult texres;
|
||||
int textype;
|
||||
float col1[4], col2[4];
|
||||
|
||||
tex_input_rgba(col1, in[0], p, thread);
|
||||
tex_input_rgba(col2, in[1], p, thread);
|
||||
|
||||
textype = multitex_nodes(nodetex, co, &texres, thread, 0, p->mtex, nullptr);
|
||||
|
||||
if (textype & TEX_RGB) {
|
||||
copy_v4_v4(out, texres.trgba);
|
||||
}
|
||||
else {
|
||||
copy_v4_v4(out, col1);
|
||||
ramp_blend(MA_RAMP_BLEND, out, texres.tin, col2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_texture()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeTexture"_ustr, TEX_NODE_TEXTURE);
|
||||
ntype.ui_name = "Texture";
|
||||
ntype.enum_name_legacy = "TEXTURE";
|
||||
ntype.nclass = NODE_CLASS_INPUT;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
ntype.flag |= NODE_PREVIEW;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,62 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{SOCK_VECTOR, N_("Offset"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_TRANSLATION},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
float offset[3], new_co[3];
|
||||
TexParams np = *p;
|
||||
np.co = new_co;
|
||||
|
||||
tex_input_vec(offset, in[1], p, thread);
|
||||
|
||||
new_co[0] = p->co[0] + offset[0];
|
||||
new_co[1] = p->co[1] + offset[1];
|
||||
new_co[2] = p->co[2] + offset[2];
|
||||
|
||||
tex_input_rgba(out, in[0], &np, thread);
|
||||
}
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_translate()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeTranslate"_ustr, TEX_NODE_TRANSLATE);
|
||||
ntype.ui_name = "Translate";
|
||||
ntype.enum_name_legacy = "TRANSLATE";
|
||||
ntype.nclass = NODE_CLASS_DISTORT;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,79 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_FLOAT, N_("Val"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, N_("Nabla"), 0.025f, 0.0f, 0.0f, 0.0f, 0.001f, 0.1f, PROP_UNSIGNED},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bke::bNodeSocketTemplate outputs[] = {
|
||||
{SOCK_VECTOR, N_("Normal")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void normalfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
float new_co[3];
|
||||
const float *co = p->co;
|
||||
|
||||
float nabla = tex_input_value(in[1], p, thread);
|
||||
float val;
|
||||
float nor[3];
|
||||
|
||||
TexParams np = *p;
|
||||
np.co = new_co;
|
||||
|
||||
val = tex_input_value(in[0], p, thread);
|
||||
|
||||
new_co[0] = co[0] + nabla;
|
||||
new_co[1] = co[1];
|
||||
new_co[2] = co[2];
|
||||
nor[0] = tex_input_value(in[0], &np, thread);
|
||||
|
||||
new_co[0] = co[0];
|
||||
new_co[1] = co[1] + nabla;
|
||||
nor[1] = tex_input_value(in[0], &np, thread);
|
||||
|
||||
new_co[1] = co[1];
|
||||
new_co[2] = co[2] + nabla;
|
||||
nor[2] = tex_input_value(in[0], &np, thread);
|
||||
|
||||
out[0] = val - nor[0];
|
||||
out[1] = val - nor[1];
|
||||
out[2] = val - nor[2];
|
||||
}
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &normalfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_valtonor()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeValToNor"_ustr, TEX_NODE_VALTONOR);
|
||||
ntype.ui_name = "Value to Normal";
|
||||
ntype.enum_name_legacy = "VALTONOR";
|
||||
ntype.nclass = NODE_CLASS_CONVERTER;
|
||||
bke::node_type_socket_templates(&ntype, inputs, outputs);
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,110 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "BKE_colorband.hh"
|
||||
#include "IMB_colormanagement.hh"
|
||||
#include "node_texture_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* **************** VALTORGB ******************** */
|
||||
static bke::bNodeSocketTemplate valtorgb_in[] = {
|
||||
{SOCK_FLOAT, N_("Fac"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{-1, ""},
|
||||
};
|
||||
static bke::bNodeSocketTemplate valtorgb_out[] = {
|
||||
{SOCK_RGBA, N_("Color")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void valtorgb_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
|
||||
{
|
||||
if (node->storage) {
|
||||
float fac = tex_input_value(in[0], p, thread);
|
||||
|
||||
BKE_colorband_evaluate(static_cast<const ColorBand *>(node->storage), fac, out);
|
||||
}
|
||||
}
|
||||
|
||||
static void valtorgb_exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &valtorgb_colorfn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
static void valtorgb_init(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
node->storage = BKE_colorband_add(true);
|
||||
}
|
||||
|
||||
void register_node_type_tex_valtorgb()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeValToRGB"_ustr, TEX_NODE_VALTORGB);
|
||||
ntype.ui_name = "Color Ramp";
|
||||
ntype.enum_name_legacy = "VALTORGB";
|
||||
ntype.nclass = NODE_CLASS_CONVERTER;
|
||||
bke::node_type_socket_templates(&ntype, valtorgb_in, valtorgb_out);
|
||||
ntype.default_width = bke::NodeWidth::_240;
|
||||
ntype.initfunc = valtorgb_init;
|
||||
bke::node_type_storage(
|
||||
ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.exec_fn = valtorgb_exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
/* **************** RGBTOBW ******************** */
|
||||
static bke::bNodeSocketTemplate rgbtobw_in[] = {
|
||||
{SOCK_RGBA, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
|
||||
{-1, ""},
|
||||
};
|
||||
static bke::bNodeSocketTemplate rgbtobw_out[] = {
|
||||
{SOCK_FLOAT, N_("Val"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void rgbtobw_valuefn(
|
||||
float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
float cin[4];
|
||||
tex_input_rgba(cin, in[0], p, thread);
|
||||
*out = IMB_colormanagement_get_luminance(cin);
|
||||
}
|
||||
|
||||
static void rgbtobw_exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode *node,
|
||||
bNodeExecData *execdata,
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
tex_output(node, execdata, in, out[0], &rgbtobw_valuefn, static_cast<TexCallData *>(data));
|
||||
}
|
||||
|
||||
void register_node_type_tex_rgbtobw()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeRGBToBW"_ustr, TEX_NODE_RGBTOBW);
|
||||
ntype.ui_name = "RGB to BW";
|
||||
ntype.enum_name_legacy = "RGBTOBW";
|
||||
ntype.nclass = NODE_CLASS_CONVERTER;
|
||||
bke::node_type_socket_templates(&ntype, rgbtobw_in, rgbtobw_out);
|
||||
ntype.exec_fn = rgbtobw_exec;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,53 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup texnodes
|
||||
*/
|
||||
|
||||
#include "node_texture_util.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bke::bNodeSocketTemplate inputs[] = {
|
||||
{SOCK_RGBA, N_("Color"), 1.0f, 0.0f, 0.0f, 1.0f},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void exec(void *data,
|
||||
int /*thread*/,
|
||||
bNode * /*node*/,
|
||||
bNodeExecData * /*execdata*/,
|
||||
bNodeStack **in,
|
||||
bNodeStack ** /*out*/)
|
||||
{
|
||||
TexCallData *cdata = static_cast<TexCallData *>(data);
|
||||
|
||||
if (cdata->do_preview) {
|
||||
TexParams params;
|
||||
float col[4];
|
||||
params_from_cdata(¶ms, cdata);
|
||||
|
||||
tex_input_rgba(col, in[0], ¶ms, cdata->thread);
|
||||
}
|
||||
}
|
||||
|
||||
void register_node_type_tex_viewer()
|
||||
{
|
||||
static bke::bNodeType ntype;
|
||||
|
||||
tex_node_type_base(&ntype, "TextureNodeViewer"_ustr, TEX_NODE_VIEWER);
|
||||
ntype.ui_name = "Viewer";
|
||||
ntype.enum_name_legacy = "VIEWER";
|
||||
ntype.nclass = NODE_CLASS_OUTPUT;
|
||||
bke::node_type_socket_templates(&ntype, inputs, nullptr);
|
||||
ntype.exec_fn = exec;
|
||||
|
||||
ntype.no_muting = true;
|
||||
ntype.flag |= NODE_PREVIEW;
|
||||
|
||||
bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
Reference in New Issue
Block a user