forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
6
leenkx/blender/lnx/material/lnx_nodes/__init__.py
Normal file
6
leenkx/blender/lnx/material/lnx_nodes/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
"""Import all nodes"""
|
||||
import glob
|
||||
from os.path import dirname, basename, isfile
|
||||
|
||||
modules = glob.glob(dirname(__file__) + "/*.py")
|
||||
__all__ = [basename(f)[:-3] for f in modules if isfile(f)]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
192
leenkx/blender/lnx/material/lnx_nodes/custom_particle_node.py
Normal file
192
leenkx/blender/lnx/material/lnx_nodes/custom_particle_node.py
Normal file
@ -0,0 +1,192 @@
|
||||
from bpy.props import *
|
||||
from bpy.types import Node
|
||||
|
||||
from lnx.material.lnx_nodes.lnx_nodes import add_node
|
||||
from lnx.material.shader import Shader
|
||||
from lnx.material.cycles import *
|
||||
|
||||
if lnx.is_reload(__name__):
|
||||
import lnx
|
||||
lnx.material.lnx_nodes.lnx_nodes = lnx.reload_module(lnx.material.lnx_nodes.lnx_nodes)
|
||||
from lnx.material.lnx_nodes.lnx_nodes import add_node
|
||||
lnx.material.shader = lnx.reload_module(lnx.material.shader)
|
||||
from lnx.material.shader import Shader
|
||||
lnx.material.cycles = lnx.reload_module(lnx.material.cycles)
|
||||
from lnx.material.cycles import *
|
||||
else:
|
||||
lnx.enable_reload(__name__)
|
||||
|
||||
|
||||
class CustomParticleNode(Node):
|
||||
"""Input data for paricles."""
|
||||
bl_idname = 'LnxCustomParticleNode'
|
||||
bl_label = 'Custom Particle'
|
||||
bl_icon = 'NONE'
|
||||
|
||||
posX: BoolProperty(
|
||||
name="",
|
||||
description="enable translation along x",
|
||||
default=False,
|
||||
)
|
||||
|
||||
posY: BoolProperty(
|
||||
name="",
|
||||
description="enable translation along y",
|
||||
default=False,
|
||||
)
|
||||
|
||||
posZ: BoolProperty(
|
||||
name="",
|
||||
description="enable translation along z",
|
||||
default=False,
|
||||
)
|
||||
|
||||
rotX: BoolProperty(
|
||||
name="",
|
||||
description="enable rotation along x",
|
||||
default=False,
|
||||
)
|
||||
|
||||
rotY: BoolProperty(
|
||||
name="",
|
||||
description="enable rotation along y",
|
||||
default=False,
|
||||
)
|
||||
|
||||
rotZ: BoolProperty(
|
||||
name="",
|
||||
description="enable rotation along z",
|
||||
default=False,
|
||||
)
|
||||
|
||||
sclX: BoolProperty(
|
||||
name="",
|
||||
description="enable scaling along x",
|
||||
default=False,
|
||||
)
|
||||
|
||||
sclY: BoolProperty(
|
||||
name="",
|
||||
description="enable scaling along y",
|
||||
default=False,
|
||||
)
|
||||
|
||||
sclZ: BoolProperty(
|
||||
name="",
|
||||
description="enable scaling along z",
|
||||
default=False,
|
||||
)
|
||||
|
||||
billBoard: BoolProperty(
|
||||
name="Bill Board",
|
||||
description="Enable Bill Board",
|
||||
default=False,
|
||||
)
|
||||
|
||||
def init(self, context):
|
||||
self.inputs.new('NodeSocketVector', 'Position')
|
||||
self.inputs.new('NodeSocketVector', 'Rotation')
|
||||
self.inputs.new('NodeSocketVector', 'Scale')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
|
||||
grid0 = layout.grid_flow(row_major=True, columns=4, align=False)
|
||||
|
||||
grid0.label(text="")
|
||||
grid0.label(text=" X")
|
||||
grid0.label(text=" Y")
|
||||
grid0.label(text=" Z")
|
||||
|
||||
grid0.label(text="Pos")
|
||||
grid0.prop(self, "posX")
|
||||
grid0.prop(self, "posY")
|
||||
grid0.prop(self, "posZ")
|
||||
|
||||
grid0.label(text="Rot")
|
||||
grid0.prop(self, "rotX")
|
||||
grid0.prop(self, "rotY")
|
||||
grid0.prop(self, "rotZ")
|
||||
|
||||
grid0.label(text="Scl")
|
||||
grid0.prop(self, "sclX")
|
||||
grid0.prop(self, "sclY")
|
||||
grid0.prop(self, "sclZ")
|
||||
|
||||
layout.prop(self, "billBoard")
|
||||
|
||||
def parse(self, vertshdr: Shader, part_con) -> None:
|
||||
|
||||
if self.sclX or self.sclY or self.sclZ:
|
||||
scl = parse_vector_input(self.inputs[2])
|
||||
|
||||
if self.sclX:
|
||||
vertshdr.write(f'spos.x *= {scl}.x;')
|
||||
|
||||
if self.sclY:
|
||||
vertshdr.write(f'spos.y *= {scl}.y;')
|
||||
|
||||
if self.sclX:
|
||||
vertshdr.write(f'spos.z *= {scl}.z;')
|
||||
|
||||
if self.billBoard:
|
||||
vertshdr.add_uniform('mat4 WV', '_worldViewMatrix')
|
||||
vertshdr.write('spos = mat4(transpose(mat3(WV))) * spos;')
|
||||
|
||||
if self.rotX or self.rotY or self.rotZ:
|
||||
rot = parse_vector_input(self.inputs[1])
|
||||
|
||||
if self.rotX and not self.rotY and not self.rotZ:
|
||||
vertshdr.write(f'mat3 part_rot_mat = mat3(1.0, 0.0, 0.0,')
|
||||
vertshdr.write(f' 0.0, cos({rot}.x), sin({rot}.x),')
|
||||
vertshdr.write(f' 0.0, -sin({rot}.x), cos({rot}.x));')
|
||||
|
||||
if not self.rotX and self.rotY and not self.rotZ:
|
||||
vertshdr.write(f'mat3 part_rot_mat = mat3(cos({rot}.y), 0.0, -sin({rot}.y),')
|
||||
vertshdr.write(f' 0.0, 1.0, 0.0,')
|
||||
vertshdr.write(f' sin({rot}.y), 0.0, cos({rot}.y));')
|
||||
|
||||
if not self.rotX and not self.rotY and self.rotZ:
|
||||
vertshdr.write(f'mat3 part_rot_mat = mat3(cos({rot}.z), sin({rot}.z), 0.0,')
|
||||
vertshdr.write(f' -sin({rot}.z), cos({rot}.z), 0.0,')
|
||||
vertshdr.write(f' 0.0, 0.0, 1.0);')
|
||||
|
||||
if self.rotX and self.rotY and not self.rotZ:
|
||||
vertshdr.write(f'mat3 part_rot_mat = mat3(cos({rot}.y), 0.0, -sin({rot}.y),')
|
||||
vertshdr.write(f' sin({rot}.y) * sin({rot}.x), cos({rot}.x), cos({rot}.y) * sin({rot}.x),')
|
||||
vertshdr.write(f' sin({rot}.y) * cos({rot}.x), -sin({rot}.x), cos({rot}.y) * cos({rot}.x));')
|
||||
|
||||
if self.rotX and not self.rotY and self.rotZ:
|
||||
vertshdr.write(f'mat3 part_rot_mat = mat3(cos({rot}.z), sin({rot}.z), 0.0,')
|
||||
vertshdr.write(f' -sin({rot}.z) * cos({rot}.x), cos({rot}.z) * cos({rot}.x), sin({rot}.x),')
|
||||
vertshdr.write(f' sin({rot}.z) * sin({rot}.x), -cos({rot}.z) * sin({rot}.x), cos({rot}.x));')
|
||||
|
||||
if not self.rotX and self.rotY and self.rotZ:
|
||||
vertshdr.write(f'mat3 part_rot_mat = mat3(cos({rot}.z) * cos({rot}.y), sin({rot}.z) * cos({rot}.y), -sin({rot}.y),')
|
||||
vertshdr.write(f' -sin({rot}.z) , cos({rot}.z), 0.0,')
|
||||
vertshdr.write(f' cos({rot}.z) * sin({rot}.y), sin({rot}.z) * sin({rot}.y), cos({rot}.y));')
|
||||
|
||||
if self.rotX and self.rotY and self.rotZ:
|
||||
vertshdr.write(f'mat3 part_rot_mat = mat3(cos({rot}.z) * cos({rot}.y), sin({rot}.z) * cos({rot}.y), -sin({rot}.y),')
|
||||
vertshdr.write(f' -sin({rot}.z) * cos({rot}.x) + cos({rot}.z) * sin({rot}.y) * sin({rot}.x), cos({rot}.z) * cos({rot}.x) + sin({rot}.z) * sin({rot}.y) * sin({rot}.x), cos({rot}.y) * sin({rot}.x),')
|
||||
vertshdr.write(f' sin({rot}.z) * sin({rot}.x) + cos({rot}.z) * sin({rot}.y) * cos({rot}.x), -cos({rot}.z) * sin({rot}.x) + sin({rot}.z) * sin({rot}.y) * cos({rot}.x), cos({rot}.y) * cos({rot}.x));')
|
||||
|
||||
vertshdr.write('spos.xyz = part_rot_mat * spos.xyz;')
|
||||
if (part_con.data['name'] == 'mesh' or part_con.data['name'] == 'translucent' or part_con.data['name'] == 'refraction'):
|
||||
vertshdr.write('wnormal = transpose(inverse(part_rot_mat)) * wnormal;')
|
||||
|
||||
if self.posX or self.posY or self.posZ:
|
||||
pos = parse_vector_input(self.inputs[0])
|
||||
|
||||
if self.posX:
|
||||
vertshdr.write(f'spos.x += {pos}.x;')
|
||||
|
||||
if self.posY:
|
||||
vertshdr.write(f'spos.y += {pos}.y;')
|
||||
|
||||
if self.posZ:
|
||||
vertshdr.write(f'spos.z += {pos}.z;')
|
||||
|
||||
vertshdr.write('wposition = vec4(W * spos).xyz;')
|
||||
|
||||
|
||||
add_node(CustomParticleNode, category='Leenkx')
|
15
leenkx/blender/lnx/material/lnx_nodes/lnx_nodes.py
Normal file
15
leenkx/blender/lnx/material/lnx_nodes/lnx_nodes.py
Normal file
@ -0,0 +1,15 @@
|
||||
from typing import Type
|
||||
|
||||
from bpy.types import Node
|
||||
import nodeitems_utils
|
||||
|
||||
nodes = []
|
||||
category_items = {}
|
||||
|
||||
|
||||
def add_node(node_class: Type[Node], category: str):
|
||||
global nodes
|
||||
nodes.append(node_class)
|
||||
if category_items.get(category) is None:
|
||||
category_items[category] = []
|
||||
category_items[category].append(nodeitems_utils.NodeItem(node_class.bl_idname))
|
110
leenkx/blender/lnx/material/lnx_nodes/shader_data_node.py
Normal file
110
leenkx/blender/lnx/material/lnx_nodes/shader_data_node.py
Normal file
@ -0,0 +1,110 @@
|
||||
from bpy.props import *
|
||||
from bpy.types import Node, NodeSocket
|
||||
|
||||
import lnx
|
||||
from lnx.material.lnx_nodes.lnx_nodes import add_node
|
||||
from lnx.material.parser_state import ParserState
|
||||
from lnx.material.shader import Shader
|
||||
|
||||
if lnx.is_reload(__name__):
|
||||
lnx.material.lnx_nodes.lnx_nodes = lnx.reload_module(lnx.material.lnx_nodes.lnx_nodes)
|
||||
from lnx.material.lnx_nodes.lnx_nodes import add_node
|
||||
lnx.material.parser_state = lnx.reload_module(lnx.material.parser_state)
|
||||
from lnx.material.parser_state import ParserState
|
||||
lnx.material.shader = lnx.reload_module(lnx.material.shader)
|
||||
from lnx.material.shader import Shader
|
||||
else:
|
||||
lnx.enable_reload(__name__)
|
||||
|
||||
|
||||
class ShaderDataNode(Node):
|
||||
"""Allows access to shader data such as uniforms and inputs."""
|
||||
bl_idname = 'LnxShaderDataNode'
|
||||
bl_label = 'Shader Data'
|
||||
bl_icon = 'NONE'
|
||||
|
||||
input_type: EnumProperty(
|
||||
items = [('input', 'Input', 'Shader Input'),
|
||||
('uniform', 'Uniform', 'Uniform value')],
|
||||
name='Input Type',
|
||||
default='input',
|
||||
description="The kind of data that should be retrieved")
|
||||
|
||||
input_source: EnumProperty(
|
||||
items = [('frag', 'Fragment Shader', 'Take the input from the fragment shader'),
|
||||
('vert', 'Vertex Shader', 'Take the input from the vertex shader and pass it through to the fragment shader')],
|
||||
name='Input Source',
|
||||
default='vert',
|
||||
description="Where to take the input value from")
|
||||
|
||||
variable_type: EnumProperty(
|
||||
items = [('int', 'int', 'int'),
|
||||
('float', 'float', 'float'),
|
||||
('vec2', 'vec2', 'vec2'),
|
||||
('vec3', 'vec3', 'vec3'),
|
||||
('vec4', 'vec4', 'vec4'),
|
||||
('sampler2D', 'sampler2D', 'sampler2D')],
|
||||
name='Variable Type',
|
||||
default='vec3',
|
||||
description="The type of the variable")
|
||||
|
||||
variable_name: StringProperty(name="Variable Name", description="The name of the variable")
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Input Type:")
|
||||
# Use a row to expand horizontally
|
||||
col.row().prop(self, "input_type", expand=True)
|
||||
|
||||
split = layout.split(factor=0.5, align=True)
|
||||
col_left = split.column()
|
||||
col_right = split.column()
|
||||
|
||||
if self.input_type == "input":
|
||||
col_left.label(text="Input Source")
|
||||
col_right.prop(self, "input_source", text="")
|
||||
|
||||
col_left.label(text="Variable Type")
|
||||
col_right.prop(self, "variable_type", text="")
|
||||
col_left.label(text="Variable Name")
|
||||
col_right.prop(self, "variable_name", text="")
|
||||
|
||||
def init(self, context):
|
||||
self.outputs.new('NodeSocketColor', 'Color')
|
||||
self.outputs.new('NodeSocketVector', 'Vector')
|
||||
self.outputs.new('NodeSocketFloat', 'Float')
|
||||
self.outputs.new('NodeSocketInt', 'Int')
|
||||
|
||||
def __parse(self, out_socket: NodeSocket, state: ParserState) -> str:
|
||||
if self.input_type == "uniform":
|
||||
state.frag.add_uniform(f'{self.variable_type} {self.variable_name}', link=self.variable_name)
|
||||
state.vert.add_uniform(f'{self.variable_type} {self.variable_name}', link=self.variable_name)
|
||||
|
||||
if self.variable_type == "sampler2D":
|
||||
state.frag.add_uniform('vec2 screenSize', link='_screenSize')
|
||||
return f'textureLod({self.variable_name}, gl_FragCoord.xy / screenSize, 0.0).rgb'
|
||||
|
||||
if self.variable_type == "vec2":
|
||||
return f'vec3({self.variable_name}.xy, 0)'
|
||||
|
||||
return self.variable_name
|
||||
|
||||
else:
|
||||
if self.input_source == "frag":
|
||||
state.frag.add_in(f'{self.variable_type} {self.variable_name}')
|
||||
return self.variable_name
|
||||
|
||||
# Reroute input from vertex shader to fragment shader (input must exist!)
|
||||
else:
|
||||
state.vert.add_out(f'{self.variable_type} out_{self.variable_name}')
|
||||
state.frag.add_in(f'{self.variable_type} out_{self.variable_name}')
|
||||
|
||||
state.vert.write(f'out_{self.variable_name} = {self.variable_name};')
|
||||
return 'out_' + self.variable_name
|
||||
|
||||
@staticmethod
|
||||
def parse(node: 'ShaderDataNode', out_socket: NodeSocket, state: ParserState) -> str:
|
||||
return node.__parse(out_socket, state)
|
||||
|
||||
|
||||
add_node(ShaderDataNode, category='Leenkx')
|
Reference in New Issue
Block a user