diff --git a/leenkx/Sources/leenkx/logicnode/GetWorldNode.hx b/leenkx/Sources/leenkx/logicnode/GetWorldNode.hx index c587196..35d40c4 100644 --- a/leenkx/Sources/leenkx/logicnode/GetWorldNode.hx +++ b/leenkx/Sources/leenkx/logicnode/GetWorldNode.hx @@ -1,26 +1,12 @@ package leenkx.logicnode; -import iron.object.Object; -import iron.math.Vec4; - class GetWorldNode extends LogicNode { - public var property0: String; - public function new(tree: LogicTree) { super(tree); } override function get(from: Int): Dynamic { - var object: Object = inputs[0].get(); - - if (object == null) return null; - - return switch (property0) { - case "Right": object.transform.world.right(); - case "Look": object.transform.world.look(); - case "Up": object.transform.world.up(); - default: null; - } + return iron.Scene.active.raw.world_ref; } -} +} \ No newline at end of file diff --git a/leenkx/Sources/leenkx/logicnode/GetWorldOrientationNode.hx b/leenkx/Sources/leenkx/logicnode/GetWorldOrientationNode.hx new file mode 100644 index 0000000..c587196 --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/GetWorldOrientationNode.hx @@ -0,0 +1,26 @@ +package leenkx.logicnode; + +import iron.object.Object; +import iron.math.Vec4; + +class GetWorldNode extends LogicNode { + + public var property0: String; + + public function new(tree: LogicTree) { + super(tree); + } + + override function get(from: Int): Dynamic { + var object: Object = inputs[0].get(); + + if (object == null) return null; + + return switch (property0) { + case "Right": object.transform.world.right(); + case "Look": object.transform.world.look(); + case "Up": object.transform.world.up(); + default: null; + } + } +} diff --git a/leenkx/Sources/leenkx/logicnode/ResolutionGetNode.hx b/leenkx/Sources/leenkx/logicnode/ResolutionGetNode.hx new file mode 100644 index 0000000..781279d --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/ResolutionGetNode.hx @@ -0,0 +1,16 @@ +package leenkx.logicnode; + +class ResolutionGetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + return switch (from) { + case 0: leenkx.renderpath.Postprocess.resolution_uniforms[0]; + case 1: leenkx.renderpath.Postprocess.resolution_uniforms[1]; + default: 0; + } + } +} \ No newline at end of file diff --git a/leenkx/Sources/leenkx/logicnode/ResolutionSetNode.hx b/leenkx/Sources/leenkx/logicnode/ResolutionSetNode.hx new file mode 100644 index 0000000..3a1fce9 --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/ResolutionSetNode.hx @@ -0,0 +1,33 @@ +package leenkx.logicnode; + +import kha.graphics4.TextureFilter; + +class ResolutionSetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + var size: Int = inputs[1].get(); + var filter: Int = inputs[2].get(); + + #if rp_resolution_filter + if (filter == 0) + iron.object.Uniforms.defaultFilter = TextureFilter.LinearFilter; + else + iron.object.Uniforms.defaultFilter = TextureFilter.PointFilter; + + leenkx.renderpath.Postprocess.resolution_uniforms[0] = size; + leenkx.renderpath.Postprocess.resolution_uniforms[1] = filter; + + var npath = leenkx.renderpath.RenderPathCreator.get(); + var world = iron.Scene.active.raw.world_ref; + npath.loadShader("shader_datas/World_" + world + "/World_" + world); + iron.RenderPath.setActive(npath); + #end + + runOutput(0); + } +} \ No newline at end of file diff --git a/leenkx/Sources/leenkx/logicnode/SetMaterialTextureFilterNode.hx b/leenkx/Sources/leenkx/logicnode/SetMaterialTextureFilterNode.hx new file mode 100644 index 0000000..45ac61d --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/SetMaterialTextureFilterNode.hx @@ -0,0 +1,55 @@ +package leenkx.logicnode; + +import iron.object.MeshObject; +import iron.data.MaterialData; + +class SetMaterialTextureFilterNode extends LogicNode { + + public function new(tree: LogicTree) { + super(tree); + } + + override function run(from: Int) { + var object: MeshObject = inputs[1].get(); + var mat: MaterialData = inputs[2].get(); + var slot: Int = inputs[3].get(); + var name: String = inputs[4].get(); + var filter: Int = inputs[5].get(); + + if (object == null) return; + if (slot >= object.materials.length) return; + + var mo = cast(object, iron.object.MeshObject); + + for (i => node in mo.materials[slot].contexts[0].raw.bind_textures) + if (node.name == name){ + var moImgt = mo.materials[slot].contexts[0].raw.bind_textures[i]; + switch(filter){ + case 0: //Linear + moImgt.min_filter = null; + moImgt.mag_filter = null; + moImgt.mipmap_filter = null; + moImgt.generate_mipmaps = null; + case 1: //Closest + moImgt.min_filter = 'point'; + moImgt.mag_filter = 'point'; + moImgt.mipmap_filter = null; + moImgt.generate_mipmaps = null; + case 2: //Cubic + moImgt.min_filter = null; + moImgt.mag_filter = null; + moImgt.mipmap_filter = 'linear'; + moImgt.generate_mipmaps = true; + case 3: //Smart + moImgt.min_filter = 'anisotropic'; + moImgt.mag_filter = null; + moImgt.mipmap_filter = 'linear'; + moImgt.generate_mipmaps = true; + } + + break; + } + + runOutput(0); + } +} \ No newline at end of file diff --git a/leenkx/Sources/leenkx/logicnode/SetWorldNode.hx b/leenkx/Sources/leenkx/logicnode/SetWorldNode.hx new file mode 100644 index 0000000..cd1acaa --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/SetWorldNode.hx @@ -0,0 +1,40 @@ +package leenkx.logicnode; + +class SetWorldNode extends LogicNode { + + public function new(tree: LogicTree) { + super(tree); + } + + override function run(from: Int) { + var world: String = inputs[1].get(); + + if (world != null){ + + //check if world shader data exists + var file: String = 'World_'+world+'_data'; + #if lnx_json + file += ".json"; + #elseif lnx_compress + file += ".lz4"; + #else + file += '.lnx'; + #end + + var exists: Bool = false; + + iron.data.Data.getBlob(file, function(b: kha.Blob) { + if (b != null) exists = true; + }); + + assert(Error, exists == true, "World must be either associated to a scene or have fake user"); + + iron.Scene.active.raw.world_ref = world; + var npath = leenkx.renderpath.RenderPathCreator.get(); + npath.loadShader("shader_datas/World_" + world + "/World_" + world); + iron.RenderPath.setActive(npath); + } + + runOutput(0); + } +} \ No newline at end of file diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index 166dcfc..77f4c69 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -780,7 +780,11 @@ class Inc { public static inline function getDisplayp(): Null { #if rp_resolution_filter // Custom resolution set + #if rp_pp + return leenkx.renderpath.Postprocess.resolution_uniforms[0]; + #else return Main.resolutionSize; + #end #else return null; #end diff --git a/leenkx/Sources/leenkx/renderpath/Postprocess.hx b/leenkx/Sources/leenkx/renderpath/Postprocess.hx index 95703d9..f7cf7c0 100644 --- a/leenkx/Sources/leenkx/renderpath/Postprocess.hx +++ b/leenkx/Sources/leenkx/renderpath/Postprocess.hx @@ -133,6 +133,11 @@ class Postprocess { [50.0] //2: Volumetric Fog Amount B ]; + public static var resolution_uniforms = [ + 720, //0: Size + 0 //1: Filter + ]; + public static function vec3Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 { var v:Vec4 = null; diff --git a/leenkx/blender/lnx/logicnode/material/LN_set_object_material_filter_texture.py b/leenkx/blender/lnx/logicnode/material/LN_set_object_material_filter_texture.py new file mode 100644 index 0000000..74b93f9 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/material/LN_set_object_material_filter_texture.py @@ -0,0 +1,23 @@ +from lnx.logicnode.lnx_nodes import * + +class SetMaterialTextureFilterNode(LnxLogicTreeNode): + """Sets texture filter interpolation.""" + bl_idname = 'LNSetMaterialTextureFilterNode' + bl_label = 'Set Object Material Texture Filter' + lnx_version = 1 + + def lnx_init(self, context): + self.add_input('LnxNodeSocketAction', 'In') + self.add_input('LnxNodeSocketObject', 'Object') + self.add_input('LnxDynamicSocket', 'Material') + self.add_input('LnxIntSocket', 'Slot') + self.add_input('LnxStringSocket', 'Node') + self.add_input('LnxIntSocket', 'Texture Filter') + + self.add_output('LnxNodeSocketAction', 'Out') + + def draw_buttons(self, context, layout): + layout.label(text='Tex Filter 0: Linear') + layout.label(text='Tex Filter 1: Closest') + layout.label(text='Tex Filter 2: Cubic') + layout.label(text='Tex Filter 3: Smart') \ No newline at end of file diff --git a/leenkx/blender/lnx/logicnode/postprocess/LN_get_resolution_settings.py b/leenkx/blender/lnx/logicnode/postprocess/LN_get_resolution_settings.py new file mode 100644 index 0000000..bdc5ac8 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/postprocess/LN_get_resolution_settings.py @@ -0,0 +1,12 @@ +from lnx.logicnode.lnx_nodes import * + +class ResolutionGetNode(LnxLogicTreeNode): + """Returns the resolution parameters. + """ + bl_idname = 'LNResolutionGetNode' + bl_label = 'Get Resolution Settings' + lnx_version = 1 + + def lnx_init(self, context): + self.add_output('LnxIntSocket', 'Size') + self.add_output('LnxIntSocket', 'Filter') \ No newline at end of file diff --git a/leenkx/blender/lnx/logicnode/postprocess/LN_set_resolution_settings.py b/leenkx/blender/lnx/logicnode/postprocess/LN_set_resolution_settings.py new file mode 100644 index 0000000..ca7e5a9 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/postprocess/LN_set_resolution_settings.py @@ -0,0 +1,20 @@ +from lnx.logicnode.lnx_nodes import * + +class ResolutionSetNode(LnxLogicTreeNode): + """Set the resolution post-processing settings. + Filter 0: Lineal 1: Closest + """ + bl_idname = 'LNResolutionSetNode' + bl_label = 'Set Resolution Settings' + lnx_version = 1 + + def lnx_init(self, context): + self.add_input('LnxNodeSocketAction', 'In') + self.add_input('LnxIntSocket', 'Size', default_value=720) + self.add_input('LnxIntSocket', 'Filter', default_value=0) + + self.add_output('LnxNodeSocketAction', 'Out') + + def draw_buttons(self, context, layout): + layout.label(text="Type 0: Lineal") + layout.label(text="Type 1: Closest") \ No newline at end of file diff --git a/leenkx/blender/lnx/logicnode/transform/LN_get_world_orientation.py b/leenkx/blender/lnx/logicnode/transform/LN_get_world_orientation.py index 40006f3..b8f2dcd 100644 --- a/leenkx/blender/lnx/logicnode/transform/LN_get_world_orientation.py +++ b/leenkx/blender/lnx/logicnode/transform/LN_get_world_orientation.py @@ -1,8 +1,8 @@ from lnx.logicnode.lnx_nodes import * -class GetWorldNode(LnxLogicTreeNode): +class GetWorldOrientationNode(LnxLogicTreeNode): """Returns the world orientation of the given object.""" - bl_idname = 'LNGetWorldNode' + bl_idname = 'LNGetWorldOrientationNode' bl_label = 'Get World Orientation' lnx_section = 'rotation' lnx_version = 1 diff --git a/leenkx/blender/lnx/logicnode/world/LN_get_world.py b/leenkx/blender/lnx/logicnode/world/LN_get_world.py new file mode 100644 index 0000000..74273ad --- /dev/null +++ b/leenkx/blender/lnx/logicnode/world/LN_get_world.py @@ -0,0 +1,10 @@ +from lnx.logicnode.lnx_nodes import * + +class GetWorldNode(LnxLogicTreeNode): + """Gets the World of the active scene.""" + bl_idname = 'LNGetWorldNode' + bl_label = 'Get World' + lnx_version = 1 + + def lnx_init(self, context): + self.add_output('LnxStringSocket', 'World') \ No newline at end of file diff --git a/leenkx/blender/lnx/logicnode/world/LN_set_world.py b/leenkx/blender/lnx/logicnode/world/LN_set_world.py new file mode 100644 index 0000000..0963735 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/world/LN_set_world.py @@ -0,0 +1,13 @@ +from lnx.logicnode.lnx_nodes import * + +class SetWorldNode(LnxLogicTreeNode): + """Sets the World of the active scene.""" + bl_idname = 'LNSetWorldNode' + bl_label = 'Set World' + lnx_version = 1 + + def lnx_init(self, context): + self.add_input('LnxNodeSocketAction', 'In') + self.add_input('LnxStringSocket', 'World') + + self.add_output('LnxNodeSocketAction', 'Out') \ No newline at end of file diff --git a/leenkx/blender/lnx/make_world.py b/leenkx/blender/lnx/make_world.py index ebe197a..eca7097 100644 --- a/leenkx/blender/lnx/make_world.py +++ b/leenkx/blender/lnx/make_world.py @@ -47,11 +47,20 @@ def build(): with write_probes.setup_envmap_render(): - for scene in bpy.data.scenes: - world = scene.world + #for scene in bpy.data.scenes: + for world in bpy.data.worlds: + #world = scene.world - # Only export worlds from enabled scenes and only once per world - if scene.lnx_export and world is not None and world not in worlds: + assigned = False; + for scene in bpy.data.scenes: + if scene.lnx_export and scene.world is not None: + if scene.world.name == world.name: + assigned = True; + break; + + #if scene.lnx_export and world is not None and world not in worlds: + # Only export worlds from enabled scenes and with fake users + if (world.use_fake_user and world.name != 'Lnx') or assigned: worlds.append(world) world.lnx_envtex_name = '' diff --git a/leenkx/blender/lnx/props_renderpath.py b/leenkx/blender/lnx/props_renderpath.py index ae1ddfd..c85a642 100644 --- a/leenkx/blender/lnx/props_renderpath.py +++ b/leenkx/blender/lnx/props_renderpath.py @@ -452,9 +452,10 @@ class LnxRPListItem(bpy.types.PropertyGroup): lnx_ssrs: BoolProperty(name="SSRS", description="Screen-space ray-traced shadows", default=False, update=assets.invalidate_shader_cache) lnx_micro_shadowing: BoolProperty(name="Micro Shadowing", description="Use the shaders' occlusion parameter to compute micro shadowing for the scene's sun lamp. This option is not available for render paths using mobile or solid material models", default=False, update=assets.invalidate_shader_cache) lnx_texture_filter: EnumProperty( - items=[('Anisotropic', 'Anisotropic', 'Anisotropic'), - ('Linear', 'Linear', 'Linear'), + items=[('Linear', 'Linear', 'Linear'), ('Point', 'Closest', 'Point'), + ('Cubic', 'Cubic', 'Cubic'), + ('Anisotropic', 'Smart', 'Anisotropic'), ('Manual', 'Manual', 'Manual')], name="Texture Filtering", description="Set Manual to honor interpolation setting on Image Texture node", default='Anisotropic') lnx_material_model: EnumProperty(