forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			193 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			193 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | 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') |