merge upstream
This commit is contained in:
		@ -191,7 +191,7 @@ def apply_materials(load_atlas=0):
 | 
			
		||||
 | 
			
		||||
                                mainNode = outputNode.inputs[0].links[0].from_node.inputs[0].links[0].from_node
 | 
			
		||||
 | 
			
		||||
                            if (mainNode.type == "ShaderNodeMixRGB"):
 | 
			
		||||
                            if (mainNode.type == "ShaderNodeMix"):
 | 
			
		||||
                                if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
 | 
			
		||||
                                    print("Mix RGB shader found")
 | 
			
		||||
                                
 | 
			
		||||
@ -199,9 +199,11 @@ def apply_materials(load_atlas=0):
 | 
			
		||||
 | 
			
		||||
                            #Add all nodes first
 | 
			
		||||
                            #Add lightmap multipliction texture
 | 
			
		||||
                            mixNode = node_tree.nodes.new(type="ShaderNodeMixRGB")
 | 
			
		||||
                            mixNode = node_tree.nodes.new(type="ShaderNodeMix")
 | 
			
		||||
                            mixNode.name = "Lightmap_Multiplication"
 | 
			
		||||
                            mixNode.location = -800, 300
 | 
			
		||||
                            mixNode.data_type = 'RGBA'
 | 
			
		||||
                            mixNode.inputs[0].default_value = 1
 | 
			
		||||
                            if scene.TLM_EngineProperties.tlm_lighting_mode == "indirect" or scene.TLM_EngineProperties.tlm_lighting_mode == "indirectAO":
 | 
			
		||||
                                mixNode.blend_type = 'MULTIPLY'
 | 
			
		||||
                            else:
 | 
			
		||||
@ -312,8 +314,8 @@ def apply_materials(load_atlas=0):
 | 
			
		||||
                                    else:
 | 
			
		||||
                                        mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
 | 
			
		||||
 | 
			
		||||
                                    mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect decode node to mixnode
 | 
			
		||||
                                    mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect exposure node to mixnode
 | 
			
		||||
                                    mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[6]) #Connect decode node to mixnode
 | 
			
		||||
                                    mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[6]) #Connect exposure node to mixnode
 | 
			
		||||
                                
 | 
			
		||||
                                else:
 | 
			
		||||
                                    
 | 
			
		||||
@ -323,10 +325,10 @@ def apply_materials(load_atlas=0):
 | 
			
		||||
                                    else:
 | 
			
		||||
                                        mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
 | 
			
		||||
 | 
			
		||||
                                    mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
 | 
			
		||||
                                    mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
 | 
			
		||||
                                
 | 
			
		||||
                                mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
 | 
			
		||||
                                mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
 | 
			
		||||
                                mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[7]) #Connect basecolor to pbr node
 | 
			
		||||
                                mat.node_tree.links.new(mixNode.outputs[2], mainNode.inputs[0]) #Connect mixnode to pbr node
 | 
			
		||||
 | 
			
		||||
                                if not scene.TLM_EngineProperties.tlm_target == "vertex":
 | 
			
		||||
                                    mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
 | 
			
		||||
@ -338,11 +340,11 @@ def apply_materials(load_atlas=0):
 | 
			
		||||
 | 
			
		||||
                                if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
 | 
			
		||||
                                    mat.node_tree.links.new(lightmapNode.outputs[0], ExposureNode.inputs[0]) #Connect lightmap node to mixnode
 | 
			
		||||
                                    mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
 | 
			
		||||
                                    mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
 | 
			
		||||
                                else:
 | 
			
		||||
                                    mat.node_tree.links.new(lightmapNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
 | 
			
		||||
                                mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
 | 
			
		||||
                                mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
 | 
			
		||||
                                    mat.node_tree.links.new(lightmapNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
 | 
			
		||||
                                mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[7]) #Connect basecolor to pbr node
 | 
			
		||||
                                mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[2]) #Connect mixnode to pbr node
 | 
			
		||||
                                if not scene.TLM_EngineProperties.tlm_target == "vertex":
 | 
			
		||||
                                    mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
 | 
			
		||||
 | 
			
		||||
@ -491,8 +493,9 @@ def applyAOPass():
 | 
			
		||||
                                AOMap.image = AOImage
 | 
			
		||||
                                AOMap.location = -800, 0
 | 
			
		||||
 | 
			
		||||
                                AOMult = nodes.new(type="ShaderNodeMixRGB")
 | 
			
		||||
                                AOMult = nodes.new(type="ShaderNodeMix")
 | 
			
		||||
                                AOMult.name = "TLM_AOMult"
 | 
			
		||||
                                AOMult.data_type = 'RGBA'
 | 
			
		||||
                                AOMult.blend_type = 'MULTIPLY'
 | 
			
		||||
                                AOMult.inputs[0].default_value = 1.0
 | 
			
		||||
                                AOMult.location = -300, 300
 | 
			
		||||
 | 
			
		||||
