Merge pull request 'update' (#1) from Onek8/Leenkx_Examples:main into main
Reviewed-on: LeenkxTeam/Leenkx_Examples#1
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
*/build*
|
||||||
|
*/*.blend?
|
||||||
|
*/Sources/Main.hx
|
||||||
|
*/Sources/arm/node/*
|
||||||
|
*.pyc
|
||||||
|
*.DS_Store
|
||||||
|
khafile.js
|
||||||
|
node_update_failure.*
|
||||||
|
.vscode/
|
||||||
|
config.arm
|
||||||
|
_*/
|
||||||
7
LICENSE.md
Normal file
@ -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.
|
||||||
BIN
RaycastRay/RaycastRay.blend
Normal file
BIN
ScreenToWorld_WorldToScreen/ScreenToWorld_WorldToScreen.blend
Normal file
1
animation_actions/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Press keyboard `1`, `2`, `3` to change the animation action
|
||||||
39
animation_actions/Sources/lnx/ActionPlayer.hx
Normal file
@ -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!");
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
animation_actions/animation_actions.blend
Normal file
0
animation_blend/Bundled/canvas/MyCanvas.files
Normal file
1
animation_blend/Bundled/canvas/MyCanvas.json
Normal file
@ -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"}
|
||||||
1
animation_blend/Bundled/canvas/_themes.json
Normal file
@ -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}]
|
||||||
1
animation_blend/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Hold keyboard `W`, `S` to blend between animations
|
||||||
30
animation_blend/Sources/lnx/MyTrait.hx
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
animation_blend/animation_blend.blend
Normal file
3
animation_bonechild/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Hand object is parented to armature bone
|
||||||
|
- Sword is parented to Hand object
|
||||||
|
- Press `X` to swap weapons
|
||||||
40
animation_bonechild/Sources/lnx/SwapWeapon.hx
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
animation_bonechild/animation_bonechild.blend
Normal file
3
animation_instanced/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Use instancing for fast rendering of linked object duplicates.
|
||||||
|
|
||||||
|
https://github.com/leenkx3d/leenkx/wiki/instancing
|
||||||
BIN
animation_instanced/animation_instanced.blend
Normal file
3
animation_movebone/README.md
Normal file
@ -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.
|
||||||
46
animation_movebone/Sources/lnx/MoveBoneFK.hx
Normal file
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
28
animation_movebone/Sources/lnx/MoveBoneIK.hx
Normal file
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
animation_movebone/animation_movebone.blend
Normal file
BIN
animation_timeline/animation_timeline.blend
Normal file
BIN
animation_uv/animation_uv.blend
Normal file
14
call_hx/Bundled/my_plugin.js
Normal file
@ -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);
|
||||||
|
}
|
||||||
2
call_hx/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Check console.
|
||||||
|
https://github.com/leenkx3d/leenkx/wiki/js
|
||||||
11
call_hx/Sources/lnx/EvalJS.hx
Normal file
@ -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());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
24
call_hx/Sources/lnx/Plugin.hx
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
call_hx/call_hx.blend
Normal file
6
call_js/README.md
Normal file
@ -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
|
||||||
33
call_js/Sources/lnx/CallJS.hx
Normal file
@ -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");');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
call_js/call_js.blend
Normal file
1
debug_draw/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
To see debug drawing, `Leenkx Project - Debug Console` option has to be enabled.
|
||||||
24
debug_draw/Sources/lnx/MyTrait.hx
Normal file
@ -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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
debug_draw/debug_draw.blend
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
38
dev_logicnode/Libraries/mynodes/blender.py
Normal file
@ -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()
|
||||||
BIN
dev_logicnode/dev_logicnode.blend
Normal file
2
ease/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- https://api.leenkx3d.org/iron/system/Ease.html
|
||||||
|
- https://api.leenkx3d.org/iron/system/Tween.html
|
||||||
33
ease/Sources/lnx/TweenTest.hx
Normal file
@ -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)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
ease/ease.blend
Normal file
0
file_read/Bundled/canvas/MyCanvas.files
Normal file
1
file_read/Bundled/canvas/MyCanvas.json
Normal file
@ -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"}
|
||||||
1
file_read/Bundled/canvas/_themes.json
Normal file
@ -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}]
|
||||||
3
file_read/Bundled/my_file.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"my_text": "Hello from json!"
|
||||||
|
}
|
||||||
1
file_read/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Loads a json file from the `Bundled/` directory.
|
||||||
34
file_read/Sources/lnx/ReadFile.hx
Normal file
@ -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;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
file_read/file_read.blend
Normal file
4
file_storage/README.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Increments a number every time you start the application.
|
||||||
|
Check console.
|
||||||
|
|
||||||
|
https://api.leenkx3d.org/kha/Storage.html
|
||||||
55
file_storage/Sources/lnx/StorageTest.hx
Normal file
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
file_storage/file_storage.blend
Normal file
1
file_write/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://github.com/leenkx3d/leenkx/wiki/reference#write-json
|
||||||
28
file_write/Sources/lnx/WriteFile.hx
Normal file
@ -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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
file_write/file_write.blend
Normal file
BIN
game_bowling/Assets/floor_base.jpg
Normal file
|
After Width: | Height: | Size: 822 KiB |
BIN
game_bowling/Assets/floor_nor.jpg
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
game_bowling/Assets/floor_occ.jpg
Normal file
|
After Width: | Height: | Size: 966 KiB |
BIN
game_bowling/Assets/floor_rough.jpg
Normal file
|
After Width: | Height: | Size: 271 KiB |
BIN
game_bowling/Assets/keys.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
game_bowling/Assets/menu.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
game_bowling/Assets/roll.wav
Normal file
BIN
game_bowling/Assets/strike.wav
Normal file
BIN
game_bowling/Assets/ui_exit.png
Normal file
|
After Width: | Height: | Size: 698 B |
BIN
game_bowling/Assets/ui_play.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
game_bowling/Assets/ui_refresh.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
3
game_bowling/Bundled/canvas/GameCanvas.files
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
../../Assets/ui_exit.png
|
||||||
|
../../Assets/ui_refresh.png
|
||||||
|
../../Assets/keys.png
|
||||||
1
game_bowling/Bundled/canvas/GameCanvas.json
Normal file
@ -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"}
|
||||||
2
game_bowling/Bundled/canvas/MenuCanvas.files
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
../../Assets/ui_play.png
|
||||||
|
../../Assets/menu.jpg
|
||||||
1
game_bowling/Bundled/canvas/MenuCanvas.json
Normal file
@ -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"}
|
||||||
1
game_bowling/Bundled/canvas/_themes.json
Normal file
@ -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}]
|
||||||
1
game_bowling/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Keyboard `space` to bowl
|
||||||
55
game_bowling/Sources/lnx/BallTrait.hx
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
24
game_bowling/Sources/lnx/PinTrait.hx
Normal file
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
game_bowling/game_bowling.blend
Normal file
BIN
game_bowling/pin.blend
Normal file
BIN
game_bowling/textures/bowling.jpg
Normal file
|
After Width: | Height: | Size: 109 KiB |
0
game_endlessrun/Bundled/canvas/MyCanvas.files
Normal file
1
game_endlessrun/Bundled/canvas/MyCanvas.json
Normal file
@ -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":[]}
|
||||||
31
game_endlessrun/Sources/lnx/GemTrait.hx
Normal file
@ -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 + "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
22
game_endlessrun/Sources/lnx/PlayerController.hx
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
51
game_endlessrun/Sources/lnx/SceneBuilder.hx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package lnx;
|
||||||
|
|
||||||
|
class SceneBuilder extends iron.Trait {
|
||||||
|
|
||||||
|
var dist = 0.0;
|
||||||
|
var tileNum = 0;
|
||||||
|
var tilesVisible = 14;
|
||||||
|
var tiles:Array<iron.object.Object> = [];
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
game_endlessrun/game_endless.blend
Normal file
BIN
game_endlessrun/grid.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
0
graphics_settings/Bundled/canvas/MyCanvas.files
Normal file
1
graphics_settings/Bundled/canvas/MyCanvas.json
Normal file
@ -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"}
|
||||||
1
graphics_settings/Bundled/canvas/_themes.json
Normal file
@ -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}]
|
||||||
20
graphics_settings/Bundled/config.lnx
Normal file
@ -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
|
||||||
|
}
|
||||||
3
graphics_settings/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
To generate config.lnx file, enable `Leenkx Project - Write Config`.
|
||||||
|
|
||||||
|
https://api.leenkx3d.org/leenkx/data/Config.html
|
||||||
71
graphics_settings/Sources/lnx/MyTrait.hx
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
graphics_settings/graphics_settings.blend
Normal file
3
input_mouselock/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Keyboard `Escape` to toggle mouse lock.
|
||||||
|
|
||||||
|
https://api.leenkx3d.org/iron/system/Mouse.html
|
||||||
28
input_mouselock/Sources/lnx/LockTrait.hx
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
input_mouselock/input_mouselock.blend
Normal file
38
input_multitouch/Sources/lnx/TouchTrait.hx
Normal file
@ -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) {}
|
||||||
|
}
|
||||||
BIN
input_multitouch/input_multitouch.blend
Normal file
20
input_sensor/Sources/lnx/SensorTrait.hx
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
input_sensor/input_sensor.blend
Normal file
6
instancing/README.md
Normal file
@ -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
|
||||||
BIN
instancing/instancing.blend
Normal file
BIN
light_area/checker.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |