diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c9be358 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*/build* +*/*.blend? +*/Sources/Main.hx +*/Sources/arm/node/* +*.pyc +*.DS_Store +khafile.js +node_update_failure.* +.vscode/ +config.arm +_*/ diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..4b308e9 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,7 @@ +# The zlib/libpng License + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: +The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +This notice may not be removed or altered from any source distribution. diff --git a/RaycastRay/RaycastRay.blend b/RaycastRay/RaycastRay.blend new file mode 100644 index 0000000..b6132e3 Binary files /dev/null and b/RaycastRay/RaycastRay.blend differ diff --git a/ScreenToWorld_WorldToScreen/ScreenToWorld_WorldToScreen.blend b/ScreenToWorld_WorldToScreen/ScreenToWorld_WorldToScreen.blend new file mode 100644 index 0000000..2a798d9 Binary files /dev/null and b/ScreenToWorld_WorldToScreen/ScreenToWorld_WorldToScreen.blend differ diff --git a/animation_actions/README.md b/animation_actions/README.md new file mode 100644 index 0000000..d580656 --- /dev/null +++ b/animation_actions/README.md @@ -0,0 +1 @@ +Press keyboard `1`, `2`, `3` to change the animation action diff --git a/animation_actions/Sources/lnx/ActionPlayer.hx b/animation_actions/Sources/lnx/ActionPlayer.hx new file mode 100644 index 0000000..828315e --- /dev/null +++ b/animation_actions/Sources/lnx/ActionPlayer.hx @@ -0,0 +1,39 @@ +package lnx; + +class ActionPlayer extends iron.Trait { + + function getAnim() { + // Trait placed on mesh object + var anim = object.animation; + // Trait placed on armature object - retrieve animation from child mesh + if (anim == null) anim = object.children[0].animation; + return anim; + } + + public function new() { + super(); + + notifyOnInit(function() { + var anim = getAnim(); + anim.notifyOnMarker("my_marker", function() { + trace("Marker!"); + }); + }); + + notifyOnUpdate(function() { + var kb = iron.system.Input.getKeyboard(); + + var anim = getAnim(); + + if (kb.started("1")) anim.play("idle"); + else if (kb.started("2")) anim.play("run"); + else if (kb.started("3")) anim.play("slash", onSlash); + else if (kb.started("6")) anim.pause(); + else if (kb.started("7")) anim.resume(); + }); + } + + function onSlash() { + trace("Slash animation played!"); + } +} diff --git a/animation_actions/animation_actions.blend b/animation_actions/animation_actions.blend new file mode 100644 index 0000000..e1c97cf Binary files /dev/null and b/animation_actions/animation_actions.blend differ diff --git a/animation_blend/Bundled/canvas/MyCanvas.files b/animation_blend/Bundled/canvas/MyCanvas.files new file mode 100644 index 0000000..e69de29 diff --git a/animation_blend/Bundled/canvas/MyCanvas.json b/animation_blend/Bundled/canvas/MyCanvas.json new file mode 100644 index 0000000..9a5464b --- /dev/null +++ b/animation_blend/Bundled/canvas/MyCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":1280,"height":720,"elements":[{"id":0,"type":0,"name":"Text","event":"","x":0,"y":0,"width":383,"height":44,"rotation":0,"text":"Hold W/S to blend","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true}],"assets":[],"theme":"Default Light"} \ No newline at end of file diff --git a/animation_blend/Bundled/canvas/_themes.json b/animation_blend/Bundled/canvas/_themes.json new file mode 100644 index 0000000..4bc4c4e --- /dev/null +++ b/animation_blend/Bundled/canvas/_themes.json @@ -0,0 +1 @@ +[{"NAME":"Default Light","WINDOW_BG_COL":-1052689,"WINDOW_TINT_COL":-14540254,"ACCENT_COL":-1118482,"ACCENT_HOVER_COL":-4473925,"ACCENT_SELECT_COL":-5592406,"BUTTON_COL":-3355444,"BUTTON_TEXT_COL":-14540254,"BUTTON_HOVER_COL":-5000269,"BUTTON_PRESSED_COL":-5131855,"TEXT_COL":-14144472,"LABEL_COL":-5592406,"SEPARATOR_COL":-6710887,"HIGHLIGHT_COL":-14656100,"CONTEXT_COL":-5592406,"PANEL_BG_COL":-5592406,"FONT_SIZE":26,"ELEMENT_W":200,"ELEMENT_H":48,"ELEMENT_OFFSET":8,"ARROW_SIZE":10,"BUTTON_H":44,"CHECK_SIZE":30,"CHECK_SELECT_SIZE":16,"SCROLL_W":12,"TEXT_OFFSET":16,"TAB_W":24,"FILL_WINDOW_BG":false,"FILL_BUTTON_BG":true,"FILL_ACCENT_BG":false,"LINK_STYLE":0,"FULL_TABS":false}] \ No newline at end of file diff --git a/animation_blend/README.md b/animation_blend/README.md new file mode 100644 index 0000000..c4f0f30 --- /dev/null +++ b/animation_blend/README.md @@ -0,0 +1 @@ +Hold keyboard `W`, `S` to blend between animations diff --git a/animation_blend/Sources/lnx/MyTrait.hx b/animation_blend/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..a7b1ab5 --- /dev/null +++ b/animation_blend/Sources/lnx/MyTrait.hx @@ -0,0 +1,30 @@ +package lnx; + +class MyTrait extends iron.Trait { + + var factor = 0.0; + + public function new() { + super(); + + notifyOnUpdate(function() { + + var anim:iron.object.BoneAnimation = cast object.children[0].animation; + var kb = iron.system.Input.getKeyboard(); + + // Blend idle and run actions + // factor 0.0 -> 100% idle + // factor 0.5 -> 50% idle, 50% run + // factor 1.0 -> 100% run + if (kb.down("w")) { + if (factor <= 0.99) factor += 0.01; + anim.blend("idle", "run", factor); + } + + if (kb.down("s")) { + if (factor >= 0.01) factor -= 0.01; + anim.blend("idle", "run", factor); + } + }); + } +} diff --git a/animation_blend/animation_blend.blend b/animation_blend/animation_blend.blend new file mode 100644 index 0000000..4358afe Binary files /dev/null and b/animation_blend/animation_blend.blend differ diff --git a/animation_bonechild/README.md b/animation_bonechild/README.md new file mode 100644 index 0000000..3ee5ba9 --- /dev/null +++ b/animation_bonechild/README.md @@ -0,0 +1,3 @@ +- Hand object is parented to armature bone +- Sword is parented to Hand object +- Press `X` to swap weapons diff --git a/animation_bonechild/Sources/lnx/SwapWeapon.hx b/animation_bonechild/Sources/lnx/SwapWeapon.hx new file mode 100644 index 0000000..d9e002a --- /dev/null +++ b/animation_bonechild/Sources/lnx/SwapWeapon.hx @@ -0,0 +1,40 @@ +package lnx; + +class SwapWeapon extends iron.Trait { + + var weapon = 0; + var hand:iron.object.Object; + var sword:iron.object.Object; + var axe:iron.object.Object; + + public function new() { + super(); + + notifyOnInit(function() { + var sc = iron.Scene.active; + hand = sc.getChild("Hand"); + sword = sc.getChild("Sword"); + axe = sc.getChild("Axe"); + }); + + notifyOnUpdate(function() { + var kb = iron.system.Input.getKeyboard(); + if (kb.started("x")) { + + var a = weapon == 0 ? sword : axe; // Currently equipped weapon + var b = weapon == 0 ? axe : sword; // The other weapon + + // Remove current weapon from hand + hand.removeChild(a); + a.visible = false; + + // Add the other weapon to hand + hand.addChild(b); + b.visible = true; + + // Swap weapon + weapon = weapon == 0 ? 1 : 0; + } + }); + } +} diff --git a/animation_bonechild/animation_bonechild.blend b/animation_bonechild/animation_bonechild.blend new file mode 100644 index 0000000..d9f54b2 Binary files /dev/null and b/animation_bonechild/animation_bonechild.blend differ diff --git a/animation_instanced/README.md b/animation_instanced/README.md new file mode 100644 index 0000000..2032066 --- /dev/null +++ b/animation_instanced/README.md @@ -0,0 +1,3 @@ +Use instancing for fast rendering of linked object duplicates. + +https://github.com/leenkx3d/leenkx/wiki/instancing diff --git a/animation_instanced/animation_instanced.blend b/animation_instanced/animation_instanced.blend new file mode 100644 index 0000000..b2b14e6 Binary files /dev/null and b/animation_instanced/animation_instanced.blend differ diff --git a/animation_movebone/README.md b/animation_movebone/README.md new file mode 100644 index 0000000..faa9f2c --- /dev/null +++ b/animation_movebone/README.md @@ -0,0 +1,3 @@ +The left lnx is controlled by Inverse Kinematics with a finger following a ball movement. +Use `W` `S` `A` and `D` keys to move the ball. +The right lnx is controlled by Forward Kinematics with a Haxe script. diff --git a/animation_movebone/Sources/lnx/MoveBoneFK.hx b/animation_movebone/Sources/lnx/MoveBoneFK.hx new file mode 100644 index 0000000..298bc5a --- /dev/null +++ b/animation_movebone/Sources/lnx/MoveBoneFK.hx @@ -0,0 +1,46 @@ +package lnx; + +import iron.math.Vec4; +import iron.math.Quat; +import iron.object.BoneAnimation; +import iron.math.Mat4; + +// Moving a bone - forward kinematics +class MoveBoneFK extends iron.Trait { + + public function new() { + super(); + + notifyOnInit(function() { + // Fetch armature animation + var anim = cast(object.children[0].animation, BoneAnimation); + // Fetch bone + var bone = anim.getBone("mixamorig:RightLnx"); + + // Manipulating bone in local space + //var m = anim.getBoneMat(bone); + // anim.notifyOnUpdate(function() { + // var offset = new Quat().fromEuler(0, Math.sin(iron.system.Time.time()), 0); + // m.applyQuat(offset); + //}); + + // Manipulating bone in world space + anim.notifyOnUpdate(function() { + // Get bone mat in world space + var m = anim.getAbsWorldMat(bone); + // Decompose transform + var loc = new Vec4(); + var scl = new Vec4(); + var rot = new Quat(); + m.decompose(loc, rot, scl); + // Apply rotation + var offset = new Quat().fromEuler(Math.sin(iron.system.Time.time()), 0, 0); + rot.multquats(offset, rot); + // Compose world matrix + m.compose(loc, rot, scl); + // Set bone matrix from world matrix + anim.setBoneMatFromWorldMat(m, bone); + }); + }); + } +} diff --git a/animation_movebone/Sources/lnx/MoveBoneIK.hx b/animation_movebone/Sources/lnx/MoveBoneIK.hx new file mode 100644 index 0000000..a04ad0b --- /dev/null +++ b/animation_movebone/Sources/lnx/MoveBoneIK.hx @@ -0,0 +1,28 @@ +package lnx; + +import iron.object.BoneAnimation; + +// Moving a bone - inverse kinematics +class MoveBoneIK extends iron.Trait { + + public function new() { + super(); + + iron.Scene.active.notifyOnInit(function() { + + // Fetch armature animation + var anim = cast(object.children[0].animation, BoneAnimation); + // Fetch bone + var bone = anim.getBone("mixamorig:LeftHandIndex4"); + // Fetch goal + var tr = iron.Scene.active.getChild("Goal").transform; + var goal = new iron.math.Vec4(); + + anim.notifyOnUpdate(function() { + goal.set(tr.worldx(), tr.worldy(), tr.worldz()); + // Align skeleton to touch the goal + anim.solveIK(bone, goal); + }); + }); + } +} diff --git a/animation_movebone/animation_movebone.blend b/animation_movebone/animation_movebone.blend new file mode 100644 index 0000000..5014a9d Binary files /dev/null and b/animation_movebone/animation_movebone.blend differ diff --git a/animation_timeline/animation_timeline.blend b/animation_timeline/animation_timeline.blend new file mode 100644 index 0000000..34e6bd8 Binary files /dev/null and b/animation_timeline/animation_timeline.blend differ diff --git a/animation_uv/animation_uv.blend b/animation_uv/animation_uv.blend new file mode 100644 index 0000000..89c353f Binary files /dev/null and b/animation_uv/animation_uv.blend differ diff --git a/call_hx/Bundled/my_plugin.js b/call_hx/Bundled/my_plugin.js new file mode 100644 index 0000000..f2bb859 --- /dev/null +++ b/call_hx/Bundled/my_plugin.js @@ -0,0 +1,14 @@ + +// Call Plugin class exposed from Haxe + +var plugin = new arm.Plugin(); +plugin.hello(); + +var scene = plugin.scene(); +var rot = 0.0; + +plugin.update = function() { + rot += 0.01; + var o = scene.getChild("Cube"); + o.transform.setRotation(0, 0, rot); +} diff --git a/call_hx/README.md b/call_hx/README.md new file mode 100644 index 0000000..1b9737c --- /dev/null +++ b/call_hx/README.md @@ -0,0 +1,2 @@ +Check console. +https://github.com/leenkx3d/leenkx/wiki/js diff --git a/call_hx/Sources/lnx/EvalJS.hx b/call_hx/Sources/lnx/EvalJS.hx new file mode 100644 index 0000000..1addc67 --- /dev/null +++ b/call_hx/Sources/lnx/EvalJS.hx @@ -0,0 +1,11 @@ +package lnx; + +class EvalJS { + + public function new() { + // Evaluate bundled JS, usually you would embed JS into .html file instead + iron.data.Data.getBlob("my_plugin.js", function(blob:kha.Blob) { + js.Syntax.code("(1, eval)({0})", blob.toString()); + }); + } +} diff --git a/call_hx/Sources/lnx/Plugin.hx b/call_hx/Sources/lnx/Plugin.hx new file mode 100644 index 0000000..45891fe --- /dev/null +++ b/call_hx/Sources/lnx/Plugin.hx @@ -0,0 +1,24 @@ +package lnx; + +// Expose this class for easy access from JS + +@:expose +class Plugin extends iron.Trait { + + var update:Void->Void = null; + + public function new() { + super(); + notifyOnUpdate(function() { + if (update != null) update(); + }); + } + + public function hello() { + trace("world"); + } + + public function scene() { + return iron.Scene.active; + } +} diff --git a/call_hx/call_hx.blend b/call_hx/call_hx.blend new file mode 100644 index 0000000..22cf4c8 Binary files /dev/null and b/call_hx/call_hx.blend differ diff --git a/call_js/README.md b/call_js/README.md new file mode 100644 index 0000000..3252e2a --- /dev/null +++ b/call_js/README.md @@ -0,0 +1,6 @@ +Shows how to call js after clicking on a `Cube` object. + +- Requires html5 target and physics enabled. +- Check devtools for output. + +https://github.com/leenkx3d/leenkx/wiki/js diff --git a/call_js/Sources/lnx/CallJS.hx b/call_js/Sources/lnx/CallJS.hx new file mode 100644 index 0000000..d094f54 --- /dev/null +++ b/call_js/Sources/lnx/CallJS.hx @@ -0,0 +1,33 @@ +package lnx; + +import leenkx.trait.physics.PhysicsWorld; +import iron.system.Input; + +// This example shows how to call JavaScript after clicking on a Cube object +// Requires physics enabled and browser target + +class CallJS extends iron.Trait { + + public function new() { + super(); + var mouse = Input.getMouse(); + notifyOnUpdate(function() { + + // Check mouse button + if (!mouse.started()) return; + + // Pick object at mouse coords + var rb = PhysicsWorld.active.pickClosest(mouse.x, mouse.y); + + // Check if picked object is our Cube + if (rb != null && rb.object.name == 'Cube') { + // Raw JS calls + js.Syntax.code('console.log("Cube clicked");'); + js.Syntax.code('document.title = "Cube clicked";'); + js.Syntax.code('window.alert("Cube clicked");'); + } else { + js.Syntax.code('console.log("click");'); + } + }); + } +} diff --git a/call_js/call_js.blend b/call_js/call_js.blend new file mode 100644 index 0000000..d87cd5c Binary files /dev/null and b/call_js/call_js.blend differ diff --git a/debug_draw/README.md b/debug_draw/README.md new file mode 100644 index 0000000..6d3d69c --- /dev/null +++ b/debug_draw/README.md @@ -0,0 +1 @@ +To see debug drawing, `Leenkx Project - Debug Console` option has to be enabled. diff --git a/debug_draw/Sources/lnx/MyTrait.hx b/debug_draw/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..f26d1e8 --- /dev/null +++ b/debug_draw/Sources/lnx/MyTrait.hx @@ -0,0 +1,24 @@ +package lnx; + +#if lnx_debug +import leenkx.trait.internal.DebugDraw; +#end + +class MyTrait extends iron.Trait { + + public function new() { + super(); + notifyOnInit( () -> { + var plane = iron.Scene.active.getChild("Plane"); + var suzanne = iron.Scene.active.getChild("Suzanne"); + // To see debug drawing, `Leenkx Project - Debug Console` option has to be enabled + #if lnx_debug + DebugDraw.notifyOnRender( (draw:DebugDraw) -> { + if(plane != null) draw.bounds(plane.transform); + if(suzanne != null) draw.bounds(suzanne.transform); + // draw.line(); + }); + #end + }); + } +} diff --git a/debug_draw/debug_draw.blend b/debug_draw/debug_draw.blend new file mode 100644 index 0000000..e56d6e4 Binary files /dev/null and b/debug_draw/debug_draw.blend differ diff --git a/dev_logicnode/Libraries/mynodes/Sources/leenkx/logicnode/TestNode.hx b/dev_logicnode/Libraries/mynodes/Sources/leenkx/logicnode/TestNode.hx new file mode 100644 index 0000000..6372db1 --- /dev/null +++ b/dev_logicnode/Libraries/mynodes/Sources/leenkx/logicnode/TestNode.hx @@ -0,0 +1,16 @@ +package leenkx.logicnode; + +class TestNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + // Logic for this node + trace("Hello, World!"); + + // Execute next action linked to this node + runOutput(0); + } +} diff --git a/dev_logicnode/Libraries/mynodes/blender.py b/dev_logicnode/Libraries/mynodes/blender.py new file mode 100644 index 0000000..623cf62 --- /dev/null +++ b/dev_logicnode/Libraries/mynodes/blender.py @@ -0,0 +1,38 @@ +from bpy.types import Node +from lnx.logicnode.lnx_nodes import * +import lnx.nodes_logic + + +class TestNode(LnxLogicTreeNode): + """Test node""" + bl_idname = 'LNTestNode' + bl_label = 'Test' + + # Use this as a tooltip in the add node menu. + # If `bl_description` does not exist, the docstring of this node is used instead. + bl_description = 'This is a test node' + + # The category in which this node is listed in the user interface + lnx_category = 'Custom Nodes' + + # Set the version of this node. If you update the node's Python + # code later, increment this version so that older projects get + # updated automatically. + # See https://github.com/leenkx3d/leenkx/wiki/logicnodes#node-versioning + lnx_version = 0 + + def init(self, context): + self.add_input('LnxNodeSocketAction', 'In') + self.add_output('LnxNodeSocketAction', 'Out') + + +def register(): + """This function is called when Leenkx loads this library.""" + + # Add a new category of nodes in which we will put the TestNode. + # This step is optional, you can also add nodes to Leenkx's default + # categories. + add_category('Custom Nodes', icon='EVENT_C') + + # Register the TestNode + TestNode.on_register() diff --git a/dev_logicnode/dev_logicnode.blend b/dev_logicnode/dev_logicnode.blend new file mode 100644 index 0000000..8678aa1 Binary files /dev/null and b/dev_logicnode/dev_logicnode.blend differ diff --git a/ease/README.md b/ease/README.md new file mode 100644 index 0000000..639b0a1 --- /dev/null +++ b/ease/README.md @@ -0,0 +1,2 @@ +- https://api.leenkx3d.org/iron/system/Ease.html +- https://api.leenkx3d.org/iron/system/Tween.html diff --git a/ease/Sources/lnx/TweenTest.hx b/ease/Sources/lnx/TweenTest.hx new file mode 100644 index 0000000..3c8520f --- /dev/null +++ b/ease/Sources/lnx/TweenTest.hx @@ -0,0 +1,33 @@ +package lnx; + +import iron.system.Tween; +#if lnx_debug +import leenkx.trait.internal.DebugDraw; +#end + +class TweenTest extends iron.Trait { + + @prop var ease : Int = 0; + + public function new() { + super(); + notifyOnInit(() -> { + #if lnx_debug + //DebugDraw.notifyOnRender( draw -> draw.bounds( object.transform) ); + #end + doTween(10); + }); + } + + function doTween( v : Float ) { + Tween.to({ + target: object.transform.loc, + props: { z: v }, + delay: 0.5, + duration: 2.0, + ease: ease, + tick: object.transform.buildMatrix, + done: () -> doTween(-v) + }); + } +} diff --git a/ease/ease.blend b/ease/ease.blend new file mode 100644 index 0000000..522ed0b Binary files /dev/null and b/ease/ease.blend differ diff --git a/file_read/Bundled/canvas/MyCanvas.files b/file_read/Bundled/canvas/MyCanvas.files new file mode 100644 index 0000000..e69de29 diff --git a/file_read/Bundled/canvas/MyCanvas.json b/file_read/Bundled/canvas/MyCanvas.json new file mode 100644 index 0000000..87b69f0 --- /dev/null +++ b/file_read/Bundled/canvas/MyCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":1280,"height":720,"elements":[{"id":0,"type":0,"name":"Text","event":"","x":0,"y":0,"width":372,"height":44,"rotation":0,"text":"My Text","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true,"color_text":-16744449}],"assets":[],"theme":"Default Light"} \ No newline at end of file diff --git a/file_read/Bundled/canvas/_themes.json b/file_read/Bundled/canvas/_themes.json new file mode 100644 index 0000000..9bc7ed6 --- /dev/null +++ b/file_read/Bundled/canvas/_themes.json @@ -0,0 +1 @@ +[{"NAME":"Default Light","WINDOW_BG_COL":-1052689,"WINDOW_TINT_COL":-14540254,"ACCENT_COL":-1118482,"ACCENT_HOVER_COL":-4473925,"ACCENT_SELECT_COL":-5592406,"BUTTON_COL":-3355444,"BUTTON_TEXT_COL":-14540254,"BUTTON_HOVER_COL":-5000269,"BUTTON_PRESSED_COL":-5131855,"TEXT_COL":-6710887,"LABEL_COL":-5592406,"SEPARATOR_COL":-6710887,"HIGHLIGHT_COL":-14656100,"CONTEXT_COL":-5592406,"PANEL_BG_COL":-5592406,"FONT_SIZE":26,"ELEMENT_W":200,"ELEMENT_H":48,"ELEMENT_OFFSET":8,"ARROW_SIZE":10,"BUTTON_H":44,"CHECK_SIZE":30,"CHECK_SELECT_SIZE":16,"SCROLL_W":12,"TEXT_OFFSET":16,"TAB_W":24,"FILL_WINDOW_BG":false,"FILL_BUTTON_BG":true,"FILL_ACCENT_BG":false,"LINK_STYLE":0}] \ No newline at end of file diff --git a/file_read/Bundled/my_file.json b/file_read/Bundled/my_file.json new file mode 100644 index 0000000..8722e18 --- /dev/null +++ b/file_read/Bundled/my_file.json @@ -0,0 +1,3 @@ +{ + "my_text": "Hello from json!" +} diff --git a/file_read/README.md b/file_read/README.md new file mode 100644 index 0000000..afddf99 --- /dev/null +++ b/file_read/README.md @@ -0,0 +1 @@ +Loads a json file from the `Bundled/` directory. diff --git a/file_read/Sources/lnx/ReadFile.hx b/file_read/Sources/lnx/ReadFile.hx new file mode 100644 index 0000000..16c3bf5 --- /dev/null +++ b/file_read/Sources/lnx/ReadFile.hx @@ -0,0 +1,34 @@ +package lnx; + +import leenkx.trait.internal.CanvasScript; +import iron.data.Data; +import iron.Scene; + +class ReadFile extends iron.Trait { + public function new() { + super(); + + notifyOnInit(function() { + + // Relative or absolute path to file + // In this case we load the file placed in the "Bundled/" directory + var file = "my_file.json"; + + // Load the file asynchronously + Data.getBlob(file, function(b:kha.Blob) { + // File is now loaded + // Get string from loaded bytes + var string = b.toString(); + + // Get json from string + var json = haxe.Json.parse(string); + + // Get canvas trait + var canvas = Scene.active.getTrait(CanvasScript); + + // Display "my_text" entry found in the loaded json file + canvas.getElement("Text").text = json.my_text; + }); + }); + } +} diff --git a/file_read/file_read.blend b/file_read/file_read.blend new file mode 100644 index 0000000..ec82a06 Binary files /dev/null and b/file_read/file_read.blend differ diff --git a/file_storage/README.md b/file_storage/README.md new file mode 100644 index 0000000..82b9dcc --- /dev/null +++ b/file_storage/README.md @@ -0,0 +1,4 @@ +Increments a number every time you start the application. +Check console. + +https://api.leenkx3d.org/kha/Storage.html diff --git a/file_storage/Sources/lnx/StorageTest.hx b/file_storage/Sources/lnx/StorageTest.hx new file mode 100644 index 0000000..7ab396c --- /dev/null +++ b/file_storage/Sources/lnx/StorageTest.hx @@ -0,0 +1,55 @@ +package lnx; + +import iron.system.Storage; + +class StorageTest extends iron.Trait { + + public function new() { + super(); + notifyOnInit(() -> { + + // Retrieve storage + var data = Storage.data; + if (data == null) + return; + + // First run - init integer variable named 'count' + var count: Dynamic = data.mycount; + if (count == null) { + data.mycount = 0; + // Init more variables as needed + // data.test1 = "String"; + // data.test2 = 1.23; + // data.test3 = true; + // data.test4 = [3, 5, 7]; + // data.test5 = {a: 3, b: "value"}; + } + + trace("Count is " + data.mycount); + + // Increase count on every run + data.mycount++; + + Storage.save(); + + var d = 10; + var s = 1; + var ox = 0; + var oy = 0; + notifyOnRender2D(g -> { + g.end(); + g.color = 0xff101010; + ox = oy = 0; + for(i in 0...data.mycount) { + g.fillRect(d+ox, d+oy, d, d); + ox += (d+1); + if(ox+d > kha.System.windowWidth()) { + ox = 0; + oy += d+1; + } + } + g.begin(false); + }); + }); + } +} diff --git a/file_storage/file_storage.blend b/file_storage/file_storage.blend new file mode 100644 index 0000000..e93a161 Binary files /dev/null and b/file_storage/file_storage.blend differ diff --git a/file_write/README.md b/file_write/README.md new file mode 100644 index 0000000..88fdc6f --- /dev/null +++ b/file_write/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/reference#write-json diff --git a/file_write/Sources/lnx/WriteFile.hx b/file_write/Sources/lnx/WriteFile.hx new file mode 100644 index 0000000..21ee253 --- /dev/null +++ b/file_write/Sources/lnx/WriteFile.hx @@ -0,0 +1,28 @@ +package lnx; + +class WriteFile extends iron.Trait { + public function new() { + super(); + + notifyOnInit(function() { + + // File writing in Krom + // To save data in HTML5, see file_storage example + + #if kha_krom + // Data to save + var o = { test: "Hello" }; + var s = haxe.Json.stringify(o); + + // Save file into game build folder + // Playing from Blender the file will be saved at + // file_write/build_file/debug/krom/my_file.json + var path = Krom.getFilesLocation() + "/my_file.json"; + + // Write file + var bytes = haxe.io.Bytes.ofString(s); + Krom.fileSaveBytes(path, bytes.getData()); + #end + }); + } +} diff --git a/file_write/file_write.blend b/file_write/file_write.blend new file mode 100644 index 0000000..0b610bd Binary files /dev/null and b/file_write/file_write.blend differ diff --git a/game_bowling/Assets/floor_base.jpg b/game_bowling/Assets/floor_base.jpg new file mode 100644 index 0000000..00d9db3 Binary files /dev/null and b/game_bowling/Assets/floor_base.jpg differ diff --git a/game_bowling/Assets/floor_nor.jpg b/game_bowling/Assets/floor_nor.jpg new file mode 100644 index 0000000..ef530ca Binary files /dev/null and b/game_bowling/Assets/floor_nor.jpg differ diff --git a/game_bowling/Assets/floor_occ.jpg b/game_bowling/Assets/floor_occ.jpg new file mode 100644 index 0000000..fb24151 Binary files /dev/null and b/game_bowling/Assets/floor_occ.jpg differ diff --git a/game_bowling/Assets/floor_rough.jpg b/game_bowling/Assets/floor_rough.jpg new file mode 100644 index 0000000..7682aec Binary files /dev/null and b/game_bowling/Assets/floor_rough.jpg differ diff --git a/game_bowling/Assets/keys.png b/game_bowling/Assets/keys.png new file mode 100644 index 0000000..a58b55f Binary files /dev/null and b/game_bowling/Assets/keys.png differ diff --git a/game_bowling/Assets/menu.jpg b/game_bowling/Assets/menu.jpg new file mode 100644 index 0000000..795fff8 Binary files /dev/null and b/game_bowling/Assets/menu.jpg differ diff --git a/game_bowling/Assets/roll.wav b/game_bowling/Assets/roll.wav new file mode 100644 index 0000000..08d49d0 Binary files /dev/null and b/game_bowling/Assets/roll.wav differ diff --git a/game_bowling/Assets/strike.wav b/game_bowling/Assets/strike.wav new file mode 100644 index 0000000..de20b68 Binary files /dev/null and b/game_bowling/Assets/strike.wav differ diff --git a/game_bowling/Assets/ui_exit.png b/game_bowling/Assets/ui_exit.png new file mode 100644 index 0000000..1e4eff9 Binary files /dev/null and b/game_bowling/Assets/ui_exit.png differ diff --git a/game_bowling/Assets/ui_play.png b/game_bowling/Assets/ui_play.png new file mode 100644 index 0000000..c24b669 Binary files /dev/null and b/game_bowling/Assets/ui_play.png differ diff --git a/game_bowling/Assets/ui_refresh.png b/game_bowling/Assets/ui_refresh.png new file mode 100644 index 0000000..bc6854d Binary files /dev/null and b/game_bowling/Assets/ui_refresh.png differ diff --git a/game_bowling/Bundled/canvas/GameCanvas.files b/game_bowling/Bundled/canvas/GameCanvas.files new file mode 100644 index 0000000..c480f7d --- /dev/null +++ b/game_bowling/Bundled/canvas/GameCanvas.files @@ -0,0 +1,3 @@ +../../Assets/ui_exit.png +../../Assets/ui_refresh.png +../../Assets/keys.png diff --git a/game_bowling/Bundled/canvas/GameCanvas.json b/game_bowling/Bundled/canvas/GameCanvas.json new file mode 100644 index 0000000..5b712fe --- /dev/null +++ b/game_bowling/Bundled/canvas/GameCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":1280,"height":720,"elements":[{"id":0,"type":1,"name":"Exit","event":"exit","x":15,"y":13,"width":64,"height":64,"text":"Image","asset":"ui_exit.png","color":-1,"anchor":0,"children":[],"visible":true,"rotation":0},{"id":1,"type":1,"name":"Refresh","event":"refresh","x":15,"y":91,"width":64,"height":64,"text":"Image","asset":"ui_refresh.png","color":-1,"anchor":0,"children":[],"visible":true,"rotation":0,"alignment":0},{"id":4,"type":1,"name":"Image","event":"","x":340,"y":620,"width":600,"height":70,"text":"Image","asset":"keys.png","color":-1,"anchor":0,"children":[],"visible":true,"rotation":0,"alignment":0}],"assets":[{"name":"ui_exit.png","file":"../../Assets/ui_exit.png","id":0},{"name":"ui_refresh.png","file":"../../Assets/ui_refresh.png","id":1},{"name":"keys.png","file":"../../Assets/keys.png","id":2}],"theme":"Default Light"} \ No newline at end of file diff --git a/game_bowling/Bundled/canvas/MenuCanvas.files b/game_bowling/Bundled/canvas/MenuCanvas.files new file mode 100644 index 0000000..f9df9a9 --- /dev/null +++ b/game_bowling/Bundled/canvas/MenuCanvas.files @@ -0,0 +1,2 @@ +../../Assets/ui_play.png +../../Assets/menu.jpg diff --git a/game_bowling/Bundled/canvas/MenuCanvas.json b/game_bowling/Bundled/canvas/MenuCanvas.json new file mode 100644 index 0000000..0874927 --- /dev/null +++ b/game_bowling/Bundled/canvas/MenuCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":1280,"height":720,"elements":[{"id":4,"type":1,"name":"Image","event":"","x":0,"y":0,"width":1280,"height":720,"rotation":0,"text":"My Image","asset":"menu.jpg","progress_at":0,"progress_total":100,"strength":1,"alignment":0,"anchor":0,"parent":null,"children":[],"visible":true},{"id":3,"type":1,"name":"Button","event":"play","x":580,"y":280,"width":160,"height":160,"rotation":0,"text":"My Image.002","asset":"ui_play.png","progress_at":0,"progress_total":100,"strength":1,"alignment":0,"anchor":0,"parent":null,"children":[],"visible":true}],"assets":[{"name":"ui_play.png","file":"../../Assets/ui_play.png","id":0},{"name":"menu.jpg","file":"../../Assets/menu.jpg","id":1}],"theme":"Default Light"} \ No newline at end of file diff --git a/game_bowling/Bundled/canvas/_themes.json b/game_bowling/Bundled/canvas/_themes.json new file mode 100644 index 0000000..e06fed7 --- /dev/null +++ b/game_bowling/Bundled/canvas/_themes.json @@ -0,0 +1 @@ +[{"NAME":"Default Light","WINDOW_BG_COL":-1052689,"WINDOW_TINT_COL":-14540254,"ACCENT_COL":-1118482,"ACCENT_HOVER_COL":-4473925,"ACCENT_SELECT_COL":-5592406,"BUTTON_COL":-3355444,"BUTTON_TEXT_COL":-14540254,"BUTTON_HOVER_COL":-5000269,"BUTTON_PRESSED_COL":-5131855,"TEXT_COL":-6710887,"LABEL_COL":-5592406,"SEPARATOR_COL":-6710887,"HIGHLIGHT_COL":-14656100,"CONTEXT_COL":-5592406,"PANEL_BG_COL":-5592406,"FONT_SIZE":26,"ELEMENT_W":200,"ELEMENT_H":48,"ELEMENT_OFFSET":8,"ARROW_SIZE":10,"BUTTON_H":44,"CHECK_SIZE":30,"CHECK_SELECT_SIZE":16,"SCROLL_W":12,"TEXT_OFFSET":16,"TAB_W":24,"FILL_WINDOW_BG":false,"FILL_BUTTON_BG":true,"FILL_ACCENT_BG":false,"LINK_STYLE":0,"FULL_TABS":false},{"NAME":"New Theme","WINDOW_BG_COL":-1052689,"WINDOW_TINT_COL":-14540254,"ACCENT_COL":-1118482,"ACCENT_HOVER_COL":-4473925,"ACCENT_SELECT_COL":-5592406,"BUTTON_COL":-3355444,"BUTTON_TEXT_COL":-14540254,"BUTTON_HOVER_COL":-5000269,"BUTTON_PRESSED_COL":-5131855,"TEXT_COL":-6710887,"LABEL_COL":-5592406,"SEPARATOR_COL":-6710887,"HIGHLIGHT_COL":-14656100,"CONTEXT_COL":-5592406,"PANEL_BG_COL":-5592406,"FONT_SIZE":26,"ELEMENT_W":200,"ELEMENT_H":48,"ELEMENT_OFFSET":8,"ARROW_SIZE":10,"BUTTON_H":44,"CHECK_SIZE":30,"CHECK_SELECT_SIZE":16,"SCROLL_W":12,"TEXT_OFFSET":16,"TAB_W":24,"FILL_WINDOW_BG":false,"FILL_BUTTON_BG":true,"FILL_ACCENT_BG":false,"LINK_STYLE":0,"FULL_TABS":false},{"NAME":"New Theme.001","WINDOW_BG_COL":-1052689,"WINDOW_TINT_COL":-14540254,"ACCENT_COL":-1118482,"ACCENT_HOVER_COL":-4473925,"ACCENT_SELECT_COL":-5592406,"BUTTON_COL":-3355444,"BUTTON_TEXT_COL":-14540254,"BUTTON_HOVER_COL":-5000269,"BUTTON_PRESSED_COL":-5131855,"TEXT_COL":-6710887,"LABEL_COL":-5592406,"SEPARATOR_COL":-6710887,"HIGHLIGHT_COL":-14656100,"CONTEXT_COL":-5592406,"PANEL_BG_COL":-5592406,"FONT_SIZE":26,"ELEMENT_W":200,"ELEMENT_H":48,"ELEMENT_OFFSET":8,"ARROW_SIZE":10,"BUTTON_H":44,"CHECK_SIZE":30,"CHECK_SELECT_SIZE":16,"SCROLL_W":12,"TEXT_OFFSET":16,"TAB_W":24,"FILL_WINDOW_BG":false,"FILL_BUTTON_BG":true,"FILL_ACCENT_BG":false,"LINK_STYLE":0,"FULL_TABS":false}] \ No newline at end of file diff --git a/game_bowling/README.md b/game_bowling/README.md new file mode 100644 index 0000000..84240f1 --- /dev/null +++ b/game_bowling/README.md @@ -0,0 +1 @@ +Keyboard `space` to bowl diff --git a/game_bowling/Sources/lnx/BallTrait.hx b/game_bowling/Sources/lnx/BallTrait.hx new file mode 100644 index 0000000..200d284 --- /dev/null +++ b/game_bowling/Sources/lnx/BallTrait.hx @@ -0,0 +1,55 @@ +package lnx; + +import iron.math.Vec4; +import leenkx.trait.physics.RigidBody; + +class BallTrait extends iron.Trait { + + @prop + var impulse = 65.0; + + var fired = false; + var rb:RigidBody; + var start = new Vec4(); + + public function new() { + super(); + + notifyOnInit(function() { + rb = object.getTrait(RigidBody); + start.setFrom(object.transform.loc); + }); + + notifyOnUpdate(function() { + + var kb = iron.system.Input.getKeyboard(); + var tr = object.transform; + + if (!fired) { + if (kb.started("x") || kb.started("space")) { + rb.applyImpulse(new Vec4(0, impulse, 0)); + fired = true; + } + else if (kb.down("left") && tr.loc.x > -0.9) { + tr.loc.x -= 0.02; + tr.buildMatrix(); + rb.syncTransform(); + } + else if (kb.down("right") && tr.loc.x < 0.9) { + tr.loc.x += 0.02; + tr.buildMatrix(); + rb.syncTransform(); + } + } + + if (fired && tr.loc.z < -10) { + tr.loc.setFrom(start); + tr.buildMatrix(); + rb.setLinearVelocity(0, 0, 0); + rb.setAngularVelocity(0, 0, 0); + rb.syncTransform(); + fired = false; + } + }); + } +} diff --git a/game_bowling/Sources/lnx/PinTrait.hx b/game_bowling/Sources/lnx/PinTrait.hx new file mode 100644 index 0000000..c45494c --- /dev/null +++ b/game_bowling/Sources/lnx/PinTrait.hx @@ -0,0 +1,24 @@ +package lnx; + +class PinTrait extends iron.Trait { + + public static var pinsRemoved = 0; + + public function new() { + super(); + + pinsRemoved = 0; + + notifyOnUpdate(function() { + + if (object.transform.loc.z < - 20) { + object.remove(); + + if (++pinsRemoved >= 10) { + leenkx.system.Event.send("exit"); + } + } + + }); + } +} diff --git a/game_bowling/game_bowling.blend b/game_bowling/game_bowling.blend new file mode 100644 index 0000000..aea0b44 Binary files /dev/null and b/game_bowling/game_bowling.blend differ diff --git a/game_bowling/pin.blend b/game_bowling/pin.blend new file mode 100644 index 0000000..de6e0ef Binary files /dev/null and b/game_bowling/pin.blend differ diff --git a/game_bowling/textures/bowling.jpg b/game_bowling/textures/bowling.jpg new file mode 100644 index 0000000..a1488cb Binary files /dev/null and b/game_bowling/textures/bowling.jpg differ diff --git a/game_endlessrun/Bundled/canvas/MyCanvas.files b/game_endlessrun/Bundled/canvas/MyCanvas.files new file mode 100644 index 0000000..e69de29 diff --git a/game_endlessrun/Bundled/canvas/MyCanvas.json b/game_endlessrun/Bundled/canvas/MyCanvas.json new file mode 100644 index 0000000..9aec0f8 --- /dev/null +++ b/game_endlessrun/Bundled/canvas/MyCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":960,"height":540,"elements":[{"id":0,"type":0,"name":"Score","event":"","x":0,"y":0,"width":150,"height":48,"text":"0","asset":"","color":-16777216,"anchor":0,"children":[]}],"assets":[]} \ No newline at end of file diff --git a/game_endlessrun/Sources/lnx/GemTrait.hx b/game_endlessrun/Sources/lnx/GemTrait.hx new file mode 100644 index 0000000..bbc9ebc --- /dev/null +++ b/game_endlessrun/Sources/lnx/GemTrait.hx @@ -0,0 +1,31 @@ +package lnx; + +class GemTrait extends iron.Trait { + + static var gemsCollected = 0; + + var player:iron.object.Object = null; + + public function new() { + super(); + + notifyOnUpdate(function() { + object.transform.rotate(iron.math.Vec4.zAxis(), 0.05); + + if (player == null) player = iron.Scene.active.getChild("Player"); + var w1 = object.transform.world; + var w2 = player.transform.world; + var d = iron.math.Vec4.distance(w1.getLoc(), w2.getLoc()); + + // Collect gem + if (d < 0.6) { + gemsCollected++; + object.remove(); + + // Update UI + var canvas = iron.Scene.active.getTrait(leenkx.trait.internal.CanvasScript); + canvas.getElement("Score").text = gemsCollected + ""; + } + }); + } +} diff --git a/game_endlessrun/Sources/lnx/PlayerController.hx b/game_endlessrun/Sources/lnx/PlayerController.hx new file mode 100644 index 0000000..80f1bc8 --- /dev/null +++ b/game_endlessrun/Sources/lnx/PlayerController.hx @@ -0,0 +1,22 @@ +package lnx; + +class PlayerController extends iron.Trait { + public function new() { + super(); + + notifyOnUpdate(function() { + var kb = iron.system.Input.getKeyboard(); + var x = object.transform.loc.x; + + // Move player + if ((kb.down("left") || kb.down("a")) && x > -1.8) { + object.transform.loc.x -= 0.06; + object.transform.dirty = true; + } + if ((kb.down("right") || kb.down("d")) && x < 1.8) { + object.transform.loc.x += 0.06; + object.transform.dirty = true; + } + }); + } +} diff --git a/game_endlessrun/Sources/lnx/SceneBuilder.hx b/game_endlessrun/Sources/lnx/SceneBuilder.hx new file mode 100644 index 0000000..cf059a3 --- /dev/null +++ b/game_endlessrun/Sources/lnx/SceneBuilder.hx @@ -0,0 +1,51 @@ +package lnx; + +class SceneBuilder extends iron.Trait { + + var dist = 0.0; + var tileNum = 0; + var tilesVisible = 14; + var tiles:Array = []; + var empty:iron.object.Object; + + function spawnTile(num:Int) { + iron.Scene.active.spawnObject("Tile" + Std.random(2), null, function(o) { + + // Remove old tile + if (tiles[num % tilesVisible] != null) { + tiles[num % tilesVisible].remove(); + } + + // Spawn new tile + tiles[num % tilesVisible] = o; + o.transform.loc.x = 0; + o.transform.loc.y = num * 4.0; + o.transform.buildMatrix(); + + // Spawn gem + if (Std.random(3) == 0) { + iron.Scene.active.spawnObject("Gem", o, function(go) { + go.transform.loc.x = (Math.random() - 0.5) * 1.8; + go.transform.loc.z = 0.2; + go.transform.buildMatrix(); + }); + } + }); + } + + public function new() { + super(); + + notifyOnUpdate(function() { + if (empty == null) empty = iron.Scene.active.getChild("Empty"); + + // Spawn new tiles + while (tileNum < Std.int(dist / 4 + 13)) spawnTile(tileNum++); + + // Travel forward + dist += 0.1; + empty.transform.loc.y = dist; + empty.transform.buildMatrix(); + }); + } +} diff --git a/game_endlessrun/game_endless.blend b/game_endlessrun/game_endless.blend new file mode 100644 index 0000000..07ff3ae Binary files /dev/null and b/game_endlessrun/game_endless.blend differ diff --git a/game_endlessrun/grid.png b/game_endlessrun/grid.png new file mode 100644 index 0000000..75d30e0 Binary files /dev/null and b/game_endlessrun/grid.png differ diff --git a/graphics_settings/Bundled/canvas/MyCanvas.files b/graphics_settings/Bundled/canvas/MyCanvas.files new file mode 100644 index 0000000..e69de29 diff --git a/graphics_settings/Bundled/canvas/MyCanvas.json b/graphics_settings/Bundled/canvas/MyCanvas.json new file mode 100644 index 0000000..1948d8e --- /dev/null +++ b/graphics_settings/Bundled/canvas/MyCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":1280,"height":720,"elements":[{"id":2,"type":6,"name":"SSR","event":"","x":20,"y":260,"width":150,"height":34,"rotation":0,"text":"SSR","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true},{"id":3,"type":6,"name":"SSAO","event":"","x":20,"y":300,"width":150,"height":40,"rotation":0,"text":"SSAO","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true},{"id":4,"type":6,"name":"Fullscreen","event":"","x":20,"y":80,"width":191,"height":14,"rotation":0,"text":"Fullscreen","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true},{"id":6,"type":6,"name":"Bloom","event":"","x":20,"y":220,"width":150,"height":44,"rotation":0,"text":"Bloom","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true},{"id":7,"type":6,"name":"MotionBlur","event":"","x":20,"y":180,"width":177,"height":44,"rotation":0,"text":"Motion Blur","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true},{"id":8,"type":8,"name":"Shadows","event":"","x":20,"y":130,"width":160,"height":60,"rotation":0,"text":"High;Medium;Low","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true},{"id":9,"type":10,"name":"ViewDistance","event":"","x":20,"y":360,"width":250,"height":44,"rotation":0,"text":"View Distance","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true},{"id":11,"type":0,"name":"Title","event":"","x":10,"y":10,"width":540,"height":60,"rotation":0,"text":"Graphics Settings","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true},{"id":12,"type":0,"name":"ShadowsTitle","event":"","x":185,"y":130,"width":184,"height":20,"rotation":0,"text":"Shadows","asset":"","color":-6381922,"anchor":0,"parent":null,"children":[],"visible":true},{"id":13,"type":2,"name":"Apply","event":"apply_settings","x":22,"y":479,"width":80,"height":50,"rotation":0,"text":"Apply","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true},{"id":14,"type":9,"name":"FoV","event":"","x":20,"y":420,"width":249,"height":48,"rotation":0,"text":"FoV","asset":"","progress_at":0,"progress_total":100,"strength":1,"alignment":2,"anchor":0,"parent":null,"children":[],"visible":true,"color_text":null,"color":null,"color_hover":null}],"assets":[],"theme":"Default Light"} \ No newline at end of file diff --git a/graphics_settings/Bundled/canvas/_themes.json b/graphics_settings/Bundled/canvas/_themes.json new file mode 100644 index 0000000..fe26c3a --- /dev/null +++ b/graphics_settings/Bundled/canvas/_themes.json @@ -0,0 +1 @@ +[{"NAME":"Default Light","WINDOW_BG_COL":-1052689,"WINDOW_TINT_COL":-14540254,"ACCENT_COL":-1118482,"ACCENT_HOVER_COL":-4473925,"ACCENT_SELECT_COL":-5592406,"BUTTON_COL":-3355444,"BUTTON_TEXT_COL":-14540254,"BUTTON_HOVER_COL":-5000269,"BUTTON_PRESSED_COL":-5131855,"TEXT_COL":-16645630,"LABEL_COL":-5592406,"SEPARATOR_COL":-6710887,"HIGHLIGHT_COL":-14656100,"CONTEXT_COL":-5592406,"PANEL_BG_COL":-5592406,"FONT_SIZE":26,"ELEMENT_W":200,"ELEMENT_H":48,"ELEMENT_OFFSET":8,"ARROW_SIZE":10,"BUTTON_H":44,"CHECK_SIZE":30,"CHECK_SELECT_SIZE":16,"SCROLL_W":12,"TEXT_OFFSET":16,"TAB_W":24,"FILL_WINDOW_BG":false,"FILL_BUTTON_BG":true,"FILL_ACCENT_BG":false,"LINK_STYLE":0,"FULL_TABS":false}] \ No newline at end of file diff --git a/graphics_settings/Bundled/config.lnx b/graphics_settings/Bundled/config.lnx new file mode 100644 index 0000000..2808312 --- /dev/null +++ b/graphics_settings/Bundled/config.lnx @@ -0,0 +1,20 @@ +{ + "rp_bloom": true, + "rp_dynres": false, + "rp_gi": false, + "rp_motionblur": true, + "rp_shadowmap_cascade": 1024, + "rp_shadowmap_cube": 512, + "rp_ssgi": true, + "rp_ssr": true, + "rp_supersample": 1.0, + "window_h": 540, + "window_maximizable": true, + "window_minimizable": true, + "window_mode": 0, + "window_msaa": 1, + "window_resizable": true, + "window_scale": 1.0, + "window_vsync": true, + "window_w": 960 +} \ No newline at end of file diff --git a/graphics_settings/README.md b/graphics_settings/README.md new file mode 100644 index 0000000..4803d5c --- /dev/null +++ b/graphics_settings/README.md @@ -0,0 +1,3 @@ +To generate config.lnx file, enable `Leenkx Project - Write Config`. + +https://api.leenkx3d.org/leenkx/data/Config.html diff --git a/graphics_settings/Sources/lnx/MyTrait.hx b/graphics_settings/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..44ba382 --- /dev/null +++ b/graphics_settings/Sources/lnx/MyTrait.hx @@ -0,0 +1,71 @@ +package lnx; + +import iron.Scene; +import leenkx.system.Event; +import leenkx.data.Config; +import leenkx.trait.internal.CanvasScript; +import leenkx.renderpath.RenderPathCreator; + +// WIP +// To generate config.lnx file, enable 'Leenkx Project - Write Config' +// Fullscreen option will take effect on next game start up (will be resolved) +class MyTrait extends iron.Trait { + + var canvas:CanvasScript; + + public function new() { + super(); + + notifyOnInit(function() { + canvas = Scene.active.getTrait(CanvasScript); + + // Init UI to values loaded from config.lnx file + canvas.notifyOnReady(function() { + canvas.getHandle("Fullscreen").selected = Config.raw.window_mode == 1; + canvas.getHandle("SSAO").selected = Config.raw.rp_ssgi; + canvas.getHandle("SSR").selected = Config.raw.rp_ssr; + canvas.getHandle("Bloom").selected = Config.raw.rp_bloom; + canvas.getHandle("MotionBlur").selected = Config.raw.rp_motionblur; + canvas.getHandle("Shadows").position = getShadowQuality(Config.raw.rp_shadowmap_cascade); + var cam = Scene.active.camera; + canvas.getHandle("ViewDistance").text = Std.string(Math.round(cam.data.raw.far_plane)); + canvas.getHandle("FoV").value = cam.data.raw.fov; + }); + + // Apply button clicked + Event.add("apply_settings", applySettings); + }); + } + + function applySettings() { + + // Apply render path settings + Config.raw.window_mode = canvas.getHandle("Fullscreen").selected ? 1 : 0; + Config.raw.rp_ssgi = canvas.getHandle("SSAO").selected; + Config.raw.rp_ssr = canvas.getHandle("SSR").selected; + Config.raw.rp_bloom = canvas.getHandle("Bloom").selected; + Config.raw.rp_motionblur = canvas.getHandle("MotionBlur").selected; + Config.raw.rp_shadowmap_cascade = getShadowMapSize(canvas.getHandle("Shadows").position); + Config.raw.rp_shadowmap_cube = getShadowMapSize(canvas.getHandle("Shadows").position); + RenderPathCreator.applyConfig(); + + // Apply camera settings + var cam = Scene.active.camera; + cam.data.raw.far_plane = Std.parseFloat(canvas.getHandle("ViewDistance").text); + cam.data.raw.fov = canvas.getHandle("FoV").value; + cam.buildProjection(); + + // Save config.lnx file + Config.save(); + } + + function getShadowQuality(i:Int):Int { + // 0 - High, 1 - Medium, 2 - Low + return i == 2048 ? 0 : i == 1024 ? 1 : 2; + } + + function getShadowMapSize(i:Int):Int { + // High - 2048, Medium - 1024, Low - 512 + return i == 0 ? 2048 : i == 1 ? 1024 : 512; + } +} diff --git a/graphics_settings/graphics_settings.blend b/graphics_settings/graphics_settings.blend new file mode 100644 index 0000000..b19ed8b Binary files /dev/null and b/graphics_settings/graphics_settings.blend differ diff --git a/input_mouselock/README.md b/input_mouselock/README.md new file mode 100644 index 0000000..31c718b --- /dev/null +++ b/input_mouselock/README.md @@ -0,0 +1,3 @@ +Keyboard `Escape` to toggle mouse lock. + +https://api.leenkx3d.org/iron/system/Mouse.html diff --git a/input_mouselock/Sources/lnx/LockTrait.hx b/input_mouselock/Sources/lnx/LockTrait.hx new file mode 100644 index 0000000..8a8f710 --- /dev/null +++ b/input_mouselock/Sources/lnx/LockTrait.hx @@ -0,0 +1,28 @@ +package lnx; + +import iron.math.Vec4; +import iron.system.Input; + +class LockTrait extends iron.Trait { + + public function new() { + + super(); + + var mouse = Input.getMouse(); + var kb = Input.getKeyboard(); + + notifyOnUpdate(() -> { + if (mouse.started("left")) { + mouse.lock(); + } else if (kb.started("escape")) { + mouse.unlock(); + } + var cube = iron.Scene.active.getChild("Cube"); + if (cube != null) { + cube.transform.rotate(Vec4.zAxis(), mouse.movementX * 0.002); + cube.transform.rotate(Vec4.xAxis(), mouse.movementY * 0.002); + } + }); + } +} diff --git a/input_mouselock/input_mouselock.blend b/input_mouselock/input_mouselock.blend new file mode 100644 index 0000000..0b9a731 Binary files /dev/null and b/input_mouselock/input_mouselock.blend differ diff --git a/input_multitouch/Sources/lnx/TouchTrait.hx b/input_multitouch/Sources/lnx/TouchTrait.hx new file mode 100644 index 0000000..8a520d2 --- /dev/null +++ b/input_multitouch/Sources/lnx/TouchTrait.hx @@ -0,0 +1,38 @@ +package lnx; + +import iron.system.Time; +import iron.math.Vec4; + +class TouchTrait extends iron.Trait { + + var touches = [false, false, false]; + + public function new() { + super(); + + notifyOnInit(function() { + var surface = kha.input.Surface.get(); + if (surface != null) surface.notify(touchStart, touchEnd, touchMove); + notifyOnUpdate(update); + }); + } + + function update() { + if (touches[0]) object.transform.rotate(Vec4.zAxis(), 0.05); + if (touches[1]) object.transform.loc.x = Math.sin(Time.time()) * 3.0; + if (touches[2]) object.transform.loc.z = Math.cos(Time.time()); + object.transform.dirty = true; + } + + function touchStart(index:Int, x:Int, y:Int) { + if (index > 2) return; + touches[index] = true; + } + + function touchEnd(index:Int, x:Int, y:Int) { + if (index > 2) return; + touches[index] = false; + } + + function touchMove(index:Int, x:Int, y:Int) {} +} diff --git a/input_multitouch/input_multitouch.blend b/input_multitouch/input_multitouch.blend new file mode 100644 index 0000000..ffcae54 Binary files /dev/null and b/input_multitouch/input_multitouch.blend differ diff --git a/input_sensor/Sources/lnx/SensorTrait.hx b/input_sensor/Sources/lnx/SensorTrait.hx new file mode 100644 index 0000000..ae4e36f --- /dev/null +++ b/input_sensor/Sources/lnx/SensorTrait.hx @@ -0,0 +1,20 @@ +package lnx; + +import iron.math.Vec4; + +class SensorTrait extends iron.Trait { + public function new() { + super(); + + notifyOnInit(function() { + var gyro = kha.input.Sensor.get(kha.input.SensorType.Gyroscope); + if (gyro != null) gyro.notify(onGyroscope); + }); + } + + function onGyroscope(x:Float, y:Float, z:Float) { + object.transform.rotate(Vec4.xAxis(), x / 20); + object.transform.rotate(Vec4.yAxis(), y / 20); + object.transform.rotate(Vec4.zAxis(), z / 20); + } +} diff --git a/input_sensor/input_sensor.blend b/input_sensor/input_sensor.blend new file mode 100644 index 0000000..563f877 Binary files /dev/null and b/input_sensor/input_sensor.blend differ diff --git a/instancing/README.md b/instancing/README.md new file mode 100644 index 0000000..1c09995 --- /dev/null +++ b/instancing/README.md @@ -0,0 +1,6 @@ +#### Enable instancing + +- Select object and set `Properties - Object - Leenkx Props - Instanced Children` property +- Create linked duplicates and parent them to object being instanced + +https://github.com/leenkx3d/leenkx/wiki/instancing diff --git a/instancing/instancing.blend b/instancing/instancing.blend new file mode 100644 index 0000000..072ae3e Binary files /dev/null and b/instancing/instancing.blend differ diff --git a/light_area/checker.png b/light_area/checker.png new file mode 100644 index 0000000..0f4e23a Binary files /dev/null and b/light_area/checker.png differ diff --git a/light_area/checker_rough.png b/light_area/checker_rough.png new file mode 100644 index 0000000..5fad6a5 Binary files /dev/null and b/light_area/checker_rough.png differ diff --git a/light_area/light_area.blend b/light_area/light_area.blend new file mode 100644 index 0000000..a67ff78 Binary files /dev/null and b/light_area/light_area.blend differ diff --git a/light_ies/Bundled/iestexture.png b/light_ies/Bundled/iestexture.png new file mode 100644 index 0000000..05c2d8f Binary files /dev/null and b/light_ies/Bundled/iestexture.png differ diff --git a/light_ies/Bundled/iestexture2.png b/light_ies/Bundled/iestexture2.png new file mode 100644 index 0000000..a92cf09 Binary files /dev/null and b/light_ies/Bundled/iestexture2.png differ diff --git a/light_ies/Bundled/iestexture3.png b/light_ies/Bundled/iestexture3.png new file mode 100644 index 0000000..7701aca Binary files /dev/null and b/light_ies/Bundled/iestexture3.png differ diff --git a/light_ies/light_ies.blend b/light_ies/light_ies.blend new file mode 100644 index 0000000..ec40a1c Binary files /dev/null and b/light_ies/light_ies.blend differ diff --git a/light_probes/light_probes.blend b/light_probes/light_probes.blend new file mode 100644 index 0000000..cea3d26 Binary files /dev/null and b/light_probes/light_probes.blend differ diff --git a/light_probes_cubemap/light_probes_cubemap.blend b/light_probes_cubemap/light_probes_cubemap.blend new file mode 100644 index 0000000..f1ae392 Binary files /dev/null and b/light_probes_cubemap/light_probes_cubemap.blend differ diff --git a/light_probes_plane/light_probes_plane.blend b/light_probes_plane/light_probes_plane.blend new file mode 100644 index 0000000..9c44555 Binary files /dev/null and b/light_probes_plane/light_probes_plane.blend differ diff --git a/light_volumetric/README.md b/light_volumetric/README.md new file mode 100644 index 0000000..59b6a15 --- /dev/null +++ b/light_volumetric/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/screen-effects#volumetric-fog diff --git a/light_volumetric/light_volumetric.blend b/light_volumetric/light_volumetric.blend new file mode 100644 index 0000000..dc765fa Binary files /dev/null and b/light_volumetric/light_volumetric.blend differ diff --git a/load_screen/Bundled/bunny.png b/load_screen/Bundled/bunny.png new file mode 100644 index 0000000..f74994e Binary files /dev/null and b/load_screen/Bundled/bunny.png differ diff --git a/load_screen/Sources/arm/LoadingScreen.hx b/load_screen/Sources/arm/LoadingScreen.hx new file mode 100644 index 0000000..d2ff422 --- /dev/null +++ b/load_screen/Sources/arm/LoadingScreen.hx @@ -0,0 +1,33 @@ +package lnx; + +// Custom loading screen, replaces the internal one + +class LoadingScreen { + + static inline var barColor = 0xff4c6ea5; + static inline var barHeight = 20; + + static var first = true; + static var bunny:kha.Image = null; + + public static function render(g:kha.graphics2.Graphics, assetsLoaded:Int, assetsTotal:Int) { + + // First run, load bundled image + if (first) { + first = false; + iron.data.Data.getImage("bunny.png", function(img:kha.Image) { + bunny = img; + }); + } + + // Draw loaded image + if (bunny != null) { + g.color = 0xffffffff; + g.drawImage(bunny, iron.App.w() / 2 - bunny.width / 2, iron.App.h() / 2 - bunny.height / 2); + } + + // Draw bar + g.color = barColor; + g.fillRect(0, 0, iron.App.w() / assetsTotal * assetsLoaded, barHeight); + } +} diff --git a/load_screen/load_screen.blend b/load_screen/load_screen.blend new file mode 100644 index 0000000..4411b49 Binary files /dev/null and b/load_screen/load_screen.blend differ diff --git a/lod/README.md b/lod/README.md new file mode 100644 index 0000000..dacbf91 --- /dev/null +++ b/lod/README.md @@ -0,0 +1 @@ +LOD (level of detail) can be decreased as the model moves away from the viewer. diff --git a/lod/lod.blend b/lod/lod.blend new file mode 100644 index 0000000..bde54b7 Binary files /dev/null and b/lod/lod.blend differ diff --git a/logic_Hello_World/logic_Hello_World.blend b/logic_Hello_World/logic_Hello_World.blend new file mode 100644 index 0000000..3cf8dba Binary files /dev/null and b/logic_Hello_World/logic_Hello_World.blend differ diff --git a/logic_Hello_World/logic_Hello_World_nodetree.png b/logic_Hello_World/logic_Hello_World_nodetree.png new file mode 100644 index 0000000..2f6f3ba Binary files /dev/null and b/logic_Hello_World/logic_Hello_World_nodetree.png differ diff --git a/logic_Hello_World/logic_Hello_World_output.png b/logic_Hello_World/logic_Hello_World_output.png new file mode 100644 index 0000000..aa4f3bf Binary files /dev/null and b/logic_Hello_World/logic_Hello_World_output.png differ diff --git a/logic_break/logic_break.blend b/logic_break/logic_break.blend new file mode 100644 index 0000000..fb3bed5 Binary files /dev/null and b/logic_break/logic_break.blend differ diff --git a/logic_callgroup/Bundled/canvas/MyCanvas.files b/logic_callgroup/Bundled/canvas/MyCanvas.files new file mode 100644 index 0000000..e69de29 diff --git a/logic_callgroup/Bundled/canvas/MyCanvas.json b/logic_callgroup/Bundled/canvas/MyCanvas.json new file mode 100644 index 0000000..2536e87 --- /dev/null +++ b/logic_callgroup/Bundled/canvas/MyCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":1280,"height":720,"theme":"New Theme","elements":[{"id":0,"type":0,"name":"Text","event":"","x":20,"y":20,"width":960,"height":20,"rotation":0,"text":"Press to call another logic group","asset":"","progress_at":0,"progress_total":100,"strength":1,"alignment":0,"anchor":0,"parent":null,"children":[],"visible":true,"color_text":null}],"assets":[]} \ No newline at end of file diff --git a/logic_callgroup/README.md b/logic_callgroup/README.md new file mode 100644 index 0000000..85cec05 --- /dev/null +++ b/logic_callgroup/README.md @@ -0,0 +1,4 @@ +Keyboard `space`: +- NodeTreeA calls NodeTreeB +- NodeTreeB sets current time to global object property +- NodeTreeA prints value of global object property diff --git a/logic_callgroup/logic_callgroup.blend b/logic_callgroup/logic_callgroup.blend new file mode 100644 index 0000000..6b4420c Binary files /dev/null and b/logic_callgroup/logic_callgroup.blend differ diff --git a/logic_camera_pan/logic_camera_pan.blend b/logic_camera_pan/logic_camera_pan.blend new file mode 100644 index 0000000..10f1cde Binary files /dev/null and b/logic_camera_pan/logic_camera_pan.blend differ diff --git a/logic_camera_zoom/logic_camera_zoom.blend b/logic_camera_zoom/logic_camera_zoom.blend new file mode 100644 index 0000000..a9b636b Binary files /dev/null and b/logic_camera_zoom/logic_camera_zoom.blend differ diff --git a/logic_canvas/Assets/background.png b/logic_canvas/Assets/background.png new file mode 100644 index 0000000..1b36154 Binary files /dev/null and b/logic_canvas/Assets/background.png differ diff --git a/logic_canvas/Assets/charactor.png b/logic_canvas/Assets/charactor.png new file mode 100644 index 0000000..5150d10 Binary files /dev/null and b/logic_canvas/Assets/charactor.png differ diff --git a/logic_canvas/Bundled/canvas/MyCanvas.files b/logic_canvas/Bundled/canvas/MyCanvas.files new file mode 100644 index 0000000..6f17547 --- /dev/null +++ b/logic_canvas/Bundled/canvas/MyCanvas.files @@ -0,0 +1,2 @@ +../../Assets/charactor.png +../../Assets/background.png diff --git a/logic_canvas/Bundled/canvas/MyCanvas.json b/logic_canvas/Bundled/canvas/MyCanvas.json new file mode 100644 index 0000000..6b912f9 --- /dev/null +++ b/logic_canvas/Bundled/canvas/MyCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":1024,"height":600,"elements":[{"id":1,"type":8,"name":"Combo","event":"","x":0,"y":200,"width":150,"height":44,"rotation":0,"text":"My Combo","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":false},{"id":0,"type":9,"name":"Shape","event":"","x":0,"y":50,"width":150,"height":100,"rotation":0,"text":"My Shape","asset":"","color":16777215,"anchor":0,"parent":3,"children":[],"visible":false},{"id":3,"type":3,"name":"EmptyB","event":"","x":0,"y":0,"width":0,"height":0,"rotation":0,"text":"My Empty","asset":"","color":-1,"anchor":0,"parent":null,"children":[0,1,11,12,14,15,16,19,18,9,21],"visible":false},{"id":2,"type":3,"name":"EmptyA","event":"","x":0,"y":0,"width":0,"height":0,"rotation":0,"text":"My Empty","asset":"","color":-1,"anchor":0,"parent":null,"children":[5,4,10,8,7,17,20],"visible":true},{"id":4,"type":1,"name":"Charactor","event":"","x":350,"y":300,"width":120,"height":200,"rotation":0,"text":"My Image","asset":"charactor.png","color":-1,"anchor":0,"parent":2,"children":[],"visible":true},{"id":5,"type":1,"name":"Background","event":"","x":0,"y":0,"width":1024,"height":600,"rotation":0,"text":"My Image","asset":"background.png","color":-1,"anchor":0,"parent":2,"children":[],"visible":true},{"id":19,"type":0,"name":"escInfo","event":"","x":640,"y":0,"width":430,"height":44,"rotation":0,"text":"ESC : Hide empty","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":true},{"id":8,"type":0,"name":"escInfo","event":"","x":640,"y":0,"width":430,"height":44,"rotation":0,"text":"ESC : Hide empty","asset":"","color":-1,"anchor":0,"parent":2,"children":[],"visible":true},{"id":18,"type":0,"name":"tabInfo","event":"","x":250,"y":0,"width":430,"height":44,"rotation":0,"text":"TAB : Change empty","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":true},{"id":7,"type":0,"name":"tabInfo","event":"","x":250,"y":0,"width":430,"height":44,"rotation":0,"text":"TAB : Change empty","asset":"","color":-1,"anchor":0,"parent":2,"children":[],"visible":true},{"id":9,"type":0,"name":"EmptyBInfo","event":"","x":0,"y":0,"width":200,"height":44,"rotation":0,"text":"EmptyB","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":true},{"id":10,"type":0,"name":"wasdInfo","event":"","x":20,"y":50,"width":600,"height":44,"rotation":0,"text":"WASD : Character operation","asset":"","color":-1,"anchor":0,"parent":2,"children":[],"visible":true},{"id":12,"type":6,"name":"Check","event":"","x":0,"y":100,"width":150,"height":44,"rotation":0,"text":"My Check","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":false},{"id":11,"type":2,"name":"Button","event":"","x":0,"y":50,"width":150,"height":44,"rotation":0,"text":"My Button","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":false},{"id":14,"type":10,"name":"Slider","event":"","x":0,"y":250,"width":150,"height":44,"rotation":0,"text":"My Slider","asset":"","color":-1,"anchor":0,"parent":3,"children":[22,25,26,27],"visible":true},{"id":15,"type":11,"name":"Input","event":"","x":0,"y":300,"width":150,"height":44,"rotation":0,"text":"","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":false},{"id":16,"type":7,"name":"Radio","event":"","x":0,"y":150,"width":150,"height":44,"rotation":0,"text":"My Radio","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":false},{"id":17,"type":0,"name":"EmptyAInfo","event":"","x":0,"y":0,"width":200,"height":44,"rotation":0,"text":"EmptyA","asset":"","color":-1,"anchor":0,"parent":2,"children":[],"visible":true},{"id":20,"type":0,"name":"AddInfo","event":"","x":670,"y":35,"width":150,"height":30,"rotation":0,"text":"or e","asset":"","color":-1,"anchor":0,"parent":2,"children":[],"visible":true},{"id":21,"type":0,"name":"AddInfo","event":"","x":670,"y":35,"width":150,"height":30,"rotation":0,"text":"or e","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":true},{"id":22,"type":0,"name":"TextSlider1","event":"","x":150,"y":-10,"width":330,"height":44,"rotation":0,"text":"Slider value is","asset":"","color":-1,"anchor":0,"parent":14,"children":[],"visible":true},{"id":25,"type":0,"name":"TextSlider2","event":"","x":400,"y":-10,"width":90,"height":44,"rotation":0,"text":"","asset":"","color":-1,"anchor":0,"parent":14,"children":[],"visible":true},{"id":26,"type":0,"name":"TextSlider3","event":"","x":0,"y":50,"width":950,"height":44,"rotation":0,"text":"Press 0 key to reset the slider value to 0.","asset":"","color":-1,"anchor":0,"parent":14,"children":[],"visible":true},{"id":27,"type":0,"name":"TextSlider4","event":"","x":20,"y":90,"width":560,"height":30,"rotation":0,"text":"Numeric keypad input is not accepted.","asset":"","color":-1,"anchor":0,"parent":14,"children":[],"visible":true}],"assets":[{"name":"charactor.png","file":"../../Assets/charactor.png","id":1},{"name":"background.png","file":"../../Assets/background.png","id":2}]} \ No newline at end of file diff --git a/logic_canvas/Bundled/canvas/_themes.json b/logic_canvas/Bundled/canvas/_themes.json new file mode 100644 index 0000000..e69de29 diff --git a/logic_canvas/logic_canvas.blend b/logic_canvas/logic_canvas.blend new file mode 100644 index 0000000..fd6dee1 Binary files /dev/null and b/logic_canvas/logic_canvas.blend differ diff --git a/logic_event_fromhaxe/README.md b/logic_event_fromhaxe/README.md new file mode 100644 index 0000000..e69de29 diff --git a/logic_event_fromhaxe/Sources/lnx/SendEvent.hx b/logic_event_fromhaxe/Sources/lnx/SendEvent.hx new file mode 100644 index 0000000..c038508 --- /dev/null +++ b/logic_event_fromhaxe/Sources/lnx/SendEvent.hx @@ -0,0 +1,19 @@ +package lnx; + +import leenkx.system.Event; + +class SendEvent extends iron.Trait { + + public function new() { + + super(); + + var mouse = iron.system.Input.getMouse(); + + notifyOnUpdate(function() { + if (mouse.started("left")) { + Event.send("my_event"); + } + }); + } +} diff --git a/logic_event_fromhaxe/logic_event_fromhaxe.blend b/logic_event_fromhaxe/logic_event_fromhaxe.blend new file mode 100644 index 0000000..4a301ac Binary files /dev/null and b/logic_event_fromhaxe/logic_event_fromhaxe.blend differ diff --git a/logic_event_global/logic_event_global.blend b/logic_event_global/logic_event_global.blend new file mode 100644 index 0000000..5a92a3c Binary files /dev/null and b/logic_event_global/logic_event_global.blend differ diff --git a/logic_event_object/README.md b/logic_event_object/README.md new file mode 100644 index 0000000..2e1e6fd --- /dev/null +++ b/logic_event_object/README.md @@ -0,0 +1 @@ +Keyboard left/right to send event. diff --git a/logic_event_object/Sources/lnx/SendEvent.hx b/logic_event_object/Sources/lnx/SendEvent.hx new file mode 100644 index 0000000..bff3666 --- /dev/null +++ b/logic_event_object/Sources/lnx/SendEvent.hx @@ -0,0 +1,16 @@ +package lnx; + +import leenkx.system.Event; + +class SendEvent extends iron.Trait { + public function new() { + super(); + + notifyOnUpdate(function() { + var mouse = iron.system.Input.getMouse(); + if (mouse.started("left")) { + Event.send("my_event"); + } + }); + } +} diff --git a/logic_event_object/logic_event_object.blend b/logic_event_object/logic_event_object.blend new file mode 100644 index 0000000..5a6dd5d Binary files /dev/null and b/logic_event_object/logic_event_object.blend differ diff --git a/logic_gamepad/Bundled/canvas/MyCanvas.files b/logic_gamepad/Bundled/canvas/MyCanvas.files new file mode 100644 index 0000000..e69de29 diff --git a/logic_gamepad/Bundled/canvas/MyCanvas.json b/logic_gamepad/Bundled/canvas/MyCanvas.json new file mode 100644 index 0000000..26cb4f5 --- /dev/null +++ b/logic_gamepad/Bundled/canvas/MyCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":1280,"height":720,"theme":"Default Light","elements":[{"id":2,"type":12,"name":"Filled_Rectangle","event":"","x":0,"y":0,"width":250,"height":50,"rotation":0,"text":"My Filled_Rectangle","asset":"","progress_at":0,"progress_total":100,"strength":1,"alignment":0,"anchor":0,"parent":null,"children":[],"visible":true,"color":null},{"id":1,"type":6,"name":"VGamepad","event":"","x":0,"y":0,"width":250,"height":50,"rotation":0,"text":"Virtual Gamepad","asset":"","progress_at":0,"progress_total":100,"strength":1,"alignment":0,"anchor":0,"parent":null,"children":[],"visible":true,"color_text":-6738141,"color":-3392436,"color_hover":-5726816}],"assets":[]} \ No newline at end of file diff --git a/logic_gamepad/Bundled/canvas/_themes.json b/logic_gamepad/Bundled/canvas/_themes.json new file mode 100644 index 0000000..e69de29 diff --git a/logic_gamepad/Sources/lnx/VirtualGamepad.hx b/logic_gamepad/Sources/lnx/VirtualGamepad.hx new file mode 100644 index 0000000..4bdc16a --- /dev/null +++ b/logic_gamepad/Sources/lnx/VirtualGamepad.hx @@ -0,0 +1,112 @@ +package lnx; + +import iron.Trait; +import iron.math.Vec2; +import iron.system.Input; + +using kha.graphics2.GraphicsExtension; + +@:access(iron.system.Gamepad) +class VirtualGamepad extends Trait { + + @prop public var gamepad : Int = 0; + @prop public var radius : Int = 100; + @prop public var offset : Int = 45; + @prop public var sizeRatio : Float = 2.2; + + public var colorA : kha.Color = 0xff888888; + public var colorB : kha.Color = 0xffcf2b43; + + var leftPadX = 0; + var leftPadY = 0; + var rightPadX = 0; + var rightPadY = 0; + var leftStickX = 0; + var leftStickY = 0; + var rightStickX = 0; + var rightStickY = 0; + // var leftStickXLast = 0; + // var leftStickYLast = 0; + // var rightStickXLast = 0; + // var rightStickYLast = 0; + var leftLocked = false; + var rightLocked = false; + var gamepad_ : Gamepad; + + public function new() { + super(); + notifyOnInit(function() { + gamepad_ = Input.getGamepad( gamepad ); + notifyOnUpdate(update); + notifyOnRender2D(render2D); + }); + } + + function update() { + + var r = radius; + var o = offset; + + leftPadX = r + o; + rightPadX = iron.App.w() - r - o; + leftPadY = rightPadY = iron.App.h() - r - o; + + final mouse = Input.getMouse(); + if (mouse.started() ) { + leftLocked = Vec2.distancef(mouse.x, mouse.y, leftPadX, leftPadY) <= r; + } else if (mouse.released()) { + leftLocked = false; + } + if (leftLocked) { + leftStickX = Std.int(mouse.x - leftPadX); + leftStickY = Std.int(mouse.y - leftPadY); + if (Math.sqrt(leftStickX * leftStickX + leftStickY * leftStickY) > r) { + leftStickX = Std.int(r * (leftStickX / Math.sqrt(leftStickX * leftStickX + leftStickY * leftStickY))); + leftStickY = Std.int(r * (leftStickY / Math.sqrt(leftStickX * leftStickX + leftStickY * leftStickY))); + } + } else { + leftStickX = leftStickY = 0; + } + + if (mouse.started() ) { + rightLocked = Vec2.distancef(mouse.x, mouse.y, rightPadX, rightPadY) <= r; + } else if (mouse.released()) { + rightLocked = false; + } + if (rightLocked) { + rightStickX = Std.int(mouse.x - rightPadX); + rightStickY = Std.int(mouse.y - rightPadY); + if (Math.sqrt(rightStickX * rightStickX + rightStickY * rightStickY) > r) { + rightStickX = Std.int(r * (rightStickX / Math.sqrt(rightStickX * rightStickX + rightStickY * rightStickY))); + rightStickY = Std.int(r * (rightStickY / Math.sqrt(rightStickX * rightStickX + rightStickY * rightStickY))); + } + } + else { + rightStickX = rightStickY = 0; + } + + gamepad_.axisListener(0, leftStickX / r); + gamepad_.axisListener(1, leftStickY / r); + gamepad_.axisListener(2, rightStickY / r); + gamepad_.axisListener(3, rightStickX / r); + + // leftStickXLast = leftStickX; + // leftStickYLast = leftStickY; + // rightStickXLast = rightStickX; + // rightStickYLast = rightStickY; + } + + function render2D(g: kha.graphics2.Graphics) { + + var r = radius; + var r2 = Std.int(r / sizeRatio); + + g.color = colorA; + g.fillCircle(leftPadX, leftPadY, r); + g.fillCircle(rightPadX, rightPadY, r); + + g.color = colorB; + g.fillCircle(leftPadX + leftStickX, leftPadY + leftStickY, r2); + g.fillCircle(rightPadX + rightStickX, rightPadY + rightStickY, r2); + } +} diff --git a/logic_gamepad/logic_gamepad.blend b/logic_gamepad/logic_gamepad.blend new file mode 100644 index 0000000..5f30fad Binary files /dev/null and b/logic_gamepad/logic_gamepad.blend differ diff --git a/logic_gate/checker.png b/logic_gate/checker.png new file mode 100644 index 0000000..75d30e0 Binary files /dev/null and b/logic_gate/checker.png differ diff --git a/logic_gate/checker_rough.png b/logic_gate/checker_rough.png new file mode 100644 index 0000000..5fad6a5 Binary files /dev/null and b/logic_gate/checker_rough.png differ diff --git a/logic_gate/logic_gate.blend b/logic_gate/logic_gate.blend new file mode 100644 index 0000000..b9cd12a Binary files /dev/null and b/logic_gate/logic_gate.blend differ diff --git a/logic_get_contacts/logic_get_contacts.blend b/logic_get_contacts/logic_get_contacts.blend new file mode 100644 index 0000000..fb5b152 Binary files /dev/null and b/logic_get_contacts/logic_get_contacts.blend differ diff --git a/logic_keyboard/logic_keyboard.blend b/logic_keyboard/logic_keyboard.blend new file mode 100644 index 0000000..bf0db92 Binary files /dev/null and b/logic_keyboard/logic_keyboard.blend differ diff --git a/logic_linked_variable/logic_linked_variable.blend b/logic_linked_variable/logic_linked_variable.blend new file mode 100644 index 0000000..b8195eb Binary files /dev/null and b/logic_linked_variable/logic_linked_variable.blend differ diff --git a/logic_loadurl/logic_loadurl.blend b/logic_loadurl/logic_loadurl.blend new file mode 100644 index 0000000..2060f2c Binary files /dev/null and b/logic_loadurl/logic_loadurl.blend differ diff --git a/logic_mouselock/logic_mouselock.blend b/logic_mouselock/logic_mouselock.blend new file mode 100644 index 0000000..8611af4 Binary files /dev/null and b/logic_mouselock/logic_mouselock.blend differ diff --git a/logic_object_rotate/README.md b/logic_object_rotate/README.md new file mode 100644 index 0000000..f97d809 --- /dev/null +++ b/logic_object_rotate/README.md @@ -0,0 +1 @@ +Press keyboard `A`, `D` to rotate object diff --git a/logic_object_rotate/logic_object_rotate.blend b/logic_object_rotate/logic_object_rotate.blend new file mode 100644 index 0000000..4ccc45d Binary files /dev/null and b/logic_object_rotate/logic_object_rotate.blend differ diff --git a/logic_object_scale/README.md b/logic_object_scale/README.md new file mode 100644 index 0000000..ec9c10e --- /dev/null +++ b/logic_object_scale/README.md @@ -0,0 +1 @@ +Press keyboard `↓` `↑` to scale object diff --git a/logic_object_scale/logic_object_scale.blend b/logic_object_scale/logic_object_scale.blend new file mode 100644 index 0000000..edef32e Binary files /dev/null and b/logic_object_scale/logic_object_scale.blend differ diff --git a/logic_object_translate/README.md b/logic_object_translate/README.md new file mode 100644 index 0000000..766b938 --- /dev/null +++ b/logic_object_translate/README.md @@ -0,0 +1 @@ +Keyboard `WASD` to translate object diff --git a/logic_object_translate/logic_object_translate.blend b/logic_object_translate/logic_object_translate.blend new file mode 100644 index 0000000..3a2755e Binary files /dev/null and b/logic_object_translate/logic_object_translate.blend differ diff --git a/logic_pause_trait/README.md b/logic_pause_trait/README.md new file mode 100644 index 0000000..fb8b426 --- /dev/null +++ b/logic_pause_trait/README.md @@ -0,0 +1,3 @@ +#### Keyboard +- `1` pause trait +- `2` resume trait diff --git a/logic_pause_trait/logic_pause_trait.blend b/logic_pause_trait/logic_pause_trait.blend new file mode 100644 index 0000000..676c907 Binary files /dev/null and b/logic_pause_trait/logic_pause_trait.blend differ diff --git a/logic_pong/checker.png b/logic_pong/checker.png new file mode 100644 index 0000000..0f4e23a Binary files /dev/null and b/logic_pong/checker.png differ diff --git a/logic_pong/checker_rough.png b/logic_pong/checker_rough.png new file mode 100644 index 0000000..5fad6a5 Binary files /dev/null and b/logic_pong/checker_rough.png differ diff --git a/logic_pong/logic_pong.blend b/logic_pong/logic_pong.blend new file mode 100644 index 0000000..122768b Binary files /dev/null and b/logic_pong/logic_pong.blend differ diff --git a/logic_scenes/README.md b/logic_scenes/README.md new file mode 100644 index 0000000..359a34c --- /dev/null +++ b/logic_scenes/README.md @@ -0,0 +1,3 @@ +#### Keyboard +- `1` to drop all objects from other scene into current +- `2` to remove current scene and switch to Scene3 diff --git a/logic_scenes/logic_scenes.blend b/logic_scenes/logic_scenes.blend new file mode 100644 index 0000000..a252674 Binary files /dev/null and b/logic_scenes/logic_scenes.blend differ diff --git a/logic_scenetree/README.md b/logic_scenetree/README.md new file mode 100644 index 0000000..0ebe169 --- /dev/null +++ b/logic_scenetree/README.md @@ -0,0 +1 @@ +Check console \ No newline at end of file diff --git a/logic_scenetree/logic_scenetree.blend b/logic_scenetree/logic_scenetree.blend new file mode 100644 index 0000000..df5be94 Binary files /dev/null and b/logic_scenetree/logic_scenetree.blend differ diff --git a/logic_script/logic_script.blend b/logic_script/logic_script.blend new file mode 100644 index 0000000..5e0adcf Binary files /dev/null and b/logic_script/logic_script.blend differ diff --git a/logic_set_property/README.md b/logic_set_property/README.md new file mode 100644 index 0000000..ff4a0c4 --- /dev/null +++ b/logic_set_property/README.md @@ -0,0 +1 @@ +- Press `1`, `2` or `3` diff --git a/logic_set_property/logic_set_property.blend b/logic_set_property/logic_set_property.blend new file mode 100644 index 0000000..1716ba8 Binary files /dev/null and b/logic_set_property/logic_set_property.blend differ diff --git a/logic_toy_car/README.md b/logic_toy_car/README.md new file mode 100644 index 0000000..37157c4 --- /dev/null +++ b/logic_toy_car/README.md @@ -0,0 +1 @@ +Car control: `← ↓ ↑ →` diff --git a/logic_toy_car/logic_toy_car.blend b/logic_toy_car/logic_toy_car.blend new file mode 100644 index 0000000..89a1399 Binary files /dev/null and b/logic_toy_car/logic_toy_car.blend differ diff --git a/logic_transform/logic_transform.blend b/logic_transform/logic_transform.blend new file mode 100644 index 0000000..2b8d4e0 Binary files /dev/null and b/logic_transform/logic_transform.blend differ diff --git a/macro_lnxpack/README.md b/macro_lnxpack/README.md new file mode 100644 index 0000000..82717ad --- /dev/null +++ b/macro_lnxpack/README.md @@ -0,0 +1,4 @@ +Use build macro to: +- Create trait constructor +- Create trait init function +- Parse exported `Scene.lnx` file and auto create references to objects in scene diff --git a/macro_lnxpack/Sources/lnx/Game.hx b/macro_lnxpack/Sources/lnx/Game.hx new file mode 100644 index 0000000..fe07467 --- /dev/null +++ b/macro_lnxpack/Sources/lnx/Game.hx @@ -0,0 +1,13 @@ +package lnx; + +import iron.math.Vec4; + +@:build(lnx.Macros.build()) +class Game extends iron.Trait { + + function update() { + Cube.transform.rotate( Vec4.zAxis(), 0.01 ); + Icosphere.transform.rotate( Vec4.yAxis(), 0.01 ); + Torus.transform.rotate( Vec4.xAxis(), 0.01 ); + } +} diff --git a/macro_lnxpack/Sources/lnx/Macros.hx b/macro_lnxpack/Sources/lnx/Macros.hx new file mode 100644 index 0000000..c222a80 --- /dev/null +++ b/macro_lnxpack/Sources/lnx/Macros.hx @@ -0,0 +1,85 @@ +package lnx; + +#if macro + +import haxe.macro.Context; +import haxe.macro.Expr; +import iron.data.SceneFormat; +import iron.system.LnxPack; +import sys.FileSystem; +import sys.io.File; + +using StringTools; +using haxe.io.Path; + +class Macros { + + static function build() { + var fields = Context.getBuildFields(); + var pos = Context.currentPos(); + var target = if( Context.defined('kha_krom') ) 'krom'; + else if( Context.defined('kha_html5') ) 'html5'; + else Context.fatalError('Only krom and html5 are supported targets for this project', pos ); + var dir = Sys.getCwd() + target; + var files = FileSystem.readDirectory(dir); + var sceneData : TSceneFormat = null; + var meshes = new Array(); + for( file in files ) { + if( file == 'Scene.lnx' ) { + var p = '$dir/$file'; + sceneData = LnxPack.decode( File.getBytes(p) ); + trace(sceneData); + trace(sceneData.name); + for( obj in sceneData.objects ) { + if( obj.properties != null ) + for( p in obj.properties ) trace(p.name +' = '+ p.value); + if( obj.type == 'mesh_object' ) + meshes.push(obj.name); + } + break; + } + } + + var constructorExprs = new Array(); + constructorExprs.push(macro super() ); + constructorExprs.push(macro notifyOnInit(init) ); + fields.push({ + access: [APublic,AInline], + name: 'new', + pos: pos, + kind: FFun({ + args: [], + ret: macro: Void, + expr: { expr: EBlock( constructorExprs ), pos: pos } + }), + }); + + var initExprs = new Array(); + initExprs.push( macro trace("Init") ); + for( mesh in meshes ) { + fields.push({ + name: mesh, + access: [APublic], + kind: FVar(macro: iron.object.MeshObject, macro null), + pos: pos + }); + initExprs.push( macro this.$mesh = iron.Scene.active.getMesh($v{mesh}) ); + } + initExprs.push( macro notifyOnUpdate(update) ); + + fields.push({ + name: 'init', + access: [], + kind: FFun({ + args: [], + ret: macro : Void, + expr: { expr: EBlock( initExprs ), pos: Context.currentPos() } + }), + pos: pos + }); + + return fields; + } +} + +#end diff --git a/macro_lnxpack/macro_lnxpack.blend b/macro_lnxpack/macro_lnxpack.blend new file mode 100644 index 0000000..70a0d62 Binary files /dev/null and b/macro_lnxpack/macro_lnxpack.blend differ diff --git a/material_alpha/README.md b/material_alpha/README.md new file mode 100644 index 0000000..64c0222 --- /dev/null +++ b/material_alpha/README.md @@ -0,0 +1 @@ +Transparency using `Properties - Material - Leenkx Props - Alpha Test` diff --git a/material_alpha/circle.png b/material_alpha/circle.png new file mode 100644 index 0000000..18daedb Binary files /dev/null and b/material_alpha/circle.png differ diff --git a/material_alpha/material_alpha.blend b/material_alpha/material_alpha.blend new file mode 100644 index 0000000..0d5af84 Binary files /dev/null and b/material_alpha/material_alpha.blend differ diff --git a/material_bake/material_bake.blend b/material_bake/material_bake.blend new file mode 100644 index 0000000..57f32fe Binary files /dev/null and b/material_bake/material_bake.blend differ diff --git a/material_batch/material_batch.blend b/material_batch/material_batch.blend new file mode 100644 index 0000000..5d022ac Binary files /dev/null and b/material_batch/material_batch.blend differ diff --git a/material_billboard/bunny.png b/material_billboard/bunny.png new file mode 100644 index 0000000..f74994e Binary files /dev/null and b/material_billboard/bunny.png differ diff --git a/material_billboard/material_billboard.blend b/material_billboard/material_billboard.blend new file mode 100644 index 0000000..9490c20 Binary files /dev/null and b/material_billboard/material_billboard.blend differ diff --git a/material_bump/brick_bump.jpg b/material_bump/brick_bump.jpg new file mode 100644 index 0000000..727b52a Binary files /dev/null and b/material_bump/brick_bump.jpg differ diff --git a/material_bump/material_bump.blend b/material_bump/material_bump.blend new file mode 100644 index 0000000..7f09c5e Binary files /dev/null and b/material_bump/material_bump.blend differ diff --git a/material_decal/decal.png b/material_decal/decal.png new file mode 100644 index 0000000..55cce62 Binary files /dev/null and b/material_decal/decal.png differ diff --git a/material_decal/material_decal.blend b/material_decal/material_decal.blend new file mode 100644 index 0000000..c13c543 Binary files /dev/null and b/material_decal/material_decal.blend differ diff --git a/material_decal_colors/README.md b/material_decal_colors/README.md new file mode 100644 index 0000000..9974fb6 --- /dev/null +++ b/material_decal_colors/README.md @@ -0,0 +1,4 @@ +- Left click and drag to rotate the monkey. +- Left click to spawn decal with random color. +- Scroll up or down to zoom in or out. +- Right click to clear all decals diff --git a/material_decal_colors/material_decal_colors.blend b/material_decal_colors/material_decal_colors.blend new file mode 100644 index 0000000..fe14c8f Binary files /dev/null and b/material_decal_colors/material_decal_colors.blend differ diff --git a/material_depth_texture/Assets/checker_rough.png b/material_depth_texture/Assets/checker_rough.png new file mode 100644 index 0000000..5fad6a5 Binary files /dev/null and b/material_depth_texture/Assets/checker_rough.png differ diff --git a/material_depth_texture/Assets/grid.png b/material_depth_texture/Assets/grid.png new file mode 100644 index 0000000..84c984b Binary files /dev/null and b/material_depth_texture/Assets/grid.png differ diff --git a/material_depth_texture/README.md b/material_depth_texture/README.md new file mode 100644 index 0000000..036c25c --- /dev/null +++ b/material_depth_texture/README.md @@ -0,0 +1,9 @@ +Wall with a material that's reading from a depth texture, which is copied from the depth buffer before drawing the wall as the last object in the scene. + +#### To use this in your own projects: + +1. Enable `Material Properties > Leenkx Props > Read Depth` +2. Make sure `Render Properties > Leenkx Render Path > Renderer > Depth Texture` is set to `Auto` or `On` +3. Add a `Shader Data` node with a uniform sampler2D with the name `depthtex` and separate the x value from the color output + +Note that the depth values depend on the camera far/near values! Also the compositor needs to be enabled on forward render path in order to work. \ No newline at end of file diff --git a/material_depth_texture/material_depth_texture.blend b/material_depth_texture/material_depth_texture.blend new file mode 100644 index 0000000..1fefbc3 Binary files /dev/null and b/material_depth_texture/material_depth_texture.blend differ diff --git a/material_displace/README.md b/material_displace/README.md new file mode 100644 index 0000000..4a3bb77 --- /dev/null +++ b/material_displace/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/materials#displacement diff --git a/material_displace/material_displace.blend b/material_displace/material_displace.blend new file mode 100644 index 0000000..b4f7dc8 Binary files /dev/null and b/material_displace/material_displace.blend differ diff --git a/material_glossy_metallic/material_glossy_metallic.blend b/material_glossy_metallic/material_glossy_metallic.blend new file mode 100644 index 0000000..a24e896 Binary files /dev/null and b/material_glossy_metallic/material_glossy_metallic.blend differ diff --git a/material_multiuvs/multiuvs.blend b/material_multiuvs/multiuvs.blend new file mode 100644 index 0000000..fa96ceb Binary files /dev/null and b/material_multiuvs/multiuvs.blend differ diff --git a/material_normalmap/material_normalmap.blend b/material_normalmap/material_normalmap.blend new file mode 100644 index 0000000..9746d03 Binary files /dev/null and b/material_normalmap/material_normalmap.blend differ diff --git a/material_params/Bundled/tex1.png b/material_params/Bundled/tex1.png new file mode 100644 index 0000000..4ca6a31 Binary files /dev/null and b/material_params/Bundled/tex1.png differ diff --git a/material_params/Bundled/tex2.png b/material_params/Bundled/tex2.png new file mode 100644 index 0000000..1d36b4a Binary files /dev/null and b/material_params/Bundled/tex2.png differ diff --git a/material_params/README.md b/material_params/README.md new file mode 100644 index 0000000..38cf0a1 --- /dev/null +++ b/material_params/README.md @@ -0,0 +1,9 @@ +Shows how to control material nodes at run-time. +Press 1, 2, 3 to change parameters. + +- Enable `Parameter` property in `Logic Node Editor - Properties - Leenkx Material Node` +- RGB, Value and Image Texture nodes are supported +- See `MyTrait` script to set material parameters using Haxe +- See `NodeTree` to set material parameters using logic nodes + +https://github.com/leenkx3d/leenkx/wiki/materials#material-parameters diff --git a/material_params/Sources/lnx/MyTrait.hx b/material_params/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..e7aefa1 --- /dev/null +++ b/material_params/Sources/lnx/MyTrait.hx @@ -0,0 +1,53 @@ +package lnx; + +import iron.math.Vec4; +import iron.object.Object; +import iron.object.Uniforms; +import iron.data.Data; +import iron.data.MaterialData; +import iron.system.Time; + +class MyTrait extends iron.Trait { + + var tex1:kha.Image = null; + var tex2:kha.Image = null; + + public function new() { + super(); + notifyOnInit(() -> { + // Register link callbacks + Uniforms.externalVec3Links.push(vec3Link); + Uniforms.externalFloatLinks.push(floatLink); + Uniforms.externalTextureLinks.push(textureLink); + }); + Data.getImage("tex1.png", img -> tex1 = img ); + Data.getImage("tex2.png", img -> tex2 = img ); + } + + function vec3Link(object:Object, mat:MaterialData, link:String):Vec4 { + // object - currently bound object + // mat - currently bound material + // link - material node name + if (link == "RGB") { + var t = Time.time(); + return new Vec4(Math.sin(t) * 0.5 + 0.5, Math.cos(t) * 0.5 + 0.5, Math.sin(t + 0.5) * 0.5 + 0.5); + } + return null; + } + + function floatLink(object:Object, mat:MaterialData, link:String):Null { + if (link == "Value") { + var t = Time.time(); + return Math.floor(t); + } + return null; + } + + function textureLink(object:Object, mat:MaterialData, link:String):kha.Image { + if (link == "Image Texture") { + var t = Time.time(); + return Math.sin(t) > 0 ? tex1 : tex2; + } + return null; + } +} diff --git a/material_params/material_params.blend b/material_params/material_params.blend new file mode 100644 index 0000000..39f84c0 Binary files /dev/null and b/material_params/material_params.blend differ diff --git a/material_shadeless/material_shadeless.blend b/material_shadeless/material_shadeless.blend new file mode 100644 index 0000000..486f315 Binary files /dev/null and b/material_shadeless/material_shadeless.blend differ diff --git a/material_shaders/Bundled/MyCustomMaterial/MyCustomMaterial.json b/material_shaders/Bundled/MyCustomMaterial/MyCustomMaterial.json new file mode 100644 index 0000000..94dd7fc --- /dev/null +++ b/material_shaders/Bundled/MyCustomMaterial/MyCustomMaterial.json @@ -0,0 +1,58 @@ +{ + "shader_datas": [ + { + "contexts": [ + { + "color_attachments": [ + "RGBA64" + ], + "compare_mode": "less", + "constants": [ + { + "link": "_worldViewProjectionMatrix", + "name": "WVP", + "type": "mat4" + }, + { + "link": "_normalMatrix", + "name": "N", + "type": "mat3" + }, + { + "link": "_posUnpack", + "name": "posUnpack", + "type": "float" + }, + { + "link": "_time", + "name": "time", + "type": "float" + }, + { + "link": "myParam", + "name": "myParam", + "type": "float" + } + ], + "cull_mode": "clockwise", + "depth_write": true, + "fragment_shader": "MyCustomMaterial.frag", + "name": "mesh", + "texture_units": [], + "vertex_elements": [ + { + "name": "pos", + "data": "short4norm" + }, + { + "name": "nor", + "data": "short2norm" + } + ], + "vertex_shader": "MyCustomMaterial.vert" + } + ], + "name": "MyCustomMaterial" + } + ] +} diff --git a/material_shaders/Shaders/MyCustomMaterial.frag.glsl b/material_shaders/Shaders/MyCustomMaterial.frag.glsl new file mode 100644 index 0000000..b61495f --- /dev/null +++ b/material_shaders/Shaders/MyCustomMaterial.frag.glsl @@ -0,0 +1,17 @@ +#version 450 + +in vec3 mpos; +in vec3 normal; + +// Color of each fragment on the screen +out vec4 fragColor; + +void main() { + // Shadeless red color + //fragColor = vec4(1.0,0.0,0.0,0.0); + + // Assuming forward rendering path for simplicity + vec3 col = (mpos + vec3(1.0)) / 8.0; + col += normal * 0.1; + fragColor = vec4(col, 1.0); +} diff --git a/material_shaders/Shaders/MyCustomMaterial.vert.glsl b/material_shaders/Shaders/MyCustomMaterial.vert.glsl new file mode 100644 index 0000000..85438cb --- /dev/null +++ b/material_shaders/Shaders/MyCustomMaterial.vert.glsl @@ -0,0 +1,28 @@ +#version 450 + +// Armory uses packed vertex data to preserve memory +in vec4 pos; // pos.xyz, nor.z +in vec2 nor; // nor.xy + +uniform mat4 WVP; +uniform mat3 N; +uniform float posUnpack; +uniform float time; +uniform float myParam; + +out vec3 mpos; +out vec3 normal; + +void main() { + vec4 p = vec4(pos.xyz, 1.0); + + // Position data is packed into (-1, 1) range + // Retrieve model position + mpos = pos.xyz * posUnpack; + + // Unpack normal.z component from pos.w + normal = N * vec3(nor.xy, pos.w); + + p.z += sin((time + mpos.x + mpos.y) * 2.0) * 0.2 * myParam; + gl_Position = WVP * p; +} diff --git a/material_shaders/Sources/lnx/MyTrait.hx b/material_shaders/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..6675efb --- /dev/null +++ b/material_shaders/Sources/lnx/MyTrait.hx @@ -0,0 +1,26 @@ +package lnx; + +import iron.Scene; +import iron.math.Vec4; +import iron.data.MaterialData; +import iron.object.MeshObject; +import iron.object.Object; +import iron.object.Uniforms; + +class MyTrait extends iron.Trait { + + public function new() { + super(); + notifyOnInit(() -> { + Uniforms.externalFloatLinks.push(floatLink); + }); + } + + function floatLink(object:Object, mat:MaterialData, link:String):Null { + if (link == "myParam") { + var mouse = iron.system.Input.getMouse(); + return (iron.App.h() - mouse.y) / 100; + } + return null; + } +} diff --git a/material_shaders/material_shaders.blend b/material_shaders/material_shaders.blend new file mode 100644 index 0000000..eaa859b Binary files /dev/null and b/material_shaders/material_shaders.blend differ diff --git a/material_sss/material_sss.blend b/material_sss/material_sss.blend new file mode 100644 index 0000000..9950090 Binary files /dev/null and b/material_sss/material_sss.blend differ diff --git a/material_translucent/circle.png b/material_translucent/circle.png new file mode 100644 index 0000000..18daedb Binary files /dev/null and b/material_translucent/circle.png differ diff --git a/material_translucent/material_translucent.blend b/material_translucent/material_translucent.blend new file mode 100644 index 0000000..2529ab1 Binary files /dev/null and b/material_translucent/material_translucent.blend differ diff --git a/material_video/README.md b/material_video/README.md new file mode 100644 index 0000000..67d6b4e --- /dev/null +++ b/material_video/README.md @@ -0,0 +1,7 @@ +- Krom is not yet supported, please use HTML5 or native targets for now. +- ffmpeg is required to process video files. + +1. Install [ffmpeg](https://ffmpeg.org) +2. Point `Edit - Preferences… - Add-ons - Leenkx - Advanced - FFMPEG Path` to ffmpeg binary +3. Play +4. During the first build, video processing may take some time diff --git a/material_video/material_video.blend b/material_video/material_video.blend new file mode 100644 index 0000000..67587ed Binary files /dev/null and b/material_video/material_video.blend differ diff --git a/material_video/video.mp4 b/material_video/video.mp4 new file mode 100644 index 0000000..81d11df Binary files /dev/null and b/material_video/video.mp4 differ diff --git a/mesh_generate/README.md b/mesh_generate/README.md new file mode 100644 index 0000000..f25183b --- /dev/null +++ b/mesh_generate/README.md @@ -0,0 +1,5 @@ +https://github.com/leenkx3d/leenkx/wiki/generate_mesh + +#### Keyboard +- `Up`, `W` Add cubes +- `Down`, `S` Remove cubes diff --git a/mesh_generate/Sources/lnx/BoxGenerator.hx b/mesh_generate/Sources/lnx/BoxGenerator.hx new file mode 100644 index 0000000..c078a1a --- /dev/null +++ b/mesh_generate/Sources/lnx/BoxGenerator.hx @@ -0,0 +1,128 @@ +package lnx; + +import iron.data.Data; +import iron.data.MaterialData; +import iron.data.MeshData; +import iron.data.SceneFormat; +import iron.object.MeshObject; +import iron.Scene; +import iron.system.Input; +import kha.arrays.Int16Array; +import kha.arrays.Uint32Array; + +class BoxGenerator extends iron.Trait { + + var meshData:MeshData; + var materials:haxe.ds.Vector; + var cubes = new Array(); + var font : kha.Font; + + function toI16(toPos:Int16Array, toNor:Int16Array, fromPos:Array, fromNor:Array) { + var numVertices = Std.int(fromPos.length / 3); + for (i in 0...numVertices) { + // Values are scaled to the signed short (-32768, 32767) range + // In the shader, vertex data is normalized into (-1, 1) range + toPos[i * 4 ] = Std.int(fromPos[i * 3 ] * 32767); + toPos[i * 4 + 1] = Std.int(fromPos[i * 3 + 1] * 32767); + toPos[i * 4 + 2] = Std.int(fromPos[i * 3 + 2] * 32767); + toNor[i * 2 ] = Std.int(fromNor[i * 3 ] * 32767); + toNor[i * 2 + 1] = Std.int(fromNor[i * 3 + 1] * 32767); + // normal.z component is packed into position.w component + toPos[i * 4 + 3] = Std.int(fromNor[i * 3 + 2] * 32767); + } + } + + function toU32(to:Uint32Array, from:Array) { + for (i in 0...to.length) to[i] = from[i]; + } + + public function new() { + super(); + + + // Raw vertex data for our box + var positions = [1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,1.0,1.0,-1.0,1.0,1.0,-1.0,-1.0,1.0,1.0,-1.0,1.0,1.0,1.0,-1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,1.0,-1.0,1.0,-1.0,1.0,1.0,1.0,1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,1.0]; + var normals = [0.0,0.0,-1.0,0.0,0.0,-1.0,0.0,0.0,-1.0,0.0,0.0,-1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,0.0,-1.0,-0.0,0.0,-1.0,-0.0,0.0,-1.0,-0.0,0.0,-1.0,-0.0,-1.0,0.0,-0.0,-1.0,0.0,-0.0,-1.0,0.0,-0.0,-1.0,0.0,-0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0]; + var indices = [0,1,2,0,2,3,4,5,6,4,6,7,8,9,10,8,10,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23]; + var numVertices = Std.int(positions.length / 3); + + // Leenkx uses packed 16-bit normalized vertex data to preserve memory + // To prevent padding and ensure 32-bit align, + // normal.z component is packed into position.w component + var posI16 = new Int16Array(numVertices * 4); // pos.xyz, nor.z + var norI16 = new Int16Array(numVertices * 2); // nor.xy + toI16(posI16, norI16, positions, normals); + + var indU32 = new Uint32Array(indices.length); + toU32(indU32, indices); + + var pos:TVertexArray = { attrib: "pos", values: posI16, data: "short4norm" }; + var nor:TVertexArray = { attrib: "nor", values: norI16, data: "short2norm" }; + var ind:TIndexArray = { material: 0, values: indU32 }; + + var rawmeshData:TMeshData = { + name: "BoxMesh", + vertex_arrays: [pos, nor], + index_arrays: [ind], + // Usable to scale positions over the (-1, 1) range + scale_pos: 0.5 + }; + + new MeshData(rawmeshData, function(data:MeshData) { + // Mesh data parsed + meshData = data; + meshData.geom.calculateAABB(); + + // Fetch material from scene data + Data.getMaterial("Scene", "Material", function(data:MaterialData) { + // Material loaded + materials = haxe.ds.Vector.fromData([data]); + notifyOnUpdate(update); + }); + }); + + Data.getFont('font_default.ttf', f -> { + font = f; + notifyOnRender2D( render2D ); + }); + } + + function update() { + // Left mouse button was pressed / display touched + final keyboard = Input.getKeyboard(); + final mouse = Input.getMouse(); + //if (mouse.down('left')) { + if (keyboard.down('up') || keyboard.down('w') || mouse.down('left')) { + final aabb = meshData.geom.aabb; + for( i in 0...10) { + // Create new object in active scene + final object = Scene.active.addMeshObject(meshData, materials); + + // Just for testing, add rigid body trait + object.transform.loc.set(Math.random() * 8- 4, Math.random() * 8 - 4, 5); + object.transform.buildMatrix(); + object.transform.dim.set(aabb.x, aabb.y, aabb.z); + object.addTrait(new leenkx.trait.physics.RigidBody()); + cubes.push(object); + } + trace(cubes.length); + } else if (keyboard.down('down') || keyboard.down('s') || mouse.down('right')) { + for( i in 0...10) { + if( cubes.length == 0 ) break; + cubes.shift().remove(); + } + trace(cubes.length); + } + } + + function render2D( g : kha.graphics2.Graphics ) { + g.end(); + g.font = font; + final fontSize = 13; + final text = 'CUBES: '+cubes.length; + final w = font.width( g.fontSize, text ); + g.fontSize = 13; + g.drawString( text, 10, 10 ); + g.begin( false ); + } +} diff --git a/mesh_generate/mesh_generate.blend b/mesh_generate/mesh_generate.blend new file mode 100644 index 0000000..8fd8980 Binary files /dev/null and b/mesh_generate/mesh_generate.blend differ diff --git a/mesh_geometry/mesh_geometry.blend b/mesh_geometry/mesh_geometry.blend new file mode 100644 index 0000000..b432a9a Binary files /dev/null and b/mesh_geometry/mesh_geometry.blend differ diff --git a/mesh_import/Bundled/cube.obj b/mesh_import/Bundled/cube.obj new file mode 100644 index 0000000..b037316 --- /dev/null +++ b/mesh_import/Bundled/cube.obj @@ -0,0 +1,44 @@ +# Blender v2.80 (sub 41) OBJ File: '' +# www.blender.org +o Cube +v 1.000000 1.000000 -1.000000 +v 1.000000 -1.000000 -1.000000 +v 1.000000 1.000000 1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +v -1.000000 -1.000000 -1.000000 +v -1.000000 1.000000 1.000000 +v -1.000000 -1.000000 1.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.750000 +vt 0.125000 0.750000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +s off +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/6/2 7/7/2 8/8/2 +f 8/8/3 7/7/3 5/9/3 6/10/3 +f 6/10/4 2/11/4 4/12/4 8/13/4 +f 2/14/5 1/15/5 3/16/5 4/17/5 +f 6/18/6 5/19/6 1/20/6 2/11/6 diff --git a/mesh_import/Sources/lnx/ImportMesh.hx b/mesh_import/Sources/lnx/ImportMesh.hx new file mode 100644 index 0000000..b3911bb --- /dev/null +++ b/mesh_import/Sources/lnx/ImportMesh.hx @@ -0,0 +1,67 @@ +package lnx; + +import iron.Scene; +import iron.data.SceneFormat; +import iron.data.Data; +import iron.data.MeshData; +import iron.data.MaterialData; +import iron.system.Input; + +class ImportMesh extends iron.Trait { + + var meshData:MeshData; + var materials:haxe.ds.Vector; + + public function new() { + super(); + + // Get raw blob + Data.getBlob("cube.obj", function(blob:kha.Blob) { + + // Parse obj file + var mesh = new ObjParser(blob); + + // Positions, normals and indices + var pos:TVertexArray = { attrib: "pos", values: mesh.posa, data: "short4norm" }; + var nor:TVertexArray = { attrib: "nor", values: mesh.nora, data: "short2norm" }; + var ind:TIndexArray = { material: 0, values: mesh.inda }; + + var rawmeshData:TMeshData = { + name: "BoxMesh", + vertex_arrays: [pos, nor], + index_arrays: [ind], + // Usable to scale positions over the (-1, 1) range + scale_pos: mesh.scalePos + }; + + // Construct new mesh + new MeshData(rawmeshData, function(data:MeshData) { + meshData = data; + meshData.geom.calculateAABB(); + + // Fetch material from scene data + Data.getMaterial("Scene", "Material", function(data:MaterialData) { + // Material loaded + materials = haxe.ds.Vector.fromData([data]); + notifyOnUpdate(update); + }); + }); + }); + } + + function update() { + // Left mouse button was pressed / display touched + var mouse = Input.getMouse(); + if (mouse.down()) { + // Create new object in active scene + var object = Scene.active.addMeshObject(meshData, materials); + + // Just for testing, add rigid body trait + var aabb = meshData.geom.aabb; + object.transform.loc.set(Math.random() * 8 - 4, Math.random() * 8 - 4, 5); + object.transform.buildMatrix(); + object.transform.dim.set(aabb.x, aabb.y, aabb.z); + object.addTrait(new leenkx.trait.physics.RigidBody()); + } + } +} diff --git a/mesh_import/Sources/lnx/ObjParser.hx b/mesh_import/Sources/lnx/ObjParser.hx new file mode 100644 index 0000000..b77b522 --- /dev/null +++ b/mesh_import/Sources/lnx/ObjParser.hx @@ -0,0 +1,395 @@ +package lnx; + +class ObjParser { + + public static var splitCode = "o".code; // Object split, "g" for groups, "u"semtl for materials + public var posa: kha.arrays.Int16Array = null; + public var nora: kha.arrays.Int16Array = null; + public var texa: kha.arrays.Int16Array = null; + public var inda: kha.arrays.Uint32Array = null; + public var udims: Array = null; // Indices split per udim tile + public var udimsU = 1; // Number of horizontal udim tiles + public var scalePos = 1.0; + public var scaleTex = 1.0; + public var name = ""; + public var hasNext = false; // File contains multiple objects + public var pos = 0; + var posTemp: Array; + var uvTemp: Array; + var norTemp: Array; + var va: kha.arrays.Uint32Array; + var ua: kha.arrays.Uint32Array; + var na: kha.arrays.Uint32Array; + var vi = 0; + var ui = 0; + var ni = 0; + var buf: haxe.io.UInt8Array = null; + + static var vindOff = 0; + static var tindOff = 0; + static var nindOff = 0; + static var bytes: haxe.io.Bytes = null; + static var posFirst: Array; + static var uvFirst: Array; + static var norFirst: Array; + + public function new(blob: kha.Blob, startPos = 0, udim = false) { + pos = startPos; + var posIndices: Array = []; + var uvIndices: Array = []; + var norIndices: Array = []; + var readingFaces = false; + var readingObject = false; + var fullAttrib = false; + bytes = blob.bytes; + + posTemp = []; + uvTemp = []; + norTemp = []; + va = new kha.arrays.Uint32Array(60); + ua = new kha.arrays.Uint32Array(60); + na = new kha.arrays.Uint32Array(60); + buf = new haxe.io.UInt8Array(64); + + if (splitCode == "u".code && startPos > 0) { + posTemp = posFirst; + norTemp = norFirst; + uvTemp = uvFirst; + } + + while (true) { + if (pos >= bytes.length) break; + + var c0 = bytes.get(pos++); + if (readingObject && readingFaces && (c0 == "v".code || c0 == splitCode)) { + pos--; + hasNext = true; + break; + } + + if (c0 == "v".code) { + var c1 = bytes.get(pos++); + if (c1 == " ".code) { + // Some exporters put additional space directly after "v" + if (bytes.get(pos) == " ".code) pos++; + posTemp.push(readFloat()); + pos++; // Space + posTemp.push(readFloat()); + pos++; // Space + posTemp.push(readFloat()); + } + else if (c1 == "t".code) { + pos++; // Space + uvTemp.push(readFloat()); + pos++; // Space + uvTemp.push(readFloat()); + if (norTemp.length > 0) fullAttrib = true; + } + else if (c1 == "n".code) { + pos++; // Space + norTemp.push(readFloat()); + pos++; // Space + norTemp.push(readFloat()); + pos++; // Space + norTemp.push(readFloat()); + if (uvTemp.length > 0) fullAttrib = true; + } + } + else if (c0 == "f".code) { + pos++; // Space + readingFaces = true; + vi = 0; + ui = 0; + ni = 0; + fullAttrib ? readFaceFast() : readFace(); + + posIndices.push(va[0]); + posIndices.push(va[1]); + posIndices.push(va[2]); + for (i in 3...vi) { + posIndices.push(va[0]); + posIndices.push(va[i - 1]); + posIndices.push(va[i]); + } + if (uvTemp.length > 0) { + uvIndices.push(ua[0]); + uvIndices.push(ua[1]); + uvIndices.push(ua[2]); + for (i in 3...ui) { + uvIndices.push(ua[0]); + uvIndices.push(ua[i - 1]); + uvIndices.push(ua[i]); + } + } + if (norTemp.length > 0) { + norIndices.push(na[0]); + norIndices.push(na[1]); + norIndices.push(na[2]); + for (i in 3...ni) { + norIndices.push(na[0]); + norIndices.push(na[i - 1]); + norIndices.push(na[i]); + } + } + } + else if (c0 == splitCode) { + if (splitCode == "u".code) pos += 5; // "u"semtl + pos++; // Space + if (!udim) readingObject = true; + name = readString(); + } + nextLine(); + } + + if (startPos > 0) { + if (splitCode != "u".code) { + for (i in 0...posIndices.length) posIndices[i] -= vindOff; + for (i in 0...uvIndices.length) uvIndices[i] -= tindOff; + for (i in 0...norIndices.length) norIndices[i] -= nindOff; + } + } + else { + vindOff = tindOff = nindOff = 0; + + if (splitCode == "u".code) { + posFirst = posTemp; + norFirst = norTemp; + uvFirst = uvTemp; + } + } + vindOff += Std.int(posTemp.length / 3); // Assumes separate vertex data per object + tindOff += Std.int(uvTemp.length / 2); + nindOff += Std.int(norTemp.length / 3); + + // Pack positions to (-1, 1) range + scalePos = 0.0; + for (i in 0...posTemp.length) { + var f = Math.abs(posTemp[i]); + if (scalePos < f) scalePos = f; + } + var inv = 32767 * (1 / scalePos); + + posa = new kha.arrays.Int16Array(posIndices.length * 4); + inda = new kha.arrays.Uint32Array(posIndices.length); + for (i in 0...posIndices.length) { + posa[i * 4 ] = Std.int( posTemp[posIndices[i] * 3 ] * inv); + posa[i * 4 + 1] = Std.int(-posTemp[posIndices[i] * 3 + 2] * inv); + posa[i * 4 + 2] = Std.int( posTemp[posIndices[i] * 3 + 1] * inv); + inda[i] = i; + } + + if (norIndices.length > 0) { + nora = new kha.arrays.Int16Array(norIndices.length * 2); + for (i in 0...posIndices.length) { + nora[i * 2 ] = Std.int( norTemp[norIndices[i] * 3 ] * 32767); + nora[i * 2 + 1] = Std.int(-norTemp[norIndices[i] * 3 + 2] * 32767); + posa[i * 4 + 3] = Std.int( norTemp[norIndices[i] * 3 + 1] * 32767); + } + } + else { + // Calc normals + nora = new kha.arrays.Int16Array(inda.length * 2); + var va = new iron.math.Vec4(); + var vb = new iron.math.Vec4(); + var vc = new iron.math.Vec4(); + var cb = new iron.math.Vec4(); + var ab = new iron.math.Vec4(); + for (i in 0...Std.int(inda.length / 3)) { + var i1 = inda[i * 3 ]; + var i2 = inda[i * 3 + 1]; + var i3 = inda[i * 3 + 2]; + va.set(posa[i1 * 4], posa[i1 * 4 + 1], posa[i1 * 4 + 2]); + vb.set(posa[i2 * 4], posa[i2 * 4 + 1], posa[i2 * 4 + 2]); + vc.set(posa[i3 * 4], posa[i3 * 4 + 1], posa[i3 * 4 + 2]); + cb.subvecs(vc, vb); + ab.subvecs(va, vb); + cb.cross(ab); + cb.normalize(); + nora[i1 * 2 ] = Std.int(cb.x * 32767); + nora[i1 * 2 + 1] = Std.int(cb.y * 32767); + posa[i1 * 4 + 3] = Std.int(cb.z * 32767); + nora[i2 * 2 ] = Std.int(cb.x * 32767); + nora[i2 * 2 + 1] = Std.int(cb.y * 32767); + posa[i2 * 4 + 3] = Std.int(cb.z * 32767); + nora[i3 * 2 ] = Std.int(cb.x * 32767); + nora[i3 * 2 + 1] = Std.int(cb.y * 32767); + posa[i3 * 4 + 3] = Std.int(cb.z * 32767); + } + } + + if (uvIndices.length > 0) { + if (udim) { + // Find number of tiles + var tilesU = 1; + var tilesV = 1; + for (i in 0...Std.int(uvTemp.length / 2)) { + while (uvTemp[i * 2 ] > tilesU) tilesU++; + while (uvTemp[i * 2 + 1] > tilesV) tilesV++; + } + + function getTile(i1: Int, i2: Int, i3: Int): Int { + var u1 = uvTemp[uvIndices[i1] * 2 ]; + var v1 = uvTemp[uvIndices[i1] * 2 + 1]; + var u2 = uvTemp[uvIndices[i2] * 2 ]; + var v2 = uvTemp[uvIndices[i2] * 2 + 1]; + var u3 = uvTemp[uvIndices[i3] * 2 ]; + var v3 = uvTemp[uvIndices[i3] * 2 + 1]; + var tileU = Std.int((u1 + u2 + u3) / 3); + var tileV = Std.int((v1 + v2 + v3) / 3); + return tileU + tileV * tilesU; + } + + // Amount of indices pre tile + var num = new kha.arrays.Uint32Array(tilesU * tilesV); + for (i in 0...Std.int(inda.length / 3)) { + var tile = getTile(inda[i * 3], inda[i * 3 + 1], inda[i * 3 + 2]); + num[tile] += 3; + } + + // Split indices per tile + udims = []; + udimsU = tilesU; + for (i in 0...tilesU * tilesV) { udims.push(new kha.arrays.Uint32Array(num[i])); num[i] = 0; } + + for (i in 0...Std.int(inda.length / 3)) { + var i1 = inda[i * 3 ]; + var i2 = inda[i * 3 + 1]; + var i3 = inda[i * 3 + 2]; + var tile = getTile(i1, i2, i3); + udims[tile][num[tile]++] = i1; + udims[tile][num[tile]++] = i2; + udims[tile][num[tile]++] = i3; + } + + // Normalize uvs to 0-1 range + var uvtiles = new kha.arrays.Int16Array(uvTemp.length); + for (i in 0...Std.int(inda.length / 3)) { // TODO: merge loops + var i1 = inda[i * 3 ]; + var i2 = inda[i * 3 + 1]; + var i3 = inda[i * 3 + 2]; + var tile = getTile(i1, i2, i3); + var tileU = tile % tilesU; + var tileV = Std.int(tile / tilesU); + uvtiles[uvIndices[i1] * 2 ] = tileU; + uvtiles[uvIndices[i1] * 2 + 1] = tileV; + uvtiles[uvIndices[i2] * 2 ] = tileU; + uvtiles[uvIndices[i2] * 2 + 1] = tileV; + uvtiles[uvIndices[i3] * 2 ] = tileU; + uvtiles[uvIndices[i3] * 2 + 1] = tileV; + } + for (i in 0...uvtiles.length) uvTemp[i] -= uvtiles[i]; + } + + texa = new kha.arrays.Int16Array(uvIndices.length * 2); + for (i in 0...posIndices.length) { + texa[i * 2 ] = Std.int( uvTemp[uvIndices[i] * 2 ] * 32767); + texa[i * 2 + 1] = Std.int((1.0 - uvTemp[uvIndices[i] * 2 + 1]) * 32767); + } + } + bytes = null; + if (!hasNext) { posFirst = norFirst = uvFirst = null; } + } + + function readFaceFast() { + while (true) { + va[vi++] = readInt() - 1; + pos++; // "/" + ua[ui++] = readInt() - 1; + pos++; // "/" + na[ni++] = readInt() - 1; + if (bytes.get(pos) == "\n".code || bytes.get(pos) == "\r".code) break; + pos++; // " " + // Some exporters put space at the end of "f" line + if (vi >= 3 && (bytes.get(pos) == "\n".code || bytes.get(pos) == "\r".code)) break; + } + } + + function readFace() { + while (true) { + va[vi++] = readInt() - 1; + if (uvTemp.length > 0 || norTemp.length > 0) { + pos++; // "/" + } + if (uvTemp.length > 0) { + ua[ui++] = readInt() - 1; + } + if (norTemp.length > 0) { + pos++; // "/" + na[ni++] = readInt() - 1; + } + if (bytes.get(pos) == "\n".code || bytes.get(pos) == "\r".code) break; + pos++; // " " + // Some exporters put space at the end of "f" line + if (vi >= 3 && (bytes.get(pos) == "\n".code || bytes.get(pos) == "\r".code)) break; + } + } + + function readFloat(): Float { + var bi = 0; + while (true) { // Read into buffer + var c = bytes.get(pos); + if (c == " ".code || c == "\n".code || c == "\r".code) break; + if (c == "E".code || c == "e".code) { + while (true) { + pos++; + c = bytes.get(pos); + if (c == " ".code || c == "\n".code || c == "\r".code) break; + } + return 0.0; // Assume number close to zero for now + } + pos++; + buf[bi++] = c; + } + var res = 0.0; // Parse buffer into float + var dot = 1; + var dec = 1; + var off = buf[0] == "-".code ? 1 : 0; + var len = bi - 1; + for (i in 0...bi - off) { + var c = buf[len - i]; + if (c == ".".code) { dot = dec; continue; } + res += (c - 48) * dec; + dec *= 10; + } + off > 0 ? res /= -dot : res /= dot; + return res; + } + + function readInt(): Int { + var bi = 0; + while (true) { // Read into buffer + var c = bytes.get(pos); + if (c == "/".code || c == "\n".code || c == "\r".code || c == " ".code) break; + pos++; + buf[bi++] = c; + } + var res = 0; // Parse buffer into int + var dec = 1; + var off = buf[0] == "-".code ? 1 : 0; + var len = bi - 1; + for (i in 0...bi - off) { + res += (buf[len - i] - 48) * dec; + dec *= 10; + } + if (off > 0) res *= -1; + return res; + } + + function readString(): String { + var s = ""; + while (true) { + var c = bytes.get(pos); + if (c == "\n".code || c == "\r".code || c == " ".code) break; + pos++; + s += String.fromCharCode(c); + } + return s; + } + + function nextLine() { + while (true) { + var c = bytes.get(pos++); + if (c == "\n".code || pos >= bytes.length) break; // \n, \r\n + } + } +} diff --git a/mesh_import/mesh_import.blend b/mesh_import/mesh_import.blend new file mode 100644 index 0000000..b589c4b Binary files /dev/null and b/mesh_import/mesh_import.blend differ diff --git a/mesh_terrain/Bundled/heightmap_01.png b/mesh_terrain/Bundled/heightmap_01.png new file mode 100644 index 0000000..51a4d3b Binary files /dev/null and b/mesh_terrain/Bundled/heightmap_01.png differ diff --git a/mesh_terrain/README.md b/mesh_terrain/README.md new file mode 100644 index 0000000..1f281f3 --- /dev/null +++ b/mesh_terrain/README.md @@ -0,0 +1,10 @@ +To generate terrain: + +- Place your heightmap as `Bundled/heightmap_01.png` +- Navigate to `Properties - Scene - Leenkx Terrain` +- Set terrain dimensions using `Sector Size` +- Set terrain height using `Height Scale` +- Click `Generate` +- Adjust terrain material + +See diff --git a/mesh_terrain/base.png b/mesh_terrain/base.png new file mode 100644 index 0000000..fc6cbe4 Binary files /dev/null and b/mesh_terrain/base.png differ diff --git a/mesh_terrain/mesh_terrain.blend b/mesh_terrain/mesh_terrain.blend new file mode 100644 index 0000000..a4bb6d3 Binary files /dev/null and b/mesh_terrain/mesh_terrain.blend differ diff --git a/navmesh/README.md b/navmesh/README.md new file mode 100644 index 0000000..4ac1b2f --- /dev/null +++ b/navmesh/README.md @@ -0,0 +1,5 @@ +- https://github.com/leenkx3d/leenkx/wiki/navmesh +--- +- https://api.leenkx3d.org/leenkx/trait/NavMesh.html +- https://api.leenkx3d.org/leenkx/trait/NavAgent.html +- https://api.leenkx3d.org/leenkx/trait/NavCrowd.html diff --git a/navmesh/gridbox.png b/navmesh/gridbox.png new file mode 100644 index 0000000..20f90f4 Binary files /dev/null and b/navmesh/gridbox.png differ diff --git a/navmesh/gridbox2.png b/navmesh/gridbox2.png new file mode 100644 index 0000000..398526b Binary files /dev/null and b/navmesh/gridbox2.png differ diff --git a/navmesh/navmesh.blend b/navmesh/navmesh.blend new file mode 100644 index 0000000..0e1c1ed Binary files /dev/null and b/navmesh/navmesh.blend differ diff --git a/navmesh_follow/README.md b/navmesh_follow/README.md new file mode 100644 index 0000000..ef5e38a --- /dev/null +++ b/navmesh_follow/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/navmesh diff --git a/navmesh_follow/navmesh_follow.blend b/navmesh_follow/navmesh_follow.blend new file mode 100644 index 0000000..f044e0a Binary files /dev/null and b/navmesh_follow/navmesh_follow.blend differ diff --git a/network_zui_chat/Bundled/canvas/MainCanvas.files b/network_zui_chat/Bundled/canvas/MainCanvas.files new file mode 100644 index 0000000..e69de29 diff --git a/network_zui_chat/Bundled/canvas/MainCanvas.json b/network_zui_chat/Bundled/canvas/MainCanvas.json new file mode 100644 index 0000000..692992c --- /dev/null +++ b/network_zui_chat/Bundled/canvas/MainCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":1280,"height":720,"theme":"Default Light","elements":[{"id":4,"type":12,"name":"chatBackground","event":"","x":0,"y":-160,"width":420,"height":60,"rotation":0,"text":"","asset":"","progress_at":0,"progress_total":100,"strength":1,"alignment":0,"anchor":4,"parent":null,"children":[],"visible":true,"color":-14145496},{"id":0,"type":0,"name":"chatStatus","event":"","x":-20,"y":-220,"width":420,"height":30,"rotation":0,"text":"CHAT: Disconnected","asset":"","progress_at":0,"progress_total":100,"strength":1,"alignment":0,"anchor":4,"parent":null,"children":[],"visible":true,"color_text":null},{"id":1,"type":0,"name":"chatMsg","event":"","x":0,"y":-180,"width":420,"height":20,"rotation":0,"text":"...","asset":"","progress_at":0,"progress_total":100,"strength":1,"alignment":0,"anchor":4,"parent":null,"children":[],"visible":true,"color_text":null},{"id":2,"type":2,"name":"chatSend","event":"","x":160,"y":-100,"width":104,"height":44,"rotation":0,"text":"SEND","asset":"","progress_at":0,"progress_total":100,"strength":1,"alignment":1,"anchor":4,"parent":null,"children":[],"visible":true,"color_text":null,"color":null,"color_hover":null,"color_press":null},{"id":3,"type":10,"name":"chatInput","event":"","x":-60,"y":-100,"width":300,"height":48,"rotation":0,"text":"","asset":"","progress_at":0,"progress_total":100,"strength":1,"alignment":0,"anchor":4,"parent":null,"children":[],"visible":true,"color_text":null,"color":null,"color_hover":null}],"assets":[]} \ No newline at end of file diff --git a/network_zui_chat/Bundled/canvas/_themes.json b/network_zui_chat/Bundled/canvas/_themes.json new file mode 100644 index 0000000..27123b6 --- /dev/null +++ b/network_zui_chat/Bundled/canvas/_themes.json @@ -0,0 +1 @@ +[{"NAME":"Default Light","WINDOW_BG_COL":-1052689,"WINDOW_TINT_COL":-14540254,"ACCENT_COL":-1118482,"ACCENT_HOVER_COL":-4473925,"ACCENT_SELECT_COL":-5592406,"BUTTON_COL":-3355444,"BUTTON_TEXT_COL":-14540254,"BUTTON_HOVER_COL":-5000269,"BUTTON_PRESSED_COL":-5131855,"TEXT_COL":-6710887,"LABEL_COL":-5592406,"SEPARATOR_COL":-6710887,"HIGHLIGHT_COL":-14656100,"CONTEXT_COL":-5592406,"PANEL_BG_COL":-5592406,"FONT_SIZE":26,"ELEMENT_W":200,"ELEMENT_H":48,"ELEMENT_OFFSET":8,"ARROW_SIZE":10,"BUTTON_H":44,"CHECK_SIZE":30,"CHECK_SELECT_SIZE":16,"SCROLL_W":12,"TEXT_OFFSET":16,"TAB_W":24,"FILL_WINDOW_BG":false,"FILL_BUTTON_BG":true,"FILL_ACCENT_BG":false,"LINK_STYLE":0,"FULL_TABS":false}] \ No newline at end of file diff --git a/network_zui_chat/README.md b/network_zui_chat/README.md new file mode 100644 index 0000000..1f59632 --- /dev/null +++ b/network_zui_chat/README.md @@ -0,0 +1,21 @@ +Simple Network Zui Chat Example: + +- Red nodes are for system host targets +- Teal nodes are for system and html browser client targets + +** If you plan on using 3rd party server / client configuration please keep in mind our nodes use bytes and buffers even for regular strings + +** Once a buffer is read it is not accessible any more, meaning if a msg parser node matches the same API field the buffer will be read and converted back into its data type + +** Both host nodes and client nodes are allowed on the same node tree however browser html targets are not capable of being hosts. A browser cannot create/listen to TCP/UDP ports) so any host related nodes will be ignored when targeting html browsers + +** System server *targets (like hashlink C for desktop/mobile) are intended to basically turn your desktop/mobile device into a server to which you can connect to with either another client instance on desktop/mobile or with a browser instance only as a client. + +``` +C targets = host / client +Browser = only client +Krom = N/A (for now) +``` + +Introduction to Networking in Leenkx 3D | Overview of all nodes +https://www.youtube.com/watch?t=135&v=ZmaG_JFmn0Q&feature=youtu.be diff --git a/network_zui_chat/network_zui_chat.blend b/network_zui_chat/network_zui_chat.blend new file mode 100644 index 0000000..2fc458b Binary files /dev/null and b/network_zui_chat/network_zui_chat.blend differ diff --git a/particle_bunny/bunny.png b/particle_bunny/bunny.png new file mode 100644 index 0000000..f74994e Binary files /dev/null and b/particle_bunny/bunny.png differ diff --git a/particle_bunny/particle_bunny.blend b/particle_bunny/particle_bunny.blend new file mode 100644 index 0000000..17332c3 Binary files /dev/null and b/particle_bunny/particle_bunny.blend differ diff --git a/particle_hair/particle_hair.blend b/particle_hair/particle_hair.blend new file mode 100644 index 0000000..46865a4 Binary files /dev/null and b/particle_hair/particle_hair.blend differ diff --git a/particle_hair_animated/README.md b/particle_hair_animated/README.md new file mode 100644 index 0000000..234292b --- /dev/null +++ b/particle_hair_animated/README.md @@ -0,0 +1,10 @@ +You can watch the video explaining this set up here: +https://youtu.be/6HqsRFteGKo + + +The particule Number is set to 100 but it +is multiplied by 5 in the Leenkx Props setion +of the particlue system (right at the bottom) + +Textures are CC0: +https://opengameart.org/content/foliage1 diff --git a/particle_hair_animated/particle_hair_animated.blend b/particle_hair_animated/particle_hair_animated.blend new file mode 100644 index 0000000..1d2c4a4 Binary files /dev/null and b/particle_hair_animated/particle_hair_animated.blend differ diff --git a/particle_info/part.png b/particle_info/part.png new file mode 100644 index 0000000..6d6873f Binary files /dev/null and b/particle_info/part.png differ diff --git a/particle_info/particle_info.blend b/particle_info/particle_info.blend new file mode 100644 index 0000000..618b402 Binary files /dev/null and b/particle_info/particle_info.blend differ diff --git a/particle_mesh/README.md b/particle_mesh/README.md new file mode 100644 index 0000000..b75b1ad --- /dev/null +++ b/particle_mesh/README.md @@ -0,0 +1,5 @@ +https://github.com/leenkx3d/leenkx/wiki/supported_particles + +#### Keyboard +- `1` Particle speed = 1 +- `2` Particle speed = 0 diff --git a/particle_mesh/particle_mesh.blend b/particle_mesh/particle_mesh.blend new file mode 100644 index 0000000..d2362fa Binary files /dev/null and b/particle_mesh/particle_mesh.blend differ diff --git a/particle_smoke/particle_smoke.blend b/particle_smoke/particle_smoke.blend new file mode 100644 index 0000000..42479a5 Binary files /dev/null and b/particle_smoke/particle_smoke.blend differ diff --git a/particle_smoke/smoke.jpg b/particle_smoke/smoke.jpg new file mode 100644 index 0000000..8f9afbb Binary files /dev/null and b/particle_smoke/smoke.jpg differ diff --git a/physics_break/physics_break.blend b/physics_break/physics_break.blend new file mode 100644 index 0000000..2f6a146 Binary files /dev/null and b/physics_break/physics_break.blend differ diff --git a/physics_collision_groups/physics_collision_groups.blend b/physics_collision_groups/physics_collision_groups.blend new file mode 100644 index 0000000..f287d94 Binary files /dev/null and b/physics_collision_groups/physics_collision_groups.blend differ diff --git a/physics_constraints/README.md b/physics_constraints/README.md new file mode 100644 index 0000000..f2c1ed1 --- /dev/null +++ b/physics_constraints/README.md @@ -0,0 +1,2 @@ +- https://github.com/leenkx3d/leenkx/wiki/physics#rigid-body-constraints +- https://api.leenkx3d.org/leenkx/trait/physics/PhysicsConstraint.html diff --git a/physics_constraints/physics_constraints.blend b/physics_constraints/physics_constraints.blend new file mode 100644 index 0000000..958eb9c Binary files /dev/null and b/physics_constraints/physics_constraints.blend differ diff --git a/physics_drag/README.md b/physics_drag/README.md new file mode 100644 index 0000000..d941561 --- /dev/null +++ b/physics_drag/README.md @@ -0,0 +1 @@ +https://api.leenkx3d.org/leenkx/trait/PhysicsDrag.html diff --git a/physics_drag/physics_drag.blend b/physics_drag/physics_drag.blend new file mode 100644 index 0000000..e44ecb8 Binary files /dev/null and b/physics_drag/physics_drag.blend differ diff --git a/physics_pick/README.md b/physics_pick/README.md new file mode 100644 index 0000000..20301dd --- /dev/null +++ b/physics_pick/README.md @@ -0,0 +1,8 @@ +Example on physics-based picking. +Object to be picked is required to have rigid body enabled. +Click on a cube to make it jump. +Select Camera object, go to `Properties - Object - Leenkx Traits` and enable one of the traits you wish to test: +- PickTrait - using scripting +- PickEvent - using scripting with mouse event +- PickTree - using logic nodes + diff --git a/physics_pick/Sources/lnx/PickEvent.hx b/physics_pick/Sources/lnx/PickEvent.hx new file mode 100644 index 0000000..034aa6a --- /dev/null +++ b/physics_pick/Sources/lnx/PickEvent.hx @@ -0,0 +1,36 @@ +package lnx; + +import kha.input.Mouse; +import leenkx.trait.physics.PhysicsWorld; + +// Using mouse events +class PickEvent extends iron.Trait { + + public function new() { + super(); + + notifyOnInit(function() { + Mouse.get().notify(onMouseDown, onMouseUp, onMouseMove, onMouseWheel); + }); + + notifyOnRemove(function() { + // Trait or its object is removed, remove event listeners + Mouse.get().remove(onMouseDown, onMouseUp, onMouseMove, onMouseWheel); + }); + } + + function onMouseDown(button: Int, x: Int, y: Int) { + // Pick object at mouse coords + var rb = PhysicsWorld.active.pickClosest(x, y); + + // Check if picked object is our Cube + if (rb != null && rb.object.name == 'Cube') { + rb.object.transform.translate(0, 0, 1); + rb.syncTransform(); + } + } + + function onMouseUp(button: Int, x: Int, y: Int) { } + function onMouseMove(x: Int, y: Int, movementX: Int, movementY: Int) { } + function onMouseWheel(delta: Int) { } +} diff --git a/physics_pick/Sources/lnx/PickTrait.hx b/physics_pick/Sources/lnx/PickTrait.hx new file mode 100644 index 0000000..4bb7227 --- /dev/null +++ b/physics_pick/Sources/lnx/PickTrait.hx @@ -0,0 +1,26 @@ +package lnx; + +import iron.system.Input; +import leenkx.trait.physics.PhysicsWorld; + +class PickTrait extends iron.Trait { + + public function new() { + super(); + + notifyOnUpdate(function() { + // Check mouse button + var mouse = Input.getMouse(); + if (!mouse.started()) return; + + // Pick object at mouse coords + var rb = PhysicsWorld.active.pickClosest(mouse.x, mouse.y); + + // Check if picked object is our Cube + if (rb != null && rb.object.name == 'Cube') { + rb.object.transform.translate(0, 0, 1); + rb.syncTransform(); + } + }); + } +} diff --git a/physics_pick/physics_pick.blend b/physics_pick/physics_pick.blend new file mode 100644 index 0000000..6836ce9 Binary files /dev/null and b/physics_pick/physics_pick.blend differ diff --git a/physics_ragdoll/README.md b/physics_ragdoll/README.md new file mode 100644 index 0000000..3ce7aa6 --- /dev/null +++ b/physics_ragdoll/README.md @@ -0,0 +1,11 @@ +Drag ragdoll with mouse, legs and lnxs are destructible. + +### Building a ragdoll + +1. Build approx rig from hitboxes +2. Connect hitboxes using rigid body constraints +3. Clear bone parents +4. Attach bones to hitboxes using bone constraints - type 'Child Of'. +5. Press 'Clear Inverse' and 'Set Inverse' once target is set. + + diff --git a/physics_ragdoll/checker.png b/physics_ragdoll/checker.png new file mode 100644 index 0000000..75d30e0 Binary files /dev/null and b/physics_ragdoll/checker.png differ diff --git a/physics_ragdoll/checker_rough.png b/physics_ragdoll/checker_rough.png new file mode 100644 index 0000000..5fad6a5 Binary files /dev/null and b/physics_ragdoll/checker_rough.png differ diff --git a/physics_ragdoll/physics_ragdoll.blend b/physics_ragdoll/physics_ragdoll.blend new file mode 100644 index 0000000..2ca4617 Binary files /dev/null and b/physics_ragdoll/physics_ragdoll.blend differ diff --git a/physics_raycast/README.md b/physics_raycast/README.md new file mode 100644 index 0000000..022d7cd --- /dev/null +++ b/physics_raycast/README.md @@ -0,0 +1,4 @@ +- Keyboard `L/R` Rotate cone +- Mouse `L` Raycast in cone direction + +https://github.com/leenkx3d/leenkx/wiki/physics#raycast diff --git a/physics_raycast/Sources/lnx/RayCastTrait.hx b/physics_raycast/Sources/lnx/RayCastTrait.hx new file mode 100644 index 0000000..dd29f55 --- /dev/null +++ b/physics_raycast/Sources/lnx/RayCastTrait.hx @@ -0,0 +1,52 @@ +package lnx; + +import leenkx.trait.physics.PhysicsWorld; + +class RayCastTrait extends iron.Trait { + + var q = new iron.math.Quat(); + + public function new() { + super(); + + var mouse = iron.system.Input.getMouse(); + var keyboard = iron.system.Input.getKeyboard(); + + notifyOnUpdate(function() { + + if (mouse.down()) { + var physics = PhysicsWorld.active; + + // Start from cone location + var from = object.transform.world.getLoc(); + + // Cast ray in the direction cone points to + var to = object.transform.look(); + + // 1000 units long + to.mult(1000); + + // End position + to.add(from); + + var hit = physics.rayCast(from, to); + var rb = (hit != null) ? hit.rb : null; + var info = ''; + if( rb != null ) info += ' ${rb.object.name}'; + trace(info); + } + + if (keyboard.down("left")) { + q.fromEuler(0, 0, 0.1); + object.transform.rot.mult(q); + object.transform.buildMatrix(); + } + + if (keyboard.down("right")) { + q.fromEuler(0, 0, -0.1); + object.transform.rot.mult(q); + object.transform.buildMatrix(); + } + }); + } +} diff --git a/physics_raycast/physics_raycast.blend b/physics_raycast/physics_raycast.blend new file mode 100644 index 0000000..7d01b21 Binary files /dev/null and b/physics_raycast/physics_raycast.blend differ diff --git a/physics_softbody/README.md b/physics_softbody/README.md new file mode 100644 index 0000000..e5e7cfc --- /dev/null +++ b/physics_softbody/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/physics#soft-bodies diff --git a/physics_softbody/physics_softbody.blend b/physics_softbody/physics_softbody.blend new file mode 100644 index 0000000..7b3cd8a Binary files /dev/null and b/physics_softbody/physics_softbody.blend differ diff --git a/raycast_objects/Raycast_Objects.blend b/raycast_objects/Raycast_Objects.blend new file mode 100644 index 0000000..cbf2ace Binary files /dev/null and b/raycast_objects/Raycast_Objects.blend differ diff --git a/raycast_objects/Sources/lnx/MyTraitRaycastObjects.hx b/raycast_objects/Sources/lnx/MyTraitRaycastObjects.hx new file mode 100644 index 0000000..3872d46 --- /dev/null +++ b/raycast_objects/Sources/lnx/MyTraitRaycastObjects.hx @@ -0,0 +1,45 @@ +package lnx; + +import iron.system.Input; +import iron.math.Vec4; +import iron.math.RayCaster; +import iron.object.Object; +import iron.object.CameraObject; + +class MyTraitRaycastObjects extends iron.Trait { + + var v = new Vec4(); + var mouse = Input.getMouse(); + var objects: Array; + var o: Object; + + public function new() { + super(); + + notifyOnInit(function() { + + objects = [object, iron.Scene.active.getChild('Sphere'), iron.Scene.active.getChild('Suzanne')]; + + }); + + notifyOnUpdate(function() { + + + if(mouse.started('left')){ + v = RayCaster.boxIntersectObject(object, mouse.x, mouse.y, iron.Scene.active.camera); + if(v != null) + trace('Raycast object at position: '+v); + + o = RayCaster.closestBoxIntersectObject(objects, mouse.x, mouse.y, iron.Scene.active.camera); + if (o != null){ + v = RayCaster.boxIntersectObject(o, mouse.x, mouse.y, iron.Scene.active.camera); + trace('Raycast object: '+o.name+' at position: '+v); + } + } + + }); + + // notifyOnRemove(function() { + // }); + } +} diff --git a/render_bloom/README.md b/render_bloom/README.md new file mode 100644 index 0000000..bfe5d7a --- /dev/null +++ b/render_bloom/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/screen-effects#bloom diff --git a/render_bloom/render_bloom.blend b/render_bloom/render_bloom.blend new file mode 100644 index 0000000..0770ddb Binary files /dev/null and b/render_bloom/render_bloom.blend differ diff --git a/render_colorgrading/Bundled/luttexture.jpg b/render_colorgrading/Bundled/luttexture.jpg new file mode 100644 index 0000000..b8d53eb Binary files /dev/null and b/render_colorgrading/Bundled/luttexture.jpg differ diff --git a/render_colorgrading/README.md b/render_colorgrading/README.md new file mode 100644 index 0000000..e752042 --- /dev/null +++ b/render_colorgrading/README.md @@ -0,0 +1,15 @@ +### LUT Textures + +1. Create a `Bundled` folder in project root +2. Put a 512x512 LUT jpg in there +3. Leenkx Render Path - Post Process panel: write `luttexture.jpg` + +You might need to clean your project for it to show. + +A color neutral LUT file have been included in `extras` folder. +Simply tweak the colors inside a photo-editing application and call it `luttexture.jpg` + +Other LUT files have also been included. +Use them as you wish. + +Includes pictures are public domain provided by National Gallery of Arts. diff --git a/render_colorgrading/extras/LUT_Cold.jpg b/render_colorgrading/extras/LUT_Cold.jpg new file mode 100644 index 0000000..ecca40e Binary files /dev/null and b/render_colorgrading/extras/LUT_Cold.jpg differ diff --git a/render_colorgrading/extras/LUT_Color_Neutral.jpg b/render_colorgrading/extras/LUT_Color_Neutral.jpg new file mode 100644 index 0000000..30d60be Binary files /dev/null and b/render_colorgrading/extras/LUT_Color_Neutral.jpg differ diff --git a/render_colorgrading/extras/LUT_Noir.jpg b/render_colorgrading/extras/LUT_Noir.jpg new file mode 100644 index 0000000..bf3dfff Binary files /dev/null and b/render_colorgrading/extras/LUT_Noir.jpg differ diff --git a/render_colorgrading/extras/LUT_Selective.jpg b/render_colorgrading/extras/LUT_Selective.jpg new file mode 100644 index 0000000..cb9e16b Binary files /dev/null and b/render_colorgrading/extras/LUT_Selective.jpg differ diff --git a/render_colorgrading/extras/LUT_Sepia.jpg b/render_colorgrading/extras/LUT_Sepia.jpg new file mode 100644 index 0000000..b8d53eb Binary files /dev/null and b/render_colorgrading/extras/LUT_Sepia.jpg differ diff --git a/render_colorgrading/extras/LUT_Wlnx.jpg b/render_colorgrading/extras/LUT_Wlnx.jpg new file mode 100644 index 0000000..34a6f75 Binary files /dev/null and b/render_colorgrading/extras/LUT_Wlnx.jpg differ diff --git a/render_colorgrading/img/calib_1.png b/render_colorgrading/img/calib_1.png new file mode 100644 index 0000000..b9420f7 Binary files /dev/null and b/render_colorgrading/img/calib_1.png differ diff --git a/render_colorgrading/img/calib_2.png b/render_colorgrading/img/calib_2.png new file mode 100644 index 0000000..4bddae2 Binary files /dev/null and b/render_colorgrading/img/calib_2.png differ diff --git a/render_colorgrading/img/tex1.jpg b/render_colorgrading/img/tex1.jpg new file mode 100644 index 0000000..ced0b8d Binary files /dev/null and b/render_colorgrading/img/tex1.jpg differ diff --git a/render_colorgrading/render_colorgrading.blend b/render_colorgrading/render_colorgrading.blend new file mode 100644 index 0000000..6a01938 Binary files /dev/null and b/render_colorgrading/render_colorgrading.blend differ diff --git a/render_splitscreen/Sources/lnx/SplitScreen.hx b/render_splitscreen/Sources/lnx/SplitScreen.hx new file mode 100644 index 0000000..7cf32c8 --- /dev/null +++ b/render_splitscreen/Sources/lnx/SplitScreen.hx @@ -0,0 +1,44 @@ +package lnx; + +import iron.Scene; +import iron.object.CameraObject; +import leenkx.renderpath.RenderPathCreator; + +class SplitScreen extends iron.Trait { + public function new() { + super(); + + notifyOnInit(function() { + + var drawMeshes = RenderPathCreator.drawMeshes; + + // Single viewport size + var w = Std.int(iron.App.w() / 2); + var h = iron.App.h(); + + // Retrieve cameras + var cam1:CameraObject = cast Scene.active.getChild("Camera"); + var cam2:CameraObject = cast Scene.active.getChild("Camera.001"); + cam1.buildProjection(w / h); + cam2.buildProjection(w / h); + + // Override draw method to draw split screen + RenderPathCreator.drawMeshes = function() { + + var g = RenderPathCreator.path.currentG; + + // Left viewport + RenderPathCreator.setTargetMeshes(); + Scene.active.camera = cam1; + g.viewport(0, 0, w, h); + drawMeshes(); + + // Right viewport + RenderPathCreator.setTargetMeshes(); + Scene.active.camera = cam2; + g.viewport(w, 0, w, h); + drawMeshes(); + } + }); + } +} diff --git a/render_splitscreen/render_splitscreen.blend b/render_splitscreen/render_splitscreen.blend new file mode 100644 index 0000000..4a20f17 Binary files /dev/null and b/render_splitscreen/render_splitscreen.blend differ diff --git a/render_to_texture/README.md b/render_to_texture/README.md new file mode 100644 index 0000000..27effff --- /dev/null +++ b/render_to_texture/README.md @@ -0,0 +1,2 @@ +#### Keyboard +`R T F G V B` to rotate suzanne diff --git a/render_to_texture/Sources/lnx/MyTrait.hx b/render_to_texture/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..50c5398 --- /dev/null +++ b/render_to_texture/Sources/lnx/MyTrait.hx @@ -0,0 +1,36 @@ +package lnx; + +class MyTrait extends iron.Trait { + public function new() { + super(); + + notifyOnInit(function() { + // Retrieve camera object + var cam = cast(iron.Scene.active.getChild("Camera.001"), iron.object.CameraObject); + + // Create render target for camera + cam.renderTarget = kha.Image.createRenderTarget( + 640, + 360, + kha.graphics4.TextureFormat.RGBA32, + kha.graphics4.DepthStencilFormat.NoDepthAndStencil + ); + + // Display camera output on this plane + var o = cast(object, iron.object.MeshObject); + o.materials[0].contexts[0].textures[0] = cam.renderTarget; // Override base color texture + + notifyOnRender(function(g:kha.graphics4.Graphics) { + // Set as scene camera + var activeCamera = iron.Scene.active.camera; + iron.Scene.active.camera = cam; + + // Update camera output + cam.renderFrame(g); + + // Restore original camera + iron.Scene.active.camera = activeCamera; + }); + }); + } +} diff --git a/render_to_texture/render_to_texture.blend b/render_to_texture/render_to_texture.blend new file mode 100644 index 0000000..17f9b28 Binary files /dev/null and b/render_to_texture/render_to_texture.blend differ diff --git a/render_voxelao_teapots/render_voxelao_teapots.blend b/render_voxelao_teapots/render_voxelao_teapots.blend new file mode 100644 index 0000000..a3e5be4 Binary files /dev/null and b/render_voxelao_teapots/render_voxelao_teapots.blend differ diff --git a/render_voxelao_teapots/shadows.blend b/render_voxelao_teapots/shadows.blend new file mode 100644 index 0000000..1b018b3 Binary files /dev/null and b/render_voxelao_teapots/shadows.blend differ diff --git a/scene_stream/README.md b/scene_stream/README.md new file mode 100644 index 0000000..cf47040 --- /dev/null +++ b/scene_stream/README.md @@ -0,0 +1,8 @@ +- Scene contains 3000+ unique, non-linked meshes, first build may take over 30 sec +- Far plane is set to 100 to visualize streaming +- Object is streamed at camera distance less than (far_plane * 1.1), and unloaded at distance over (far_plane * 1.5) +- Check debug console to see amount of objects loaded +- Mobile render path is set to focus on stream performance + +- Only HTML5 streaming is multi-threaded currently +- Materials (and associated textures) are preloaded at scene startup diff --git a/scene_stream/scene_stream.blend b/scene_stream/scene_stream.blend new file mode 100644 index 0000000..61e6a5c Binary files /dev/null and b/scene_stream/scene_stream.blend differ diff --git a/screentex/Sources/lnx/MyTrait.hx b/screentex/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..32a07de --- /dev/null +++ b/screentex/Sources/lnx/MyTrait.hx @@ -0,0 +1,27 @@ +package lnx; + +import leenkx.renderpath.RenderPathCreator; + +class MyTrait extends iron.Trait { + public function new() { + super(); + + notifyOnRender2D(function(g:kha.graphics2.Graphics) { + if (RenderPathCreator.finalTarget == null) return; + + // Access final composited image that is afterwards drawn to the screen + var image = RenderPathCreator.finalTarget.image; + + g.color = 0xff000000; + g.fillRect(0, 0, image.width / 5, image.height / 5); + + g.color = 0xffffffff; + if (kha.Image.renderTargetsInvertedY()) { + g.drawScaledImage(image, 0, image.height / 5, image.width / 5, -image.height / 5); + } + else { + g.drawScaledImage(image, 0, 0, image.width / 5, image.height / 5); + } + }); + } +} diff --git a/screentex/screentex.blend b/screentex/screentex.blend new file mode 100644 index 0000000..2e116aa Binary files /dev/null and b/screentex/screentex.blend differ diff --git a/script_camera_lerp/README.md b/script_camera_lerp/README.md new file mode 100644 index 0000000..ebf632c --- /dev/null +++ b/script_camera_lerp/README.md @@ -0,0 +1,2 @@ +Use keys `A` and `D` to rotate the cube. +The camera follows the cube smoothly with interpolation. diff --git a/script_camera_lerp/Sources/lnx/CameraTrait.hx b/script_camera_lerp/Sources/lnx/CameraTrait.hx new file mode 100644 index 0000000..99125f9 --- /dev/null +++ b/script_camera_lerp/Sources/lnx/CameraTrait.hx @@ -0,0 +1,26 @@ +package lnx; + +import iron.object.Object; +import iron.Scene; +import iron.math.Quat; + +class CameraTrait extends iron.Trait { + + var cube:Object; + + public function new() { + super(); + + notifyOnInit(function() { + cube = Scene.active.getChild("Cube"); + }); + + notifyOnUpdate(function() { + if(cube.transform.rot != object.transform.rot){ + var newRot = new Quat().lerp(cube.transform.rot, object.transform.rot, 0.9); + object.transform.rot.setFrom(newRot); + object.transform.buildMatrix(); + } + }); + } +} diff --git a/script_camera_lerp/Sources/lnx/MyTrait.hx b/script_camera_lerp/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..1f1dca5 --- /dev/null +++ b/script_camera_lerp/Sources/lnx/MyTrait.hx @@ -0,0 +1,23 @@ +package lnx; + +import iron.system.Input; +import iron.math.Vec4; +import iron.system.Time; + +class MyTrait extends iron.Trait { + public function new() { + super(); + + notifyOnUpdate(function() { + + var kb = Input.getKeyboard(); + + if(kb.down("a") || kb.down("left")){ + object.transform.rotate(new Vec4(0,0,1), -3 * Time.delta); + } else if(kb.down("d") || kb.down("right")){ + object.transform.rotate(new Vec4(0,0,1), 3 * Time.delta); + } + + }); + } +} diff --git a/script_camera_lerp/script_camera_lerp.blend b/script_camera_lerp/script_camera_lerp.blend new file mode 100644 index 0000000..978ee81 Binary files /dev/null and b/script_camera_lerp/script_camera_lerp.blend differ diff --git a/script_linkedgroup/README.md b/script_linkedgroup/README.md new file mode 100644 index 0000000..59f01a9 --- /dev/null +++ b/script_linkedgroup/README.md @@ -0,0 +1 @@ +Click to spawn pin \ No newline at end of file diff --git a/script_linkedgroup/Sources/lnx/PinSpawner.hx b/script_linkedgroup/Sources/lnx/PinSpawner.hx new file mode 100644 index 0000000..56c9d3c --- /dev/null +++ b/script_linkedgroup/Sources/lnx/PinSpawner.hx @@ -0,0 +1,14 @@ +package lnx; + +class PinSpawner extends iron.Trait { + public function new() { + super(); + + notifyOnUpdate(function() { + var mouse = iron.system.Input.getMouse(); + if (mouse.started()) { + iron.Scene.active.spawnObject("PinGroup", null, null); + } + }); + } +} diff --git a/script_linkedgroup/Sources/lnx/PinTrait.hx b/script_linkedgroup/Sources/lnx/PinTrait.hx new file mode 100644 index 0000000..8308024 --- /dev/null +++ b/script_linkedgroup/Sources/lnx/PinTrait.hx @@ -0,0 +1,12 @@ +package lnx; + +class PinTrait extends iron.Trait { + + public function new() { + super(); + + notifyOnInit(function() { + trace("Pin spawned!"); + }); + } +} diff --git a/script_linkedgroup/pin.blend b/script_linkedgroup/pin.blend new file mode 100644 index 0000000..f5f804a Binary files /dev/null and b/script_linkedgroup/pin.blend differ diff --git a/script_linkedgroup/script_linkedgroup.blend b/script_linkedgroup/script_linkedgroup.blend new file mode 100644 index 0000000..bd19ed3 Binary files /dev/null and b/script_linkedgroup/script_linkedgroup.blend differ diff --git a/script_logic_talk/property/Sources/lnx/ReadConfig.hx b/script_logic_talk/property/Sources/lnx/ReadConfig.hx new file mode 100644 index 0000000..f330c37 --- /dev/null +++ b/script_logic_talk/property/Sources/lnx/ReadConfig.hx @@ -0,0 +1,13 @@ +package lnx; + +class ReadConfig extends iron.Trait { + public function new() { + super(); + + notifyOnInit(function() { + // Retrieve property set from logic nodes + var prop = iron.Scene.global.properties.get("test"); + trace(prop); + }); + } +} diff --git a/script_logic_talk/property/property.blend b/script_logic_talk/property/property.blend new file mode 100644 index 0000000..1a4ceed Binary files /dev/null and b/script_logic_talk/property/property.blend differ diff --git a/script_properties/Sources/lnx/MyTrait.hx b/script_properties/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..0a9bcd2 --- /dev/null +++ b/script_properties/Sources/lnx/MyTrait.hx @@ -0,0 +1,19 @@ +package lnx; + +import iron.math.Vec4; + +class MyTrait extends iron.Trait { + + // Property marked with @prop gets exposed in + // Blender - Properties - Object - Leenkx Traits panel + @prop + var speed:Float = 0.1; + + public function new() { + super(); + + notifyOnUpdate(function() { + object.transform.rotate(Vec4.zAxis(), speed); + }); + } +} diff --git a/script_properties/script_properties.blend b/script_properties/script_properties.blend new file mode 100644 index 0000000..985ab34 Binary files /dev/null and b/script_properties/script_properties.blend differ diff --git a/script_properties_global/Sources/lnx/Config.hx b/script_properties_global/Sources/lnx/Config.hx new file mode 100644 index 0000000..bc7757c --- /dev/null +++ b/script_properties_global/Sources/lnx/Config.hx @@ -0,0 +1,14 @@ +package lnx; + +class Config extends iron.Trait { + + @prop public var speed:Float = 0.1; + @prop public var text:String; + + public static var inst:Config = null; + + public function new() { + super(); + inst = this; + } +} diff --git a/script_properties_global/Sources/lnx/ReadConfig.hx b/script_properties_global/Sources/lnx/ReadConfig.hx new file mode 100644 index 0000000..17fcc34 --- /dev/null +++ b/script_properties_global/Sources/lnx/ReadConfig.hx @@ -0,0 +1,12 @@ +package lnx; + +class ReadConfig extends iron.Trait { + public function new() { + super(); + + notifyOnInit(function() { + var c = Config.inst; + trace("Text is: " + c.text + ", speed is: " + c.speed); + }); + } +} diff --git a/script_properties_global/script_properties_global.blend b/script_properties_global/script_properties_global.blend new file mode 100644 index 0000000..57f1282 Binary files /dev/null and b/script_properties_global/script_properties_global.blend differ diff --git a/script_rigidbody_trigger/README.md b/script_rigidbody_trigger/README.md new file mode 100644 index 0000000..7dff43c --- /dev/null +++ b/script_rigidbody_trigger/README.md @@ -0,0 +1,10 @@ +Rigid body set to: +- Active dynamic +- Axis and rotation locked (linear and angular factor) +- Trigger/Ghost checked making this a trigger instead of a collision object +- Force deactivation unchecked to make sure physics engine keep the rigid body active +- Trigger script checks for overlapping rigid bodies on each update + +## How to test +Move the box around using WASD+QE. +When box is overlapping sphere the icoshpere object is visible, otherwise it's hidden. diff --git a/script_rigidbody_trigger/Sources/lnx/Trigger.hx b/script_rigidbody_trigger/Sources/lnx/Trigger.hx new file mode 100644 index 0000000..631508c --- /dev/null +++ b/script_rigidbody_trigger/Sources/lnx/Trigger.hx @@ -0,0 +1,40 @@ +package lnx; + +import iron.object.Object; +import iron.Scene; +import leenkx.trait.physics.PhysicsWorld; +import leenkx.trait.physics.RigidBody; + +class Trigger extends iron.Trait { + + var rb:RigidBody; + var physics:leenkx.trait.physics.PhysicsWorld; + var obj:Object; + + public function new() { + super(); + + notifyOnInit(function() { + rb = object.getTrait(RigidBody); + physics = leenkx.trait.physics.PhysicsWorld.active; + obj = Scene.active.getChild("Icosphere"); + }); + + notifyOnUpdate(function() { + // TODO: replace with notifyOnCollisionEnter or notifyOnTriggerEnter once implemented + // ref: https://github.com/leenkx3d/leenkx/issues/331 + var rbs = physics.getContacts(object.getTrait(RigidBody)); + var visible = false; + + if (rbs != null) { + for (rb in rbs){ + if(rb.object.name == "Cube"){ + visible = true; + } + } + } + + obj.visible = visible; + }); + } +} diff --git a/script_rigidbody_trigger/script_rigidbody_trigger.blend b/script_rigidbody_trigger/script_rigidbody_trigger.blend new file mode 100644 index 0000000..60f5801 Binary files /dev/null and b/script_rigidbody_trigger/script_rigidbody_trigger.blend differ diff --git a/script_spawnobject/Sources/lnx/SpawnTrait.hx b/script_spawnobject/Sources/lnx/SpawnTrait.hx new file mode 100644 index 0000000..4ac0cd4 --- /dev/null +++ b/script_spawnobject/Sources/lnx/SpawnTrait.hx @@ -0,0 +1,23 @@ +package lnx; + +class SpawnTrait extends iron.Trait { + public function new() { + super(); + + notifyOnInit(function() { + + // Spawn object from scene hierarchy, including children + iron.Scene.active.spawnObject("Cube", null, function(object:iron.object.Object) { + object.transform.loc.set(0, 4, 0); + object.transform.buildMatrix(); + }); + + // Spawn single object from scene hierarchy + var spawnChildren = false; + iron.Scene.active.spawnObject("Cube", null, function(object:iron.object.Object) { + object.transform.loc.set(-4, 0, 0); + object.transform.buildMatrix(); + }, spawnChildren); + }); + } +} diff --git a/script_spawnobject/script_spawnobject.blend b/script_spawnobject/script_spawnobject.blend new file mode 100644 index 0000000..96be83c Binary files /dev/null and b/script_spawnobject/script_spawnobject.blend differ diff --git a/script_transform/README.md b/script_transform/README.md new file mode 100644 index 0000000..0ebe169 --- /dev/null +++ b/script_transform/README.md @@ -0,0 +1 @@ +Check console \ No newline at end of file diff --git a/script_transform/Sources/lnx/TransformTest.hx b/script_transform/Sources/lnx/TransformTest.hx new file mode 100644 index 0000000..3ccda41 --- /dev/null +++ b/script_transform/Sources/lnx/TransformTest.hx @@ -0,0 +1,45 @@ +package lnx; + +class TransformTest extends iron.Trait { + public function new() { + super(); + + notifyOnInit(function() { + + trace('Testing 2 cubes, parent cube at (1, 0, 0), child cube at (5, 0, 0)'); + + trace('Parent location: ' + object.parent.transform.loc); + // (1, 0, 0) + + trace('Child location: ' + object.transform.loc); + // (5, 0, 0) + + trace('Child location in world space: ' + object.transform.world.getLoc()); + // (6, 0, 0) + + trace('Setting child to parent location …'); + object.transform.loc.set(0, 0, 0); + object.transform.buildMatrix(); + + trace('Child location: ' + object.transform.loc); + // (0, 0, 0) + + trace('Child location in world space: ' + object.transform.world.getLoc()); + // (1, 0, 0) + + trace('Moving parent …'); + object.parent.transform.loc.set(0, 3, 0); + object.parent.transform.buildMatrix(); + + trace('Child location: ' + object.transform.loc); + // (0, 0, 0) + + trace('Child location in world space: ' + object.transform.world.getLoc()); + // (0, 3, 0) + + // Note: In Blender, you may need to: + // - Clear Parent - Clear Parent Inverse + // - To get local transform + }); + } +} diff --git a/script_transform/script_transform.blend b/script_transform/script_transform.blend new file mode 100644 index 0000000..9435577 Binary files /dev/null and b/script_transform/script_transform.blend differ diff --git a/server_stream/README.md b/server_stream/README.md new file mode 100644 index 0000000..5fe77e5 --- /dev/null +++ b/server_stream/README.md @@ -0,0 +1 @@ +Press keyboard space to play speaker sound \ No newline at end of file diff --git a/server_stream/Sources/lnx/ArcBall.hx b/server_stream/Sources/lnx/ArcBall.hx new file mode 100644 index 0000000..df13260 --- /dev/null +++ b/server_stream/Sources/lnx/ArcBall.hx @@ -0,0 +1,21 @@ +package lnx; + +import iron.Trait; +import iron.system.Input; +import iron.math.Vec4; + +class ArcBall extends Trait { + + public function new() { + super(); + notifyOnUpdate(update); + } + + function update() { + var mouse = Input.getMouse(); + if (mouse.down()) { + object.transform.rotate(new Vec4(0, 0, 1), mouse.movementX / 100); + object.transform.buildMatrix(); + } + } +} diff --git a/server_stream/Sources/lnx/LoadTrait.hx b/server_stream/Sources/lnx/LoadTrait.hx new file mode 100644 index 0000000..4fa31c8 --- /dev/null +++ b/server_stream/Sources/lnx/LoadTrait.hx @@ -0,0 +1,59 @@ +package lnx; + +import haxe.io.Bytes; +import iron.object.MeshObject; +import iron.data.MeshData; +import iron.data.SceneFormat; +import iron.Scene; + +class LoadTrait extends iron.Trait { + + function getFormat(asset:Dynamic, format:String):Dynamic { + var fs:Array = asset.formats; + for (i in 0...fs.length) if (fs[i].formatType == format) return fs[i]; + return null; + } + + public function new() { + super(); + + notifyOnInit(function() { + // Load Future Car mesh by Dennis Haupt from poly.google.com + // See https://developers.google.com/poly/develop/web + var url = "https://poly.googleapis.com/v1/assets/0XrQdpjc4Vk/?key=AIzaSyAME8tuXn8gIaPcxmVaz0qbar0DkR4Kw6Q"; + var http = new haxe.Http(url); + http.onData = function(data:String) { + var format = getFormat(haxe.Json.parse(data), "OBJ"); + if (format != null) { + var root = format.root; + http = new haxe.Http(root.url); + http.onData = makeMesh; + http.request(); + } + } + http.request(); + }); + } + + function makeMesh(data:String) { + // Parse received .obj data + var mesh = new ObjParser(kha.Blob.fromBytes(Bytes.ofString(data))); + var posaAr: TVertexArray = { attrib: "pos", values: mesh.posa, data: "short4norm"}; + var noraAr: TVertexArray = { attrib: "nor", values: mesh.nora, data: "short2norm"}; + var raw:TMeshData = { + name: "Mesh", + vertex_arrays: [posaAr, noraAr], + index_arrays: [ + { values: mesh.inda, material: 0 } + ], + scale_pos: mesh.scalePos + }; + + // Set as a new mesh for cube object + new MeshData(raw, function(md:MeshData) { + var cube = cast(Scene.active.getChild("Cube"), MeshObject); + cube.data.delete(); + cube.setData(md); + }); + } +} diff --git a/server_stream/Sources/lnx/ObjParser.hx b/server_stream/Sources/lnx/ObjParser.hx new file mode 100644 index 0000000..b77b522 --- /dev/null +++ b/server_stream/Sources/lnx/ObjParser.hx @@ -0,0 +1,395 @@ +package lnx; + +class ObjParser { + + public static var splitCode = "o".code; // Object split, "g" for groups, "u"semtl for materials + public var posa: kha.arrays.Int16Array = null; + public var nora: kha.arrays.Int16Array = null; + public var texa: kha.arrays.Int16Array = null; + public var inda: kha.arrays.Uint32Array = null; + public var udims: Array = null; // Indices split per udim tile + public var udimsU = 1; // Number of horizontal udim tiles + public var scalePos = 1.0; + public var scaleTex = 1.0; + public var name = ""; + public var hasNext = false; // File contains multiple objects + public var pos = 0; + var posTemp: Array; + var uvTemp: Array; + var norTemp: Array; + var va: kha.arrays.Uint32Array; + var ua: kha.arrays.Uint32Array; + var na: kha.arrays.Uint32Array; + var vi = 0; + var ui = 0; + var ni = 0; + var buf: haxe.io.UInt8Array = null; + + static var vindOff = 0; + static var tindOff = 0; + static var nindOff = 0; + static var bytes: haxe.io.Bytes = null; + static var posFirst: Array; + static var uvFirst: Array; + static var norFirst: Array; + + public function new(blob: kha.Blob, startPos = 0, udim = false) { + pos = startPos; + var posIndices: Array = []; + var uvIndices: Array = []; + var norIndices: Array = []; + var readingFaces = false; + var readingObject = false; + var fullAttrib = false; + bytes = blob.bytes; + + posTemp = []; + uvTemp = []; + norTemp = []; + va = new kha.arrays.Uint32Array(60); + ua = new kha.arrays.Uint32Array(60); + na = new kha.arrays.Uint32Array(60); + buf = new haxe.io.UInt8Array(64); + + if (splitCode == "u".code && startPos > 0) { + posTemp = posFirst; + norTemp = norFirst; + uvTemp = uvFirst; + } + + while (true) { + if (pos >= bytes.length) break; + + var c0 = bytes.get(pos++); + if (readingObject && readingFaces && (c0 == "v".code || c0 == splitCode)) { + pos--; + hasNext = true; + break; + } + + if (c0 == "v".code) { + var c1 = bytes.get(pos++); + if (c1 == " ".code) { + // Some exporters put additional space directly after "v" + if (bytes.get(pos) == " ".code) pos++; + posTemp.push(readFloat()); + pos++; // Space + posTemp.push(readFloat()); + pos++; // Space + posTemp.push(readFloat()); + } + else if (c1 == "t".code) { + pos++; // Space + uvTemp.push(readFloat()); + pos++; // Space + uvTemp.push(readFloat()); + if (norTemp.length > 0) fullAttrib = true; + } + else if (c1 == "n".code) { + pos++; // Space + norTemp.push(readFloat()); + pos++; // Space + norTemp.push(readFloat()); + pos++; // Space + norTemp.push(readFloat()); + if (uvTemp.length > 0) fullAttrib = true; + } + } + else if (c0 == "f".code) { + pos++; // Space + readingFaces = true; + vi = 0; + ui = 0; + ni = 0; + fullAttrib ? readFaceFast() : readFace(); + + posIndices.push(va[0]); + posIndices.push(va[1]); + posIndices.push(va[2]); + for (i in 3...vi) { + posIndices.push(va[0]); + posIndices.push(va[i - 1]); + posIndices.push(va[i]); + } + if (uvTemp.length > 0) { + uvIndices.push(ua[0]); + uvIndices.push(ua[1]); + uvIndices.push(ua[2]); + for (i in 3...ui) { + uvIndices.push(ua[0]); + uvIndices.push(ua[i - 1]); + uvIndices.push(ua[i]); + } + } + if (norTemp.length > 0) { + norIndices.push(na[0]); + norIndices.push(na[1]); + norIndices.push(na[2]); + for (i in 3...ni) { + norIndices.push(na[0]); + norIndices.push(na[i - 1]); + norIndices.push(na[i]); + } + } + } + else if (c0 == splitCode) { + if (splitCode == "u".code) pos += 5; // "u"semtl + pos++; // Space + if (!udim) readingObject = true; + name = readString(); + } + nextLine(); + } + + if (startPos > 0) { + if (splitCode != "u".code) { + for (i in 0...posIndices.length) posIndices[i] -= vindOff; + for (i in 0...uvIndices.length) uvIndices[i] -= tindOff; + for (i in 0...norIndices.length) norIndices[i] -= nindOff; + } + } + else { + vindOff = tindOff = nindOff = 0; + + if (splitCode == "u".code) { + posFirst = posTemp; + norFirst = norTemp; + uvFirst = uvTemp; + } + } + vindOff += Std.int(posTemp.length / 3); // Assumes separate vertex data per object + tindOff += Std.int(uvTemp.length / 2); + nindOff += Std.int(norTemp.length / 3); + + // Pack positions to (-1, 1) range + scalePos = 0.0; + for (i in 0...posTemp.length) { + var f = Math.abs(posTemp[i]); + if (scalePos < f) scalePos = f; + } + var inv = 32767 * (1 / scalePos); + + posa = new kha.arrays.Int16Array(posIndices.length * 4); + inda = new kha.arrays.Uint32Array(posIndices.length); + for (i in 0...posIndices.length) { + posa[i * 4 ] = Std.int( posTemp[posIndices[i] * 3 ] * inv); + posa[i * 4 + 1] = Std.int(-posTemp[posIndices[i] * 3 + 2] * inv); + posa[i * 4 + 2] = Std.int( posTemp[posIndices[i] * 3 + 1] * inv); + inda[i] = i; + } + + if (norIndices.length > 0) { + nora = new kha.arrays.Int16Array(norIndices.length * 2); + for (i in 0...posIndices.length) { + nora[i * 2 ] = Std.int( norTemp[norIndices[i] * 3 ] * 32767); + nora[i * 2 + 1] = Std.int(-norTemp[norIndices[i] * 3 + 2] * 32767); + posa[i * 4 + 3] = Std.int( norTemp[norIndices[i] * 3 + 1] * 32767); + } + } + else { + // Calc normals + nora = new kha.arrays.Int16Array(inda.length * 2); + var va = new iron.math.Vec4(); + var vb = new iron.math.Vec4(); + var vc = new iron.math.Vec4(); + var cb = new iron.math.Vec4(); + var ab = new iron.math.Vec4(); + for (i in 0...Std.int(inda.length / 3)) { + var i1 = inda[i * 3 ]; + var i2 = inda[i * 3 + 1]; + var i3 = inda[i * 3 + 2]; + va.set(posa[i1 * 4], posa[i1 * 4 + 1], posa[i1 * 4 + 2]); + vb.set(posa[i2 * 4], posa[i2 * 4 + 1], posa[i2 * 4 + 2]); + vc.set(posa[i3 * 4], posa[i3 * 4 + 1], posa[i3 * 4 + 2]); + cb.subvecs(vc, vb); + ab.subvecs(va, vb); + cb.cross(ab); + cb.normalize(); + nora[i1 * 2 ] = Std.int(cb.x * 32767); + nora[i1 * 2 + 1] = Std.int(cb.y * 32767); + posa[i1 * 4 + 3] = Std.int(cb.z * 32767); + nora[i2 * 2 ] = Std.int(cb.x * 32767); + nora[i2 * 2 + 1] = Std.int(cb.y * 32767); + posa[i2 * 4 + 3] = Std.int(cb.z * 32767); + nora[i3 * 2 ] = Std.int(cb.x * 32767); + nora[i3 * 2 + 1] = Std.int(cb.y * 32767); + posa[i3 * 4 + 3] = Std.int(cb.z * 32767); + } + } + + if (uvIndices.length > 0) { + if (udim) { + // Find number of tiles + var tilesU = 1; + var tilesV = 1; + for (i in 0...Std.int(uvTemp.length / 2)) { + while (uvTemp[i * 2 ] > tilesU) tilesU++; + while (uvTemp[i * 2 + 1] > tilesV) tilesV++; + } + + function getTile(i1: Int, i2: Int, i3: Int): Int { + var u1 = uvTemp[uvIndices[i1] * 2 ]; + var v1 = uvTemp[uvIndices[i1] * 2 + 1]; + var u2 = uvTemp[uvIndices[i2] * 2 ]; + var v2 = uvTemp[uvIndices[i2] * 2 + 1]; + var u3 = uvTemp[uvIndices[i3] * 2 ]; + var v3 = uvTemp[uvIndices[i3] * 2 + 1]; + var tileU = Std.int((u1 + u2 + u3) / 3); + var tileV = Std.int((v1 + v2 + v3) / 3); + return tileU + tileV * tilesU; + } + + // Amount of indices pre tile + var num = new kha.arrays.Uint32Array(tilesU * tilesV); + for (i in 0...Std.int(inda.length / 3)) { + var tile = getTile(inda[i * 3], inda[i * 3 + 1], inda[i * 3 + 2]); + num[tile] += 3; + } + + // Split indices per tile + udims = []; + udimsU = tilesU; + for (i in 0...tilesU * tilesV) { udims.push(new kha.arrays.Uint32Array(num[i])); num[i] = 0; } + + for (i in 0...Std.int(inda.length / 3)) { + var i1 = inda[i * 3 ]; + var i2 = inda[i * 3 + 1]; + var i3 = inda[i * 3 + 2]; + var tile = getTile(i1, i2, i3); + udims[tile][num[tile]++] = i1; + udims[tile][num[tile]++] = i2; + udims[tile][num[tile]++] = i3; + } + + // Normalize uvs to 0-1 range + var uvtiles = new kha.arrays.Int16Array(uvTemp.length); + for (i in 0...Std.int(inda.length / 3)) { // TODO: merge loops + var i1 = inda[i * 3 ]; + var i2 = inda[i * 3 + 1]; + var i3 = inda[i * 3 + 2]; + var tile = getTile(i1, i2, i3); + var tileU = tile % tilesU; + var tileV = Std.int(tile / tilesU); + uvtiles[uvIndices[i1] * 2 ] = tileU; + uvtiles[uvIndices[i1] * 2 + 1] = tileV; + uvtiles[uvIndices[i2] * 2 ] = tileU; + uvtiles[uvIndices[i2] * 2 + 1] = tileV; + uvtiles[uvIndices[i3] * 2 ] = tileU; + uvtiles[uvIndices[i3] * 2 + 1] = tileV; + } + for (i in 0...uvtiles.length) uvTemp[i] -= uvtiles[i]; + } + + texa = new kha.arrays.Int16Array(uvIndices.length * 2); + for (i in 0...posIndices.length) { + texa[i * 2 ] = Std.int( uvTemp[uvIndices[i] * 2 ] * 32767); + texa[i * 2 + 1] = Std.int((1.0 - uvTemp[uvIndices[i] * 2 + 1]) * 32767); + } + } + bytes = null; + if (!hasNext) { posFirst = norFirst = uvFirst = null; } + } + + function readFaceFast() { + while (true) { + va[vi++] = readInt() - 1; + pos++; // "/" + ua[ui++] = readInt() - 1; + pos++; // "/" + na[ni++] = readInt() - 1; + if (bytes.get(pos) == "\n".code || bytes.get(pos) == "\r".code) break; + pos++; // " " + // Some exporters put space at the end of "f" line + if (vi >= 3 && (bytes.get(pos) == "\n".code || bytes.get(pos) == "\r".code)) break; + } + } + + function readFace() { + while (true) { + va[vi++] = readInt() - 1; + if (uvTemp.length > 0 || norTemp.length > 0) { + pos++; // "/" + } + if (uvTemp.length > 0) { + ua[ui++] = readInt() - 1; + } + if (norTemp.length > 0) { + pos++; // "/" + na[ni++] = readInt() - 1; + } + if (bytes.get(pos) == "\n".code || bytes.get(pos) == "\r".code) break; + pos++; // " " + // Some exporters put space at the end of "f" line + if (vi >= 3 && (bytes.get(pos) == "\n".code || bytes.get(pos) == "\r".code)) break; + } + } + + function readFloat(): Float { + var bi = 0; + while (true) { // Read into buffer + var c = bytes.get(pos); + if (c == " ".code || c == "\n".code || c == "\r".code) break; + if (c == "E".code || c == "e".code) { + while (true) { + pos++; + c = bytes.get(pos); + if (c == " ".code || c == "\n".code || c == "\r".code) break; + } + return 0.0; // Assume number close to zero for now + } + pos++; + buf[bi++] = c; + } + var res = 0.0; // Parse buffer into float + var dot = 1; + var dec = 1; + var off = buf[0] == "-".code ? 1 : 0; + var len = bi - 1; + for (i in 0...bi - off) { + var c = buf[len - i]; + if (c == ".".code) { dot = dec; continue; } + res += (c - 48) * dec; + dec *= 10; + } + off > 0 ? res /= -dot : res /= dot; + return res; + } + + function readInt(): Int { + var bi = 0; + while (true) { // Read into buffer + var c = bytes.get(pos); + if (c == "/".code || c == "\n".code || c == "\r".code || c == " ".code) break; + pos++; + buf[bi++] = c; + } + var res = 0; // Parse buffer into int + var dec = 1; + var off = buf[0] == "-".code ? 1 : 0; + var len = bi - 1; + for (i in 0...bi - off) { + res += (buf[len - i] - 48) * dec; + dec *= 10; + } + if (off > 0) res *= -1; + return res; + } + + function readString(): String { + var s = ""; + while (true) { + var c = bytes.get(pos); + if (c == "\n".code || c == "\r".code || c == " ".code) break; + pos++; + s += String.fromCharCode(c); + } + return s; + } + + function nextLine() { + while (true) { + var c = bytes.get(pos++); + if (c == "\n".code || pos >= bytes.length) break; // \n, \r\n + } + } +} diff --git a/server_stream/server_stream.blend b/server_stream/server_stream.blend new file mode 100644 index 0000000..83f60dd Binary files /dev/null and b/server_stream/server_stream.blend differ diff --git a/sound/Bundled/hit0.wav b/sound/Bundled/hit0.wav new file mode 100644 index 0000000..0c2cd67 Binary files /dev/null and b/sound/Bundled/hit0.wav differ diff --git a/sound/Bundled/hit1.wav b/sound/Bundled/hit1.wav new file mode 100644 index 0000000..97d48cc Binary files /dev/null and b/sound/Bundled/hit1.wav differ diff --git a/sound/Bundled/hit2.wav b/sound/Bundled/hit2.wav new file mode 100644 index 0000000..f8de89a Binary files /dev/null and b/sound/Bundled/hit2.wav differ diff --git a/sound/README.md b/sound/README.md new file mode 100644 index 0000000..3b6782e --- /dev/null +++ b/sound/README.md @@ -0,0 +1,6 @@ +- Keyboard `Space`: load/play bundled sound +- Keyboard `A`: toggle play/pause positional speaker + +- https://github.com/leenkx3d/leenkx/wiki/sound +- https://api.leenkx3d.org/iron/object/SpeakerObject.html +- https://api.leenkx3d.org/kha/Sound.html diff --git a/sound/Sources/lnx/SoundControl.hx b/sound/Sources/lnx/SoundControl.hx new file mode 100644 index 0000000..bc019ac --- /dev/null +++ b/sound/Sources/lnx/SoundControl.hx @@ -0,0 +1,32 @@ +package lnx; + +import iron.object.SpeakerObject; +import iron.system.Input; + +class SoundControl extends iron.Trait { + + public function new() { + super(); + notifyOnInit(() -> { + final mouse = Input.getMouse(); + final keyboard = Input.getKeyboard(); + final speaker = iron.Scene.active.getSpeaker('Speaker'); + trace(speaker.data); + notifyOnUpdate( () -> { + if(keyboard.started('a')) { + trace('Toggle speaker (${!speaker.paused})'); + speaker.paused ? speaker.play() : speaker.pause(); + } + if(keyboard.started('space')) { + // Randomly play one of the three hit sounds + final sound = 'hit${Std.random(3)}.wav'; + trace('Play $sound'); + iron.data.Data.getSound(sound, (s:kha.Sound) -> { + var channel = iron.system.Audio.play(s); + channel.volume = 0.4; + }); + } + }); + }); + } +} diff --git a/sound/drums.wav b/sound/drums.wav new file mode 100644 index 0000000..ba4fd96 Binary files /dev/null and b/sound/drums.wav differ diff --git a/sound/sound.blend b/sound/sound.blend new file mode 100644 index 0000000..d10fee1 Binary files /dev/null and b/sound/sound.blend differ diff --git a/spawn_from_scene/README.md b/spawn_from_scene/README.md new file mode 100644 index 0000000..efa34d3 --- /dev/null +++ b/spawn_from_scene/README.md @@ -0,0 +1,3 @@ +Spawns an object from another scene. + +https://api.leenkx3d.org/iron/Scene.html#spawnObject diff --git a/spawn_from_scene/Sources/lnx/MyTrait.hx b/spawn_from_scene/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..b3270c5 --- /dev/null +++ b/spawn_from_scene/Sources/lnx/MyTrait.hx @@ -0,0 +1,22 @@ +package lnx; + +import iron.Scene; +import iron.object.Object; +import iron.data.Data; +import iron.data.SceneFormat; + +class MyTrait extends iron.Trait { + public function new() { + super(); + notifyOnInit(init); + } + + function init() { + Data.getSceneRaw("Scene.001", function (raw:TSceneFormat) { + var obj = Scene.getRawObjectByName(raw, "Suzanne"); + Scene.active.createObject(obj, raw, null, null, function(o:Object) { + trace("Suzanne spawned!"); + }); + }); + } +} diff --git a/spawn_from_scene/spawn_from_scene.blend b/spawn_from_scene/spawn_from_scene.blend new file mode 100644 index 0000000..6f33c8d Binary files /dev/null and b/spawn_from_scene/spawn_from_scene.blend differ diff --git a/text_area_string/text_area_string.blend b/text_area_string/text_area_string.blend new file mode 100644 index 0000000..32a45a6 Binary files /dev/null and b/text_area_string/text_area_string.blend differ diff --git a/tilesheet/README.md b/tilesheet/README.md new file mode 100644 index 0000000..857755f --- /dev/null +++ b/tilesheet/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/Tilesheets diff --git a/tilesheet/Sources/lnx/AnimControl.hx b/tilesheet/Sources/lnx/AnimControl.hx new file mode 100644 index 0000000..081af62 --- /dev/null +++ b/tilesheet/Sources/lnx/AnimControl.hx @@ -0,0 +1,22 @@ +package lnx; + +class AnimControl extends iron.Trait { + + var tilesheet:iron.object.Tilesheet; + + public function new() { + super(); + + notifyOnInit(function() { + tilesheet = cast(object, iron.object.MeshObject).tilesheet; + iron.system.Tween.timer(Std.random(8), playAnim); + }); + } + + function playAnim() { + tilesheet.play("rest", function() { + tilesheet.play("idle"); + iron.system.Tween.timer(Std.random(8), playAnim); + }); + } +} diff --git a/tilesheet/textures/dungeon tileset calciumtrice simple.png b/tilesheet/textures/dungeon tileset calciumtrice simple.png new file mode 100644 index 0000000..1c07787 Binary files /dev/null and b/tilesheet/textures/dungeon tileset calciumtrice simple.png differ diff --git a/tilesheet/textures/minotaur spritesheet calciumtrice.png b/tilesheet/textures/minotaur spritesheet calciumtrice.png new file mode 100644 index 0000000..2c3a5f8 Binary files /dev/null and b/tilesheet/textures/minotaur spritesheet calciumtrice.png differ diff --git a/tilesheet/textures/orc spritesheet calciumtrice.png b/tilesheet/textures/orc spritesheet calciumtrice.png new file mode 100644 index 0000000..9c6f84b Binary files /dev/null and b/tilesheet/textures/orc spritesheet calciumtrice.png differ diff --git a/tilesheet/textures/ranger spritesheet calciumtrice.png b/tilesheet/textures/ranger spritesheet calciumtrice.png new file mode 100644 index 0000000..ea19fae Binary files /dev/null and b/tilesheet/textures/ranger spritesheet calciumtrice.png differ diff --git a/tilesheet/textures/rogue spritesheet calciumtrice_0.png b/tilesheet/textures/rogue spritesheet calciumtrice_0.png new file mode 100644 index 0000000..9a979f9 Binary files /dev/null and b/tilesheet/textures/rogue spritesheet calciumtrice_0.png differ diff --git a/tilesheet/textures/warrior spritesheet calciumtrice.png b/tilesheet/textures/warrior spritesheet calciumtrice.png new file mode 100644 index 0000000..881f12f Binary files /dev/null and b/tilesheet/textures/warrior spritesheet calciumtrice.png differ diff --git a/tilesheet/textures/wizard spritesheet calciumtrice.png b/tilesheet/textures/wizard spritesheet calciumtrice.png new file mode 100644 index 0000000..5694a1c Binary files /dev/null and b/tilesheet/textures/wizard spritesheet calciumtrice.png differ diff --git a/tilesheet/tilesheet.blend b/tilesheet/tilesheet.blend new file mode 100644 index 0000000..4959bfe Binary files /dev/null and b/tilesheet/tilesheet.blend differ diff --git a/tilesheet_2d/README.md b/tilesheet_2d/README.md new file mode 100644 index 0000000..857755f --- /dev/null +++ b/tilesheet_2d/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/Tilesheets diff --git a/tilesheet_2d/Sources/lnx/AnimControl.hx b/tilesheet_2d/Sources/lnx/AnimControl.hx new file mode 100644 index 0000000..081af62 --- /dev/null +++ b/tilesheet_2d/Sources/lnx/AnimControl.hx @@ -0,0 +1,22 @@ +package lnx; + +class AnimControl extends iron.Trait { + + var tilesheet:iron.object.Tilesheet; + + public function new() { + super(); + + notifyOnInit(function() { + tilesheet = cast(object, iron.object.MeshObject).tilesheet; + iron.system.Tween.timer(Std.random(8), playAnim); + }); + } + + function playAnim() { + tilesheet.play("rest", function() { + tilesheet.play("idle"); + iron.system.Tween.timer(Std.random(8), playAnim); + }); + } +} diff --git a/tilesheet_2d/textures/dungeon tileset calciumtrice simple.png b/tilesheet_2d/textures/dungeon tileset calciumtrice simple.png new file mode 100644 index 0000000..1c07787 Binary files /dev/null and b/tilesheet_2d/textures/dungeon tileset calciumtrice simple.png differ diff --git a/tilesheet_2d/textures/minotaur spritesheet calciumtrice.png b/tilesheet_2d/textures/minotaur spritesheet calciumtrice.png new file mode 100644 index 0000000..2c3a5f8 Binary files /dev/null and b/tilesheet_2d/textures/minotaur spritesheet calciumtrice.png differ diff --git a/tilesheet_2d/textures/orc spritesheet calciumtrice.png b/tilesheet_2d/textures/orc spritesheet calciumtrice.png new file mode 100644 index 0000000..9c6f84b Binary files /dev/null and b/tilesheet_2d/textures/orc spritesheet calciumtrice.png differ diff --git a/tilesheet_2d/textures/ranger spritesheet calciumtrice.png b/tilesheet_2d/textures/ranger spritesheet calciumtrice.png new file mode 100644 index 0000000..c6e4593 Binary files /dev/null and b/tilesheet_2d/textures/ranger spritesheet calciumtrice.png differ diff --git a/tilesheet_2d/textures/rogue spritesheet calciumtrice_0.png b/tilesheet_2d/textures/rogue spritesheet calciumtrice_0.png new file mode 100644 index 0000000..9a979f9 Binary files /dev/null and b/tilesheet_2d/textures/rogue spritesheet calciumtrice_0.png differ diff --git a/tilesheet_2d/textures/warrior spritesheet calciumtrice.png b/tilesheet_2d/textures/warrior spritesheet calciumtrice.png new file mode 100644 index 0000000..881f12f Binary files /dev/null and b/tilesheet_2d/textures/warrior spritesheet calciumtrice.png differ diff --git a/tilesheet_2d/textures/wizard spritesheet calciumtrice.png b/tilesheet_2d/textures/wizard spritesheet calciumtrice.png new file mode 100644 index 0000000..5694a1c Binary files /dev/null and b/tilesheet_2d/textures/wizard spritesheet calciumtrice.png differ diff --git a/tilesheet_2d/tilesheet_2d.blend b/tilesheet_2d/tilesheet_2d.blend new file mode 100644 index 0000000..dda9470 Binary files /dev/null and b/tilesheet_2d/tilesheet_2d.blend differ diff --git a/tilesheet_walkcycle/README.md b/tilesheet_walkcycle/README.md new file mode 100644 index 0000000..4b876b8 --- /dev/null +++ b/tilesheet_walkcycle/README.md @@ -0,0 +1,2 @@ +The level is built using [SpryTile blender add-on](https://chemikhazi.itch.io/sprytile). +https://github.com/leenkx3d/leenkx/wiki/Tilesheets diff --git a/tilesheet_walkcycle/Sources/lnx/AnimControl.hx b/tilesheet_walkcycle/Sources/lnx/AnimControl.hx new file mode 100644 index 0000000..081af62 --- /dev/null +++ b/tilesheet_walkcycle/Sources/lnx/AnimControl.hx @@ -0,0 +1,22 @@ +package lnx; + +class AnimControl extends iron.Trait { + + var tilesheet:iron.object.Tilesheet; + + public function new() { + super(); + + notifyOnInit(function() { + tilesheet = cast(object, iron.object.MeshObject).tilesheet; + iron.system.Tween.timer(Std.random(8), playAnim); + }); + } + + function playAnim() { + tilesheet.play("rest", function() { + tilesheet.play("idle"); + iron.system.Tween.timer(Std.random(8), playAnim); + }); + } +} diff --git a/tilesheet_walkcycle/sprite_tux.png b/tilesheet_walkcycle/sprite_tux.png new file mode 100644 index 0000000..ba811b5 Binary files /dev/null and b/tilesheet_walkcycle/sprite_tux.png differ diff --git a/tilesheet_walkcycle/tilesheet_walkcycle.blend b/tilesheet_walkcycle/tilesheet_walkcycle.blend new file mode 100644 index 0000000..c2c85ec Binary files /dev/null and b/tilesheet_walkcycle/tilesheet_walkcycle.blend differ diff --git a/tween/Sources/lnx/MyTrait.hx b/tween/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..f2aa636 --- /dev/null +++ b/tween/Sources/lnx/MyTrait.hx @@ -0,0 +1,62 @@ +package lnx; + +import iron.system.Tween; +import iron.math.Vec4; +import iron.math.Quat; + +class MyTrait extends iron.Trait { + + public function new() { + super(); + + notifyOnInit(function() { + scaleUp(); + }); + } + + var q = new Quat(); + + function scaleUp() { + // Begin tween + iron.system.Tween.to({ + target: object.transform, + props: { // Target values to tween + loc: new Vec4(0, 0, 1), + scale: new Vec4(1.5, 1.5, 1.5), + rot: q.fromEuler(0, 0, Math.PI / 2), // Radians + }, + duration: 1.0, + // Optional + delay: 0, // Wait before tweening starts + tick: function() { trace("Scaling up"); }, // Tweening in progress + done: scaleDown, // Tweening finished + ease: Ease.ExpoOut + }); + + // Single vector component + // iron.system.Tween.to({ + // target: object.transform.loc, + // props: { z: 1.0 }, + // duration: 1.0, + // done: scaleDown, + // // Make sure transform matrix gets updated + // tick: function() { object.transform.dirty = true; } + // }); + } + + function scaleDown() { + iron.system.Tween.to({ + target: object.transform, + props: { + loc: new Vec4(0, 0, 0), + scale: new Vec4(1, 1, 1), + rot: q.fromEuler(0, 0, 0) + }, + duration: 1.0, + delay: 0, + tick: function() { trace("Scaling down"); }, + done: scaleUp, + ease: Ease.Linear + }); + } +} diff --git a/tween/tween.blend b/tween/tween.blend new file mode 100644 index 0000000..18e0ed6 Binary files /dev/null and b/tween/tween.blend differ diff --git a/ui_canvas/Assets/crate.png b/ui_canvas/Assets/crate.png new file mode 100644 index 0000000..c86f830 Binary files /dev/null and b/ui_canvas/Assets/crate.png differ diff --git a/ui_canvas/Assets/license.txt b/ui_canvas/Assets/license.txt new file mode 100644 index 0000000..cad6355 --- /dev/null +++ b/ui_canvas/Assets/license.txt @@ -0,0 +1,2 @@ +Crate by Cpt_flash - CC0 +https://opengameart.org/content/2d-wooden-box \ No newline at end of file diff --git a/ui_canvas/Bundled/canvas/MyCanvas.files b/ui_canvas/Bundled/canvas/MyCanvas.files new file mode 100644 index 0000000..f79e962 --- /dev/null +++ b/ui_canvas/Bundled/canvas/MyCanvas.files @@ -0,0 +1 @@ +../../Assets/crate.png diff --git a/ui_canvas/Bundled/canvas/MyCanvas.json b/ui_canvas/Bundled/canvas/MyCanvas.json new file mode 100644 index 0000000..f7f1107 --- /dev/null +++ b/ui_canvas/Bundled/canvas/MyCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":960,"height":540,"elements":[{"id":0,"type":0,"name":"MyText","event":"","x":0,"y":0,"width":364,"height":48,"text":"Text","asset":"crate.png","color":-1,"anchor":3,"children":[],"visible":true,"rotation":0,"color_text":-1},{"id":1,"type":1,"name":"MyImage","event":"","x":352,"y":120,"width":256,"height":256,"text":"Image","asset":"crate.png","color":-1,"anchor":0,"children":[],"visible":true,"rotation":0,"color_text":-1,"color_hover":-1},{"id":2,"type":2,"name":"MyButton","event":"buttonEvent","x":5,"y":60,"width":150,"height":34,"text":"0","asset":"crate.png","color":-1,"anchor":0,"children":[],"visible":true,"rotation":0,"color_text":-13290187,"color_hover":-5066062,"color_press":-10921639},{"id":3,"type":9,"name":"Shape","event":"","x":742,"y":66,"width":190,"height":145,"rotation":0,"text":"My Shape","asset":"","color":16777215,"anchor":0,"parent":null,"children":[7,8,10],"visible":true},{"id":4,"type":2,"name":"MenuButton","event":"toggleMenu","x":779,"y":7,"width":150,"height":44,"rotation":0,"text":"Menu","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true,"color_text":-12763843,"color_hover":-5066062,"color_press":-8421505},{"id":7,"type":8,"name":"Combo","event":"","x":0,"y":4,"width":190,"height":44,"rotation":0,"text":"Combo 1;Combo 2","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":true,"color_text":-1,"color_hover":-5066062},{"id":8,"type":7,"name":"Radio","event":"","x":0,"y":49,"width":190,"height":44,"rotation":0,"text":"Radio 1;Radio 2","asset":"","color":-1,"anchor":0,"parent":3,"children":[],"visible":true,"color_text":-1,"color_hover":-5066062},{"id":9,"type":6,"name":"Check","event":"","x":5,"y":112,"width":150,"height":44,"rotation":0,"text":"Rotate","asset":"","color":-1,"anchor":0,"parent":null,"children":[],"visible":true,"color_text":-1,"color_hover":-5066062},{"id":10,"type":9,"name":"Slider","event":"","x":2,"y":98,"width":187,"height":48,"rotation":0,"text":"My Slider","asset":"","color":-1,"color_text":-8226182,"color_hover":-1,"color_press":-15000805,"anchor":0,"parent":3,"children":[],"visible":true}],"assets":[{"name":"crate.png","file":"../../Assets/crate.png","id":0}]} \ No newline at end of file diff --git a/ui_canvas/README.md b/ui_canvas/README.md new file mode 100644 index 0000000..8806744 --- /dev/null +++ b/ui_canvas/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/ui_editor diff --git a/ui_canvas/Sources/lnx/CanvasTrait.hx b/ui_canvas/Sources/lnx/CanvasTrait.hx new file mode 100644 index 0000000..5415b45 --- /dev/null +++ b/ui_canvas/Sources/lnx/CanvasTrait.hx @@ -0,0 +1,54 @@ +package lnx; + +import iron.Scene; +import iron.App; +import iron.system.Time; +import leenkx.system.Event; +import leenkx.trait.internal.CanvasScript; + +class CanvasTrait extends iron.Trait { + + var canvas:CanvasScript; + var clicks = 0; + + public function new() { + super(); + + notifyOnInit(function() { + // Get canvas attached to scene + canvas = Scene.active.getTrait(CanvasScript); + + // Notify on button click + Event.add("buttonEvent", onEvent); + Event.add("toggleMenu", onToggleMenu); + + canvas.notifyOnReady(function() { + notifyOnUpdate(update); + }); + }); + } + + function onEvent() { + // Set butotn text + canvas.getElement("MyButton").text = Std.string(++clicks); + } + + function onToggleMenu() { + var shape = canvas.getElement("Shape"); + shape.visible = !shape.visible; + } + + function update() { + // Canvas may be still being loaded + if (!canvas.ready) return; + + // Set text + canvas.getElement("MyText").text = "Hello world"; + + // Move image + var img = canvas.getElement("MyImage"); + var center = App.w() / 2 - img.width / 2; + img.x = center + Math.sin(Time.time()) * 100; + img.rotation = canvas.getHandle("Check").selected ? Math.PI / 4 : 0; + } +} diff --git a/ui_canvas/ui_canvas.blend b/ui_canvas/ui_canvas.blend new file mode 100644 index 0000000..e72935d Binary files /dev/null and b/ui_canvas/ui_canvas.blend differ diff --git a/ui_events/Bundled/canvas/MyCanvas.files b/ui_events/Bundled/canvas/MyCanvas.files new file mode 100644 index 0000000..e69de29 diff --git a/ui_events/Bundled/canvas/MyCanvas.json b/ui_events/Bundled/canvas/MyCanvas.json new file mode 100644 index 0000000..68faff4 --- /dev/null +++ b/ui_events/Bundled/canvas/MyCanvas.json @@ -0,0 +1 @@ +{"name":"untitled","x":0,"y":0,"width":960,"height":540,"elements":[{"id":1,"type":2,"name":"Button","event":"move_box","x":20,"y":20,"width":201,"height":57,"text":"Move Box","asset":"","color":-1,"anchor":0,"children":[],"visible":true,"rotation":0}],"assets":[],"theme":"Default Light"} \ No newline at end of file diff --git a/ui_events/README.md b/ui_events/README.md new file mode 100644 index 0000000..8806744 --- /dev/null +++ b/ui_events/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/ui_editor diff --git a/ui_events/Sources/lnx/MyTrait.hx b/ui_events/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..42385e9 --- /dev/null +++ b/ui_events/Sources/lnx/MyTrait.hx @@ -0,0 +1,16 @@ +package lnx; + +class MyTrait extends iron.Trait { + public function new() { + super(); + leenkx.system.Event.add("move_box", onEvent); + } + + function onEvent() { + trace("move_box"); + var loc = object.transform.loc; + loc.y += 1; + if (loc.y > 4) loc.y -= 8; + object.transform.buildMatrix(); + } +} diff --git a/ui_events/ui_events.blend b/ui_events/ui_events.blend new file mode 100644 index 0000000..4513e5f Binary files /dev/null and b/ui_events/ui_events.blend differ diff --git a/ui_script2d/README.md b/ui_script2d/README.md new file mode 100644 index 0000000..00929d4 --- /dev/null +++ b/ui_script2d/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/zui diff --git a/ui_script2d/Sources/lnx/UITrait.hx b/ui_script2d/Sources/lnx/UITrait.hx new file mode 100644 index 0000000..ede1f43 --- /dev/null +++ b/ui_script2d/Sources/lnx/UITrait.hx @@ -0,0 +1,89 @@ +package lnx; + +import iron.object.Object; +import zui.*; + +class UITrait extends iron.Trait { + + var ui:Zui; + var cube:Object; + var plane:Object; + var move = true; + + public function new() { + super(); + + // Load font for UI labels + iron.data.Data.getFont("font_default.ttf", function(f:kha.Font) { + ui = new Zui({font: f}); + iron.Scene.active.notifyOnInit(sceneInit); + }); + } + + function sceneInit() { + // Store references to cube and plane objects + cube = iron.Scene.active.getChild("Cube"); + plane = iron.Scene.active.getChild("Plane"); + notifyOnRender2D(render2D); + notifyOnUpdate(update); + } + + function render2D(g:kha.graphics2.Graphics) { + g.end(); + + // Start with UI + ui.begin(g); + // Make window + if (ui.window(Id.handle(), 20, 20, 230, 600, true)) { + // Make panel in this window + if (ui.panel(Id.handle({selected: true}), "Menu")) { + ui.indent(); + + // Scale sliders + ui.text("Scale"); + var sx = ui.slider(Id.handle({value: 1.0}), "X", 0, 2, true); + var sy = ui.slider(Id.handle({value: 1.0}), "Y", 0, 2, true); + var sz = ui.slider(Id.handle({value: 1.0}), "Z", 0, 2, true); + + // Rotation sliders + ui.text("Rotation"); + var rx = ui.slider(Id.handle(), "X", 0, 3.14); + var ry = ui.slider(Id.handle(), "Y", 0, 3.14); + var rz = ui.slider(Id.handle(), "Z", 0, 3.14); + + // Move checkbox + move = ui.check(Id.handle({selected: move}), "Move"); + + // Toggle buttons + if (ui.button("Toggle Cube")) { + cube.visible = !cube.visible; + } + + ui.row([1/2, 1/2]); + if (ui.button("Toggle Plane")) { + plane.visible = !plane.visible; + } + if (ui.button("Rotate Plane")) { + plane.transform.rotate(iron.math.Vec4.zAxis(), Math.random() * 3.14); + } + + ui.unindent(); + + // Set cube transform using values set in UI + cube.transform.setRotation(rx, ry, rz); + cube.transform.scale.set(sx, sy, sz); + } + } + ui.end(); + + g.begin(false); + } + + function update() { + // Translate cube location over time + if (move) { + cube.transform.loc.x = Math.sin(iron.system.Time.time() * 2); + cube.transform.dirty = true; + } + } +} diff --git a/ui_script2d/ui_script2d.blend b/ui_script2d/ui_script2d.blend new file mode 100644 index 0000000..36eb647 Binary files /dev/null and b/ui_script2d/ui_script2d.blend differ diff --git a/ui_script3d/Assets/dummy.jpg b/ui_script3d/Assets/dummy.jpg new file mode 100644 index 0000000..70857f1 Binary files /dev/null and b/ui_script3d/Assets/dummy.jpg differ diff --git a/ui_script3d/README.md b/ui_script3d/README.md new file mode 100644 index 0000000..00929d4 --- /dev/null +++ b/ui_script3d/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/zui diff --git a/ui_script3d/Sources/lnx/UITrait.hx b/ui_script3d/Sources/lnx/UITrait.hx new file mode 100644 index 0000000..7fc097b --- /dev/null +++ b/ui_script3d/Sources/lnx/UITrait.hx @@ -0,0 +1,79 @@ +package lnx; + +import iron.object.Object; +import iron.system.Input; +import zui.*; + +class UITrait extends iron.Trait { + + var ui:Zui; + var rt:kha.Image; // Render target for UI + var uiWidth = 512; + var uiHeight = 512; + var gate:Object; + var opened = false; + + public function new() { + super(); + + // Load font for UI labels + iron.data.Data.getFont("font_default.ttf", function(f:kha.Font) { + ui = new Zui({font: f, autoNotifyInput: false}); + iron.Scene.active.notifyOnInit(sceneInit); + }); + } + + function sceneInit() { + // Reference to gate object + gate = iron.Scene.active.getChild('Gate'); + gate.animation.pause(); + + rt = kha.Image.createRenderTarget(uiWidth, uiHeight); + + // We will use empty texture slot in attached material to render UI + var mat:iron.data.MaterialData = cast(object, iron.object.MeshObject).materials[0]; + mat.contexts[0].textures[0] = rt; // Override diffuse texture + + notifyOnRender(render); + notifyOnUpdate(update); + } + + function render(g:kha.graphics4.Graphics) { + // Begin drawing UI + ui.begin(rt.g2); + // Make new window + if (ui.window(Id.handle(), 0, 0, uiWidth, uiHeight, true)) { + // Gate controll buttons + if (ui.button("Open") && !opened) { + // Gate object is animated in Blender + // Play GateOpen animation + gate.animation.play('GateOpen', function() { gate.animation.pause(); }); + opened = true; + } + if (ui.button("Close") && opened) { + // And close.. + gate.animation.play('GateClose', function() { gate.animation.pause(); }); + opened = false; + } + } + ui.end(); + } + + function update() { + // Get plane UV + var mouse = Input.getMouse(); + var uv = iron.math.RayCaster.boxIntersect(cast object.transform, mouse.x, mouse.y, iron.Scene.active.camera); + if (uv == null) return; + + // Pixel coords + var d1 = object.transform.dim; + var px = Std.int(((uv.x-(-d1.x/2)) / ((d1.x/2)-(-d1.x/2)) - object.transform.worldx()) * uiWidth); + var py = Std.int(((uv.z-(d1.z/2)) / ((d1.z/2)-(-d1.z/2)) - object.transform.worldz()) * -uiHeight) ; + + + // Send input events + if (mouse.started()) ui.onMouseDown(0, px, py); + else if (mouse.released()) ui.onMouseUp(0, px, py); + if (mouse.movementX != 0 || mouse.movementY != 0) ui.onMouseMove(px, py, 0, 0); + } +} diff --git a/ui_script3d/checker.png b/ui_script3d/checker.png new file mode 100644 index 0000000..75d30e0 Binary files /dev/null and b/ui_script3d/checker.png differ diff --git a/ui_script3d/checker_rough.png b/ui_script3d/checker_rough.png new file mode 100644 index 0000000..5fad6a5 Binary files /dev/null and b/ui_script3d/checker_rough.png differ diff --git a/ui_script3d/ui_script3d.blend b/ui_script3d/ui_script3d.blend new file mode 100644 index 0000000..99f702c Binary files /dev/null and b/ui_script3d/ui_script3d.blend differ diff --git a/wasm_call/Bundled/main.wasm b/wasm_call/Bundled/main.wasm new file mode 100644 index 0000000..3a4ab81 Binary files /dev/null and b/wasm_call/Bundled/main.wasm differ diff --git a/wasm_call/README.md b/wasm_call/README.md new file mode 100644 index 0000000..97e5678 --- /dev/null +++ b/wasm_call/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/wasm diff --git a/wasm_call/Sources/lnx/MyTrait.hx b/wasm_call/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..4a0cb6f --- /dev/null +++ b/wasm_call/Sources/lnx/MyTrait.hx @@ -0,0 +1,26 @@ +package lnx; + +import iron.data.Data; +import iron.data.Wasm; + +class MyTrait extends iron.Trait { + + public function new() { + super(); + notifyOnInit(init); + } + + function init() { + // Load wasm blob + Data.getBlob("main.wasm", blob -> { + // Create wasm module + var wasm = Wasm.instance(blob); + var rot = 0.0; + notifyOnUpdate(function() { + // Call function from wasm module + rot += wasm.exports.test(); + object.transform.setRotation(0, 0, rot); + }); + }); + } +} diff --git a/wasm_call/main.c b/wasm_call/main.c new file mode 100644 index 0000000..a8ec640 --- /dev/null +++ b/wasm_call/main.c @@ -0,0 +1,6 @@ +#define WASM_EXPORT __attribute__((visibility("default"))) + +WASM_EXPORT +float test() { + return 0.01f; +} diff --git a/wasm_call/wasm.png b/wasm_call/wasm.png new file mode 100644 index 0000000..3584791 Binary files /dev/null and b/wasm_call/wasm.png differ diff --git a/wasm_call/wasm_call.blend b/wasm_call/wasm_call.blend new file mode 100644 index 0000000..c7964cd Binary files /dev/null and b/wasm_call/wasm_call.blend differ diff --git a/wasm_trait_c/Bundled/main.wasm b/wasm_trait_c/Bundled/main.wasm new file mode 100644 index 0000000..ff295fa Binary files /dev/null and b/wasm_trait_c/Bundled/main.wasm differ diff --git a/wasm_trait_c/README.md b/wasm_trait_c/README.md new file mode 100644 index 0000000..bc91c69 --- /dev/null +++ b/wasm_trait_c/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/wasm \ No newline at end of file diff --git a/wasm_trait_c/main.c b/wasm_trait_c/main.c new file mode 100644 index 0000000..d8d8ace --- /dev/null +++ b/wasm_trait_c/main.c @@ -0,0 +1,17 @@ +#define WASM_EXPORT __attribute__((visibility("default"))) + +void notify_on_update(void* f); +int get_object(const char* name); +void set_transform(int object, float x, float y, float z, float rx, float ry, float rz, float sx, float sy, float sz); + +WASM_EXPORT void update() { + static float rot = 0.0f; + rot += 0.01f; + set_transform(get_object("Cube"), 0, 0, 0, 0, 0, rot, 1, 1, 1); +} + +// Include main function, Armory calls it when trait is instantiated +WASM_EXPORT int main() { + notify_on_update(update); + return 0; +} diff --git a/wasm_trait_c/wasm.png b/wasm_trait_c/wasm.png new file mode 100644 index 0000000..3584791 Binary files /dev/null and b/wasm_trait_c/wasm.png differ diff --git a/wasm_trait_c/wasm_trait_c.blend b/wasm_trait_c/wasm_trait_c.blend new file mode 100644 index 0000000..1a02ea4 Binary files /dev/null and b/wasm_trait_c/wasm_trait_c.blend differ diff --git a/wasm_trait_rust/Bundled/main.wasm b/wasm_trait_rust/Bundled/main.wasm new file mode 100644 index 0000000..f61aeb7 Binary files /dev/null and b/wasm_trait_rust/Bundled/main.wasm differ diff --git a/wasm_trait_rust/README.md b/wasm_trait_rust/README.md new file mode 100644 index 0000000..97e5678 --- /dev/null +++ b/wasm_trait_rust/README.md @@ -0,0 +1 @@ +https://github.com/leenkx3d/leenkx/wiki/wasm diff --git a/wasm_trait_rust/main.rs b/wasm_trait_rust/main.rs new file mode 100644 index 0000000..e89a549 --- /dev/null +++ b/wasm_trait_rust/main.rs @@ -0,0 +1,24 @@ +extern { + fn notify_on_update(f: extern fn() -> ()) -> (); + fn get_object(name: *const i8) -> i32; + fn set_transform(object: i32, x: f32, y: f32, z: f32, rx: f32, ry: f32, rz: f32, sx: f32, sy: f32, sz: f32) -> (); +} + +#[no_mangle] +pub extern "C" fn update() -> () { + unsafe { + let name = std::ffi::CString::new("Cube").unwrap(); + let object = get_object(name.as_ptr()); + static mut rot: f32 = 0.1; + rot += 0.01; + set_transform(object, 0.0, 0.0, 0.0, 0.0, 0.0, rot, 1.0, 1.0, 1.0); + } +} + +#[no_mangle] +pub extern "C" fn main() -> i32 { + unsafe { + notify_on_update(update); + } + return 0; +} diff --git a/wasm_trait_rust/wasm.png b/wasm_trait_rust/wasm.png new file mode 100644 index 0000000..3584791 Binary files /dev/null and b/wasm_trait_rust/wasm.png differ diff --git a/wasm_trait_rust/wasm_trait_rust.blend b/wasm_trait_rust/wasm_trait_rust.blend new file mode 100644 index 0000000..b4a06fd Binary files /dev/null and b/wasm_trait_rust/wasm_trait_rust.blend differ diff --git a/world_sun_direction/README.md b/world_sun_direction/README.md new file mode 100644 index 0000000..107ba74 --- /dev/null +++ b/world_sun_direction/README.md @@ -0,0 +1,6 @@ +Sky Texture synchronized with light direction. + +### Keyboard + +- `1` HosekWilkie +- `2` Nishita diff --git a/world_sun_direction/Sources/lnx/MyTrait.hx b/world_sun_direction/Sources/lnx/MyTrait.hx new file mode 100644 index 0000000..d1a5347 --- /dev/null +++ b/world_sun_direction/Sources/lnx/MyTrait.hx @@ -0,0 +1,42 @@ +package lnx; + +import leenkx.renderpath.HosekWilkie; +import leenkx.renderpath.Nishita; +import iron.Scene; +import iron.math.Vec4; +import iron.system.Input; + +class MyTrait extends iron.Trait { + public function new() { + super(); + notifyOnInit(function() { + + var world = Scene.active.world; + var center = Scene.active.getEmpty('Center'); + var light = Scene.active.lights[0]; + var keyboard = Input.getKeyboard(); + var model = 'hosekwilkie'; + notifyOnUpdate(function() { + + if (keyboard.started("1")) Scene.setActive('Scene_'+(model = 'hosekwilkie')); + if (keyboard.started("2")) Scene.setActive('Scene_'+(model = 'nishita')); + + center.transform.rotate(Vec4.xAxis(),0.02); + + // Sync sun direction + var v = light.look(); + world.raw.sun_direction[0] = v.x; + world.raw.sun_direction[1] = v.y; + world.raw.sun_direction[2] = v.z; + + switch model { + case 'hosekwilkie': HosekWilkie.recompute(world); + case 'nishita': Nishita.recompute(world); + } + + // Set world strength + // world.getGlobalProbe().raw.strength = 1.0; + }); + }); + } +} diff --git a/world_sun_direction/world_sun_direction.blend b/world_sun_direction/world_sun_direction.blend new file mode 100644 index 0000000..1e9e01b Binary files /dev/null and b/world_sun_direction/world_sun_direction.blend differ