@ -518,7 +518,7 @@ def configure_meshes(self):
 | 
			
		||||
                                if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
 | 
			
		||||
                                    print("The material group is not supported!")
 | 
			
		||||
 | 
			
		||||
                        if (mainNode.type == "ShaderNodeMixRGB"):
 | 
			
		||||
                        if (mainNode.type == "ShaderNodeMix"):
 | 
			
		||||
                            if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
 | 
			
		||||
                                print("Mix shader found")
 | 
			
		||||
 | 
			
		||||
@ -811,7 +811,7 @@ def set_settings():
 | 
			
		||||
    
 | 
			
		||||
    print(bpy.app.version)
 | 
			
		||||
 | 
			
		||||
    if bpy.app.version[0] == 3:
 | 
			
		||||
    if bpy.app.version[0] == 3 or byp.app.version[0] == 4:
 | 
			
		||||
        if cycles.device == "GPU":
 | 
			
		||||
            scene.cycles.tile_size = 256
 | 
			
		||||
        else:
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,11 @@ class ViewportDraw:
 | 
			
		||||
        w = 400
 | 
			
		||||
        h = 200
 | 
			
		||||
 | 
			
		||||
        self.shader = gpu.shader.from_builtin('2D_IMAGE')
 | 
			
		||||
        if bpy.app.version[0] == 3:
 | 
			
		||||
            self.shader = gpu.shader.from_builtin('2D_IMAGE')
 | 
			
		||||
        else:
 | 
			
		||||
            self.shader = gpu.shader.from_builtin('IMAGE')
 | 
			
		||||
            
 | 
			
		||||
        self.batch = batch_for_shader(
 | 
			
		||||
            self.shader, 'TRI_FAN',
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,7 @@ class Shader_Node_Types:
 | 
			
		||||
    normal = "ShaderNodeNormalMap"
 | 
			
		||||
    ao = "ShaderNodeAmbientOcclusion"
 | 
			
		||||
    uv = "ShaderNodeUVMap"
 | 
			
		||||
    mix = "ShaderNodeMixRGB"
 | 
			
		||||
    mix = "ShaderNodeMix"
 | 
			
		||||
 | 
			
		||||
def select_object(self,obj):
 | 
			
		||||
    C = bpy.context
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,8 @@ def init_categories():
 | 
			
		||||
    lnx_nodes.add_category('Navmesh', icon='UV_VERTEXSEL', section="motion")
 | 
			
		||||
    lnx_nodes.add_category('Transform', icon='TRANSFORM_ORIGINS', section="motion")
 | 
			
		||||
    lnx_nodes.add_category('Physics', icon='PHYSICS', section="motion")
 | 
			
		||||
 | 
			
		||||
    lnx_nodes.add_category('Particle', icon='PARTICLE_DATA', section="motion")
 | 
			
		||||
    
 | 
			
		||||
    lnx_nodes.add_category('Array', icon='MOD_ARRAY', section="values")
 | 
			
		||||
    lnx_nodes.add_category('Map', icon='SHORTDISPLAY', section="values")
 | 
			
		||||
    lnx_nodes.add_category('Database', icon='MESH_CYLINDER', section="values")
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,15 @@ class DrawCameraTextureNode(LnxLogicTreeNode):
 | 
			
		||||
    @input Object: Object of which to choose the material in the `Material Slot` input.
 | 
			
		||||
    @input Material Slot: Index of the material slot of which the diffuse
 | 
			
		||||
        texture is replaced with the camera's render target.
 | 
			
		||||
 | 
			
		||||
    @input Node: Node name of the Image Texture Node.
 | 
			
		||||
    
 | 
			
		||||
    @output On Start: Activated after the `Start` input has been activated.
 | 
			
		||||
    @output On Stop: Activated after the `Stop` input has been activated.
 | 
			
		||||
    """
 | 
			
		||||
    bl_idname = 'LNDrawCameraTextureNode'
 | 
			
		||||
    bl_label = 'Draw Camera to Texture'
 | 
			
		||||
    lnx_section = 'draw'
 | 
			
		||||
    lnx_version = 1
 | 
			
		||||
    lnx_version = 2
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.add_input('LnxNodeSocketAction', 'Start')
 | 
			
		||||
@ -26,6 +27,13 @@ class DrawCameraTextureNode(LnxLogicTreeNode):
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'Camera')
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'Object')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'Material Slot')
 | 
			
		||||
 | 
			
		||||
        self.add_input('LnxStringSocket', 'Node')
 | 
			
		||||
        
 | 
			
		||||
        self.add_output('LnxNodeSocketAction', 'On Start')
 | 
			
		||||
        self.add_output('LnxNodeSocketAction', 'On Stop')
 | 
			
		||||
 | 
			
		||||
    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
			
		||||
        if self.lnx_version not in (0, 1):
 | 
			
		||||
            raise LookupError()
 | 
			
		||||
 | 
			
		||||
        return NodeReplacement.Identity(self)
 | 
			
		||||
							
								
								
									
										44
									
								
								leenkx/blender/lnx/logicnode/draw/LN_draw_sub_image.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								leenkx/blender/lnx/logicnode/draw/LN_draw_sub_image.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
from lnx.logicnode.lnx_nodes import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DrawSubImageNode(LnxLogicTreeNode):
 | 
			
		||||
    """Draws an image.
 | 
			
		||||
    @input Draw: Activate to draw the image on this frame. The input must
 | 
			
		||||
        be (indirectly) called from an `On Render2D` node.
 | 
			
		||||
    @input Image: The filename of the image.
 | 
			
		||||
    @input Color: The color that the image's pixels are multiplied with.
 | 
			
		||||
    @input Left/Center/Right: Horizontal anchor point of the image.
 | 
			
		||||
        0 = Left, 1 = Center, 2 = Right
 | 
			
		||||
    @input Top/Middle/Bottom: Vertical anchor point of the image.
 | 
			
		||||
        0 = Top, 1 = Middle, 2 = Bottom
 | 
			
		||||
    @input X/Y: Position of the anchor point in pixels.
 | 
			
		||||
    @input Width/Height: Size of the sub image in pixels.
 | 
			
		||||
    @input sX/Y: Position of the sub anchor point in pixels.
 | 
			
		||||
    @input sWidth/Height: Size of the image in pixels.
 | 
			
		||||
    @input Angle: Rotation angle in radians. Image will be rotated cloclwiswe
 | 
			
		||||
        at the anchor point.
 | 
			
		||||
    @output Out: Activated after the image has been drawn.
 | 
			
		||||
    @see [`kha.graphics2.Graphics.drawImage()`](http://kha.tech/api/kha/graphics2/Graphics.html#drawImage).
 | 
			
		||||
    """
 | 
			
		||||
    bl_idname = 'LNDrawSubImageNode'
 | 
			
		||||
    bl_label = 'Draw Sub Image'
 | 
			
		||||
    lnx_section = 'draw'
 | 
			
		||||
    lnx_version = 1
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.add_input('LnxNodeSocketAction', 'Draw')
 | 
			
		||||
        self.add_input('LnxStringSocket', 'Image File')
 | 
			
		||||
        self.add_input('LnxColorSocket', 'Color', default_value=[1.0, 1.0, 1.0, 1.0])
 | 
			
		||||
        self.add_input('LnxIntSocket', '0/1/2 = Left/Center/Right', default_value=0)
 | 
			
		||||
        self.add_input('LnxIntSocket', '0/1/2 = Top/Middle/Bottom', default_value=0)
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'X')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'Y')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'Width')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'Height')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'sX')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'sY')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'sWidth')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'sHeight')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'Angle')
 | 
			
		||||
 | 
			
		||||
        self.add_output('LnxNodeSocketAction', 'Out') 
 | 
			
		||||
@ -5,8 +5,6 @@ class WriteFileNode(LnxLogicTreeNode):
 | 
			
		||||
    """Writes the given string content to the given file. If the file
 | 
			
		||||
    already exists, the existing content of the file is overwritten.
 | 
			
		||||
 | 
			
		||||
    > **This node is currently only implemented on Krom**
 | 
			
		||||
 | 
			
		||||
    @input File: the name of the file, relative to `Krom.getFilesLocation()`
 | 
			
		||||
    @input Content: the content to write to the file.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										34
									
								
								leenkx/blender/lnx/logicnode/native/LN_write_image.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								leenkx/blender/lnx/logicnode/native/LN_write_image.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
from lnx.logicnode.lnx_nodes import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class WriteImageNode(LnxLogicTreeNode):
 | 
			
		||||
    """Writes the given image to the given file. If the image
 | 
			
		||||
    already exists, the existing content of the image is overwritten.
 | 
			
		||||
    Aspect ratio must match display resolution ratio.
 | 
			
		||||
    @input Image File: the name of the image, relative to `Krom.getFilesLocation()`
 | 
			
		||||
    @input Camera: the render target image of the camera to write to the image file.
 | 
			
		||||
    @input Width: width of the image file.
 | 
			
		||||
    @input Height: heigth of the image file.
 | 
			
		||||
    @input sX: sub position of first x pixel of the sub image (0 for start).
 | 
			
		||||
    @input sY: sub position of first y pixel of the sub image (0 for start).
 | 
			
		||||
    @input sWidth: width of the sub image.
 | 
			
		||||
    @input sHeight: height of the sub image.
 | 
			
		||||
    @seeNode Read File
 | 
			
		||||
    """
 | 
			
		||||
    bl_idname = 'LNWriteImageNode'
 | 
			
		||||
    bl_label = 'Write Image'
 | 
			
		||||
    lnx_section = 'file'
 | 
			
		||||
    lnx_version = 1
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.add_input('LnxNodeSocketAction', 'In')
 | 
			
		||||
        self.add_input('LnxStringSocket', 'Image File')
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'Camera')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'Width')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'Height')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'sX')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'sY')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'sWidth')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'sHeight')
 | 
			
		||||
 | 
			
		||||
        self.add_output('LnxNodeSocketAction', 'Out')
 | 
			
		||||
@ -5,8 +5,6 @@ class WriteJsonNode(LnxLogicTreeNode):
 | 
			
		||||
    """Writes the given content to the given JSON file. If the file
 | 
			
		||||
    already exists, the existing content of the file is overwritten.
 | 
			
		||||
 | 
			
		||||
    > **This node is currently only implemented on Krom**
 | 
			
		||||
 | 
			
		||||
    @input File: the name of the file, relative to `Krom.getFilesLocation()`,
 | 
			
		||||
        including the file extension.
 | 
			
		||||
    @input Dynamic: the content to write to the file. Can be any type that can
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
from lnx.logicnode.lnx_nodes import *
 | 
			
		||||
 | 
			
		||||
class AddParticleToObjectNode(LnxLogicTreeNode):
 | 
			
		||||
    """Sets the speed of the given particle source."""
 | 
			
		||||
    bl_idname = 'LNAddParticleToObjectNode'
 | 
			
		||||
    bl_label = 'Add Particle To Object'
 | 
			
		||||
    lnx_version = 1
 | 
			
		||||
 | 
			
		||||
    def remove_extra_inputs(self, context):
 | 
			
		||||
        while len(self.inputs) > 1:
 | 
			
		||||
            self.inputs.remove(self.inputs[-1])
 | 
			
		||||
        if self.property0 == 'Scene':
 | 
			
		||||
            self.add_input('LnxStringSocket', 'Scene From Name')
 | 
			
		||||
            self.add_input('LnxStringSocket', 'Object From Name')
 | 
			
		||||
        else:
 | 
			
		||||
            self.add_input('LnxNodeSocketObject', 'Object From')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'Slot')
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'Object To')
 | 
			
		||||
        self.add_input('LnxBoolSocket', 'Render Emitter', default_value = True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    property0: HaxeEnumProperty(
 | 
			
		||||
    'property0',
 | 
			
		||||
    items = [('Scene Active', 'Scene Active', 'Scene Active'),
 | 
			
		||||
             ('Scene', 'Scene', 'Scene')],
 | 
			
		||||
    name='', default='Scene Active', update=remove_extra_inputs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.add_input('LnxNodeSocketAction', 'In')
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'Object From')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'Slot')
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'Object To')
 | 
			
		||||
        self.add_input('LnxBoolSocket', 'Render Emitter', default_value = True)
 | 
			
		||||
 | 
			
		||||
        self.add_output('LnxNodeSocketAction', 'Out')
 | 
			
		||||
 | 
			
		||||
    def draw_buttons(self, context, layout):
 | 
			
		||||
        layout.prop(self, 'property0')
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								leenkx/blender/lnx/logicnode/particle/LN_get_particle.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								leenkx/blender/lnx/logicnode/particle/LN_get_particle.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
from lnx.logicnode.lnx_nodes import *
 | 
			
		||||
 | 
			
		||||
class GetParticleNode(LnxLogicTreeNode):
 | 
			
		||||
    """Returns the Particle Systems of an object."""
 | 
			
		||||
    bl_idname = 'LNGetParticleNode'
 | 
			
		||||
    bl_label = 'Get Particle'
 | 
			
		||||
    lnx_version = 1
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.inputs.new('LnxNodeSocketObject', 'Object')
 | 
			
		||||
 | 
			
		||||
        self.outputs.new('LnxNodeSocketArray', 'Names')
 | 
			
		||||
        self.outputs.new('LnxIntSocket', 'Length')
 | 
			
		||||
        self.outputs.new('LnxBoolSocket', 'Render Emitter')
 | 
			
		||||
@ -0,0 +1,31 @@
 | 
			
		||||
from lnx.logicnode.lnx_nodes import *
 | 
			
		||||
 | 
			
		||||
class GetParticleDataNode(LnxLogicTreeNode):
 | 
			
		||||
    """Returns the data of the given Particle System."""
 | 
			
		||||
    bl_idname = 'LNGetParticleDataNode'
 | 
			
		||||
    bl_label = 'Get Particle Data'
 | 
			
		||||
    lnx_version = 1
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.inputs.new('LnxNodeSocketObject', 'Object')
 | 
			
		||||
        self.inputs.new('LnxIntSocket', 'Slot')
 | 
			
		||||
 | 
			
		||||
        self.outputs.new('LnxStringSocket', 'Name')
 | 
			
		||||
        self.outputs.new('LnxFloatSocket', 'Particle Size')
 | 
			
		||||
        self.outputs.new('LnxIntSocket', 'Frame Start')
 | 
			
		||||
        self.outputs.new('LnxIntSocket', 'Frame End')
 | 
			
		||||
        self.outputs.new('LnxIntSocket', 'Lifetime')
 | 
			
		||||
        self.outputs.new('LnxFloatSocket', 'Lifetime Random')
 | 
			
		||||
        self.outputs.new('LnxIntSocket', 'Emit From')
 | 
			
		||||
 | 
			
		||||
        self.outputs.new('LnxVectorSocket', 'Velocity')
 | 
			
		||||
        self.outputs.new('LnxFloatSocket', 'Velocity Random')
 | 
			
		||||
        self.outputs.new('LnxVectorSocket', 'Gravity')
 | 
			
		||||
        self.outputs.new('LnxFloatSocket', 'Weight Gravity')
 | 
			
		||||
 | 
			
		||||
        self.outputs.new('LnxFloatSocket', 'Speed')
 | 
			
		||||
    
 | 
			
		||||
        self.outputs.new('LnxFloatSocket', 'Time')
 | 
			
		||||
        self.outputs.new('LnxFloatSocket', 'Lap')
 | 
			
		||||
        self.outputs.new('LnxFloatSocket', 'Lap Time')
 | 
			
		||||
        self.outputs.new('LnxIntSocket', 'Count')
 | 
			
		||||
@ -0,0 +1,33 @@
 | 
			
		||||
from lnx.logicnode.lnx_nodes import *
 | 
			
		||||
 | 
			
		||||
class RemoveParticleFromObjectNode(LnxLogicTreeNode):
 | 
			
		||||
    """Remove Particle From Object."""
 | 
			
		||||
    bl_idname = 'LNRemoveParticleFromObjectNode'
 | 
			
		||||
    bl_label = 'Remove Particle From Object'
 | 
			
		||||
    lnx_version = 1
 | 
			
		||||
 | 
			
		||||
    def remove_extra_inputs(self, context):
 | 
			
		||||
        while len(self.inputs) > 2:
 | 
			
		||||
                self.inputs.remove(self.inputs[-1])
 | 
			
		||||
        if self.property0 == 'Slot':
 | 
			
		||||
            self.add_input('LnxIntSocket', 'Slot')
 | 
			
		||||
        if self.property0 == 'Name':
 | 
			
		||||
            self.add_input('LnxStringSocket', 'Name')
 | 
			
		||||
 | 
			
		||||
    property0: HaxeEnumProperty(
 | 
			
		||||
    'property0',
 | 
			
		||||
    items = [('Slot', 'Slot', 'Slot'),
 | 
			
		||||
             ('Name', 'Name', 'Name'),
 | 
			
		||||
             ('All', 'All', 'All')],
 | 
			
		||||
    name='', default='Slot', update=remove_extra_inputs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.add_input('LnxNodeSocketAction', 'In')
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'Object')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'Slot')
 | 
			
		||||
 | 
			
		||||
        self.add_output('LnxNodeSocketAction', 'Out')
 | 
			
		||||
 | 
			
		||||
    def draw_buttons(self, context, layout):
 | 
			
		||||
        layout.prop(self, 'property0')
 | 
			
		||||
@ -0,0 +1,58 @@
 | 
			
		||||
from lnx.logicnode.lnx_nodes import *
 | 
			
		||||
 | 
			
		||||
class SetParticleDataNode(LnxLogicTreeNode):
 | 
			
		||||
    """Sets the parameters of the given particle system."""
 | 
			
		||||
    bl_idname = 'LNSetParticleDataNode'
 | 
			
		||||
    bl_label = 'Set Particle Data'
 | 
			
		||||
    lnx_version = 1
 | 
			
		||||
 | 
			
		||||
    def remove_extra_inputs(self, context):
 | 
			
		||||
        while len(self.inputs) > 3:
 | 
			
		||||
                self.inputs.remove(self.inputs[-1])
 | 
			
		||||
        if self.property0 == 'Particle Size':
 | 
			
		||||
            self.add_input('LnxFloatSocket', 'Particle Size')
 | 
			
		||||
        if self.property0 == 'Frame End':
 | 
			
		||||
            self.add_input('LnxIntSocket', 'Frame End')
 | 
			
		||||
        if self.property0 == 'Frame Start':
 | 
			
		||||
            self.add_input('LnxIntSocket', 'Frame Start')
 | 
			
		||||
        if self.property0 == 'Lifetime': 
 | 
			
		||||
            self.add_input('LnxIntSocket', 'Lifetime')
 | 
			
		||||
        if self.property0 == 'Lifetime Random':
 | 
			
		||||
            self.add_input('LnxFloatSocket', 'Lifetime Random')
 | 
			
		||||
        if self.property0 == 'Emit From':
 | 
			
		||||
            self.add_input('LnxIntSocket', 'Emit From')
 | 
			
		||||
        if self.property0 == 'Velocity':
 | 
			
		||||
            self.add_input('LnxVectorSocket', 'Velocity')
 | 
			
		||||
        if self.property0 == 'Velocity Random':
 | 
			
		||||
            self.add_input('LnxFloatSocket', 'Velocity Random')
 | 
			
		||||
        if self.property0 == 'Weight Gravity':
 | 
			
		||||
            self.add_input('LnxFloatSocket', 'Weight Gravity')
 | 
			
		||||
        if self.property0 == 'Speed':
 | 
			
		||||
            self.add_input('LnxFloatSocket', 'Speed')
 | 
			
		||||
 | 
			
		||||
       
 | 
			
		||||
    property0: HaxeEnumProperty(
 | 
			
		||||
    'property0',
 | 
			
		||||
    items = [('Particle Size', 'Particle Size', 'for the system'),
 | 
			
		||||
             ('Frame Start', 'Frame Start', 'for the system'),
 | 
			
		||||
             ('Frame End', 'Frame End', 'for the system'),
 | 
			
		||||
             ('Lifetime', 'Lifetime', 'for the instance'),
 | 
			
		||||
             ('Lifetime Random', 'Lifetime Random', 'for the system'),
 | 
			
		||||
             ('Emit From', 'Emit From', 'for the system (Vertices:0 Faces:1 Volume: 2)'),
 | 
			
		||||
             ('Velocity', 'Velocity', 'for the instance'),
 | 
			
		||||
             ('Velocity Random', 'Velocity Random', 'for the system'),
 | 
			
		||||
             ('Weight Gravity', 'Weight Gravity', 'for the instance'),
 | 
			
		||||
             ('Speed', 'Speed', 'for the instance')],
 | 
			
		||||
    name='', default='Speed', update=remove_extra_inputs)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.add_input('LnxNodeSocketAction', 'In')
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'Object')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'Slot')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
 | 
			
		||||
 | 
			
		||||
        self.add_output('LnxNodeSocketAction', 'Out')
 | 
			
		||||
        
 | 
			
		||||
    def draw_buttons(self, context, layout):
 | 
			
		||||
        layout.prop(self, 'property0')
 | 
			
		||||
@ -1,14 +1,22 @@
 | 
			
		||||
from lnx.logicnode.lnx_nodes import *
 | 
			
		||||
 | 
			
		||||
class SetParticleSpeedNode(LnxLogicTreeNode):
 | 
			
		||||
    """Sets the speed of the given particle source."""
 | 
			
		||||
    bl_idname = 'LNSetParticleSpeedNode'
 | 
			
		||||
    bl_label = 'Set Particle Speed'
 | 
			
		||||
    lnx_version = 1
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.add_input('LnxNodeSocketAction', 'In')
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'Object')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
 | 
			
		||||
 | 
			
		||||
        self.add_output('LnxNodeSocketAction', 'Out')
 | 
			
		||||
from lnx.logicnode.lnx_nodes import *
 | 
			
		||||
 | 
			
		||||
class SetParticleSpeedNode(LnxLogicTreeNode):
 | 
			
		||||
    """Sets the speed of the given particle source."""
 | 
			
		||||
    bl_idname = 'LNSetParticleSpeedNode'
 | 
			
		||||
    bl_label = 'Set Particle Speed'
 | 
			
		||||
    lnx_version = 2
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.add_input('LnxNodeSocketAction', 'In')
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'Object')
 | 
			
		||||
        self.add_input('LnxIntSocket', 'Slot')
 | 
			
		||||
        self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
 | 
			
		||||
 | 
			
		||||
        self.add_output('LnxNodeSocketAction', 'Out')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
			
		||||
        if self.lnx_version not in (0, 1):
 | 
			
		||||
            raise LookupError()
 | 
			
		||||
            
 | 
			
		||||
        return NodeReplacement.Identity(self)
 | 
			
		||||
							
								
								
									
										3
									
								
								leenkx/blender/lnx/logicnode/particle/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								leenkx/blender/lnx/logicnode/particle/__init__.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
from lnx.logicnode.lnx_nodes import add_node_section
 | 
			
		||||
 | 
			
		||||
add_node_section(name='default', category='Particle')
 | 
			
		||||
@ -234,7 +234,7 @@ def build():
 | 
			
		||||
                wrd.compo_defs += '_CGrain'
 | 
			
		||||
            if rpdat.lnx_sharpen:
 | 
			
		||||
                wrd.compo_defs += '_CSharpen'
 | 
			
		||||
            if bpy.data.scenes[0].view_settings.exposure != 0.0:
 | 
			
		||||
            if bpy.utils.get_active_scene().view_settings.exposure != 0.0:
 | 
			
		||||
                wrd.compo_defs += '_CExposure'
 | 
			
		||||
            if rpdat.lnx_fog:
 | 
			
		||||
                wrd.compo_defs += '_CFog'
 | 
			
		||||
 | 
			
		||||
@ -298,6 +298,125 @@ float tex_brick_f(vec3 p) {
 | 
			
		||||
}
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#https://github.com/blender/blender/blob/main/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl
 | 
			
		||||
str_tex_brick_blender = """
 | 
			
		||||
float integer_noise(int n)
 | 
			
		||||
{
 | 
			
		||||
  /* Integer bit-shifts for these calculations can cause precision problems on macOS.
 | 
			
		||||
   * Using uint resolves these issues. */
 | 
			
		||||
  uint nn;
 | 
			
		||||
  nn = (uint(n) + 1013u) & 0x7fffffffu;
 | 
			
		||||
  nn = (nn >> 13u) ^ nn;
 | 
			
		||||
  nn = (uint(nn * (nn * nn * 60493u + 19990303u)) + 1376312589u) & 0x7fffffffu;
 | 
			
		||||
  return 0.5f * (float(nn) / 1073741824.0f);
 | 
			
		||||
}
 | 
			
		||||
vec2 calc_brick_texture(vec3 p,
 | 
			
		||||
                          float mortar_size,
 | 
			
		||||
                          float mortar_smooth,
 | 
			
		||||
                          float bias,
 | 
			
		||||
                          float brick_width,
 | 
			
		||||
                          float row_height,
 | 
			
		||||
                          float offset_amount,
 | 
			
		||||
                          int offset_frequency,
 | 
			
		||||
                          float squash_amount,
 | 
			
		||||
                          int squash_frequency)
 | 
			
		||||
{
 | 
			
		||||
  int bricknum, rownum;
 | 
			
		||||
  float offset = 0.0f;
 | 
			
		||||
  float x, y;
 | 
			
		||||
  rownum = int(floor(p.y / row_height));
 | 
			
		||||
  if (offset_frequency != 0 && squash_frequency != 0) {
 | 
			
		||||
    brick_width *= (rownum % squash_frequency != 0) ? 1.0f : squash_amount;           /* squash */
 | 
			
		||||
    offset = (rownum % offset_frequency != 0) ? 0.0f : (brick_width * offset_amount); /* offset */
 | 
			
		||||
  }
 | 
			
		||||
  bricknum = int(floor((p.x + offset) / brick_width));
 | 
			
		||||
  x = (p.x + offset) - brick_width * bricknum;
 | 
			
		||||
  y = p.y - row_height * rownum;
 | 
			
		||||
  float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0f, 1.0f);
 | 
			
		||||
  float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
 | 
			
		||||
  if (min_dist >= mortar_size) {
 | 
			
		||||
    return vec2(tint, 0.0f);
 | 
			
		||||
  }
 | 
			
		||||
  else if (mortar_smooth == 0.0f) {
 | 
			
		||||
    return vec2(tint, 1.0f);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    min_dist = 1.0f - min_dist / mortar_size;
 | 
			
		||||
    return vec2(tint, smoothstep(0.0f, mortar_smooth, min_dist));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
vec3 tex_brick_blender(vec3 co,
 | 
			
		||||
                    vec3 color1,
 | 
			
		||||
                    vec3 color2,
 | 
			
		||||
                    vec3 mortar,
 | 
			
		||||
                    float scale,
 | 
			
		||||
                    float mortar_size,
 | 
			
		||||
                    float mortar_smooth,
 | 
			
		||||
                    float bias,
 | 
			
		||||
                    float brick_width,
 | 
			
		||||
                    float row_height,
 | 
			
		||||
                    float offset_amount,
 | 
			
		||||
                    float offset_frequency,
 | 
			
		||||
                    float squash_amount,
 | 
			
		||||
                    float squash_frequency)
 | 
			
		||||
{
 | 
			
		||||
  vec2 f2 = calc_brick_texture(co * scale,
 | 
			
		||||
                                 mortar_size,
 | 
			
		||||
                                 mortar_smooth,
 | 
			
		||||
                                 bias,
 | 
			
		||||
                                 brick_width,
 | 
			
		||||
                                 row_height,
 | 
			
		||||
                                 offset_amount,
 | 
			
		||||
                                 int(offset_frequency),
 | 
			
		||||
                                 squash_amount,
 | 
			
		||||
                                 int(squash_frequency));
 | 
			
		||||
  float tint = f2.x;
 | 
			
		||||
  float f = f2.y;
 | 
			
		||||
  if (f != 1.0f) {
 | 
			
		||||
    float facm = 1.0f - tint;
 | 
			
		||||
    color1 = facm * color1 + tint * color2;
 | 
			
		||||
  }
 | 
			
		||||
    return mix(color1, mortar, f);
 | 
			
		||||
}
 | 
			
		||||
float tex_brick_blender_f(vec3 co,
 | 
			
		||||
                    vec3 color1,
 | 
			
		||||
                    vec3 color2,
 | 
			
		||||
                    vec3 mortar,
 | 
			
		||||
                    float scale,
 | 
			
		||||
                    float mortar_size,
 | 
			
		||||
                    float mortar_smooth,
 | 
			
		||||
                    float bias,
 | 
			
		||||
                    float brick_width,
 | 
			
		||||
                    float row_height,
 | 
			
		||||
                    float offset_amount,
 | 
			
		||||
                    float offset_frequency,
 | 
			
		||||
                    float squash_amount,
 | 
			
		||||
                    float squash_frequency)
 | 
			
		||||
{
 | 
			
		||||
  vec2 f2 = calc_brick_texture(co * scale,
 | 
			
		||||
                                 mortar_size,
 | 
			
		||||
                                 mortar_smooth,
 | 
			
		||||
                                 bias,
 | 
			
		||||
                                 brick_width,
 | 
			
		||||
                                 row_height,
 | 
			
		||||
                                 offset_amount,
 | 
			
		||||
                                 int(offset_frequency),
 | 
			
		||||
                                 squash_amount,
 | 
			
		||||
                                 int(squash_frequency));
 | 
			
		||||
  float tint = f2.x;
 | 
			
		||||
  float f = f2.y;
 | 
			
		||||
  if (f != 1.0f) {
 | 
			
		||||
    float facm = 1.0f - tint;
 | 
			
		||||
    color1 = facm * color1 + tint * color2;
 | 
			
		||||
  }
 | 
			
		||||
    return f;
 | 
			
		||||
}
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
str_tex_wave = """
 | 
			
		||||
float tex_wave_f(const vec3 p, const int type, const int profile, const float dist, const float detail, const float detail_scale) {
 | 
			
		||||
    float n;
 | 
			
		||||
 | 
			
		||||
@ -29,24 +29,35 @@ else:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_tex_brick(node: bpy.types.ShaderNodeTexBrick, out_socket: bpy.types.NodeSocket, state: ParserState) -> Union[floatstr, vec3str]:
 | 
			
		||||
    state.curshader.add_function(c_functions.str_tex_brick)
 | 
			
		||||
    state.curshader.add_function(c_functions.str_tex_brick_blender)
 | 
			
		||||
 | 
			
		||||
    if node.inputs[0].is_linked:
 | 
			
		||||
        co = c.parse_vector_input(node.inputs[0])
 | 
			
		||||
    else:
 | 
			
		||||
        co = 'bposition'
 | 
			
		||||
 | 
			
		||||
    offset_amount = node.offset
 | 
			
		||||
    offset_frequency = node.offset_frequency
 | 
			
		||||
    squash_amount = node.squash
 | 
			
		||||
    squash_frequency = node.squash_frequency        
 | 
			
		||||
 | 
			
		||||
    col1 = c.parse_vector_input(node.inputs[1])
 | 
			
		||||
    col2 = c.parse_vector_input(node.inputs[2])
 | 
			
		||||
    col3 = c.parse_vector_input(node.inputs[3])
 | 
			
		||||
    scale = c.parse_value_input(node.inputs[4])
 | 
			
		||||
    mortar_size = c.parse_value_input(node.inputs[5])
 | 
			
		||||
    mortar_smooth = c.parse_value_input(node.inputs[6])
 | 
			
		||||
    bias = c.parse_value_input(node.inputs[7])
 | 
			
		||||
    brick_width = c.parse_value_input(node.inputs[8])
 | 
			
		||||
    row_height = c.parse_value_input(node.inputs[9])
 | 
			
		||||
    #res = f'tex_brick({co} * {scale}, {col1}, {col2}, {col3})'
 | 
			
		||||
 | 
			
		||||
    # Color
 | 
			
		||||
    if out_socket == node.outputs[0]:
 | 
			
		||||
        col1 = c.parse_vector_input(node.inputs[1])
 | 
			
		||||
        col2 = c.parse_vector_input(node.inputs[2])
 | 
			
		||||
        col3 = c.parse_vector_input(node.inputs[3])
 | 
			
		||||
        scale = c.parse_value_input(node.inputs[4])
 | 
			
		||||
        res = f'tex_brick({co} * {scale}, {col1}, {col2}, {col3})'
 | 
			
		||||
        res = f'tex_brick_blender({co}, {col1}, {col2}, {col3}, {scale}, {mortar_size}, {mortar_smooth}, {bias}, {brick_width}, {row_height}, {offset_amount}, {offset_frequency}, {squash_amount}, {squash_frequency})'
 | 
			
		||||
    # Fac
 | 
			
		||||
    else:
 | 
			
		||||
        scale = c.parse_value_input(node.inputs[4])
 | 
			
		||||
        res = 'tex_brick_f({0} * {1})'.format(co, scale)
 | 
			
		||||
        res = f'tex_brick_blender_f({co}, {col1}, {col2}, {col3}, {scale}, {mortar_size}, {mortar_smooth}, {bias}, {brick_width}, {row_height}, {offset_amount}, {offset_frequency}, {squash_amount}, {squash_frequency})'
 | 
			
		||||
 | 
			
		||||
    return res
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -77,7 +77,7 @@ class LNX_MT_NodeAddOverride(bpy.types.Menu):
 | 
			
		||||
                layout.separator()
 | 
			
		||||
                layout.menu(f'LNX_MT_{INTERNAL_GROUPS_MENU_ID}_menu', text=internal_groups_menu_class.bl_label, icon='OUTLINER_OB_GROUP_INSTANCE')
 | 
			
		||||
 | 
			
		||||
        elif context.space_data.tree_type == 'ShaderNodeTree':
 | 
			
		||||
        elif context.space_data.tree_type == 'ShaderNodeTree' and bpy.app.version > (4, 0, 0):
 | 
			
		||||
            # TO DO - Recursively gather nodes and draw them to menu
 | 
			
		||||
 | 
			
		||||
            LNX_MT_NodeAddOverride.overridden_draw(self, context)
 | 
			
		||||
 | 
			
		||||
@ -769,9 +769,9 @@ const vec3 compoLetterboxColor = vec3(""" + str(round(rpdat.lnx_letterbox_color[
 | 
			
		||||
"""const float compoSharpenStrength = """ + str(round(rpdat.lnx_sharpen_strength * 100) / 100) + """;
 | 
			
		||||
""")
 | 
			
		||||
 | 
			
		||||
        if bpy.data.scenes[0].view_settings.exposure != 0.0:
 | 
			
		||||
        if bpy.utils.get_active_scene().view_settings.exposure != 0.0:
 | 
			
		||||
            f.write(
 | 
			
		||||
"""const float compoExposureStrength = """ + str(round(bpy.data.scenes[0].view_settings.exposure * 100) / 100) + """;
 | 
			
		||||
"""const float compoExposureStrength = """ + str(round(bpy.utils.get_active_scene().view_settings.exposure * 100) / 100) + """;
 | 
			
		||||
""")
 | 
			
		||||
 | 
			
		||||
        if rpdat.lnx_fog:
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user