From c3ea496ed0cd445fde80cea0c8c5209b1a56ba90 Mon Sep 17 00:00:00 2001 From: dlannan Date: Sat, 25 Jul 2026 15:20:59 +0930 Subject: [PATCH] Minor improvements --- bin/shaderbin/shader_gen.h | 245 +++++++++++-- data/config/rbuilder.log | 1 + editor/editor.lua | 2 +- {lua => engine}/cgltf.lua | 0 {lua/engine => engine}/gameobject.lua | 0 {lua => engine}/geometry/bins.lua | 0 {lua => engine}/geometry/meshes.lua | 0 {lua => engine}/gltfloader/geometry-utils.lua | 0 {lua => engine}/gltfloader/gltfloader.lua | 0 {lua => engine}/gltfloader/image-utils.lua | 0 engine/nuklear.lua | 203 +++++++++++ engine/renderer.lua | 337 ++++++++++++++++++ .../shaders}/base_texture.glsl | 0 .../engine => engine/shaders}/cgltf-sapp.glsl | 0 .../shaders}/cube_simple.glsl | 0 .../samples/offscreen_nuklear_sapp.lua | 6 +- tools/vfs/dirtools.lua | 8 +- 17 files changed, 755 insertions(+), 47 deletions(-) rename {lua => engine}/cgltf.lua (100%) rename {lua/engine => engine}/gameobject.lua (100%) rename {lua => engine}/geometry/bins.lua (100%) rename {lua => engine}/geometry/meshes.lua (100%) rename {lua => engine}/gltfloader/geometry-utils.lua (100%) rename {lua => engine}/gltfloader/gltfloader.lua (100%) rename {lua => engine}/gltfloader/image-utils.lua (100%) create mode 100644 engine/nuklear.lua create mode 100644 engine/renderer.lua rename {lua/engine => engine/shaders}/base_texture.glsl (100%) rename {lua/engine => engine/shaders}/cgltf-sapp.glsl (100%) rename {lua/engine => engine/shaders}/cube_simple.glsl (100%) diff --git a/bin/shaderbin/shader_gen.h b/bin/shaderbin/shader_gen.h index 4645723..2f8ceca 100644 --- a/bin/shaderbin/shader_gen.h +++ b/bin/shaderbin/shader_gen.h @@ -5,18 +5,37 @@ Generated by sokol-shdc (https://github.com/floooh/sokol-tools) Cmdline: - sokol-shdc -i ./projects/examples/samples/triangle-sapp.glsl -o F:\dev\luajit\repos\sokol-luajit\bin\shaderbin\shader_gen.h -l glsl410 -f sokol + sokol-shdc -i ./projects/examples/samples/offscreen-sapp.glsl -o F:\dev\luajit\repos\sokol-luajit\bin\shaderbin\shader_gen.h -l glsl410 -f sokol Overview: ========= - Shader program: 'triangle': - Get shader desc: triangle_shader_desc(sg_query_backend()); - Vertex Shader: vs - Fragment Shader: fs + Shader program: 'default': + Get shader desc: default_shader_desc(sg_query_backend()); + Vertex Shader: vs_default + Fragment Shader: fs_default Attributes: - ATTR_triangle_position => 0 - ATTR_triangle_color0 => 1 + ATTR_default_position => 0 + ATTR_default_normal => 1 + ATTR_default_texcoord0 => 2 + Shader program: 'offscreen': + Get shader desc: offscreen_shader_desc(sg_query_backend()); + Vertex Shader: vs_offscreen + Fragment Shader: fs_offscreen + Attributes: + ATTR_offscreen_position => 0 + ATTR_offscreen_normal => 1 Bindings: + Uniform block 'vs_params': + C struct: vs_params_t + Bind slot: UB_vs_params => 0 + Image 'tex': + Image type: SG_IMAGETYPE_2D + Sample type: SG_IMAGESAMPLETYPE_FLOAT + Multisampled: false + Bind slot: IMG_tex => 0 + Sampler 'smp': + Type: SG_SAMPLERTYPE_FILTERING + Bind slot: SMP_smp => 0 */ #if !defined(SOKOL_GFX_INCLUDED) #error "Please include sokol_gfx.h before shader_gen.h" @@ -28,73 +47,221 @@ #define SOKOL_SHDC_ALIGN(a) __attribute__((aligned(a))) #endif #endif -#define ATTR_triangle_position (0) -#define ATTR_triangle_color0 (1) +#define ATTR_default_position (0) +#define ATTR_default_normal (1) +#define ATTR_default_texcoord0 (2) +#define ATTR_offscreen_position (0) +#define ATTR_offscreen_normal (1) +#define UB_vs_params (0) +#define IMG_tex (0) +#define SMP_smp (0) +#pragma pack(push,1) +SOKOL_SHDC_ALIGN(16) typedef struct vs_params_t { + hmm_mat4 mvp; +} vs_params_t; +#pragma pack(pop) /* #version 410 + uniform vec4 vs_params[4]; layout(location = 0) in vec4 position; - layout(location = 0) out vec4 color; - layout(location = 1) in vec4 color0; + layout(location = 0) out vec4 nrm; + layout(location = 1) in vec4 normal; void main() { - gl_Position = position; - color = color0; + gl_Position = mat4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]) * position; + nrm = normal; } */ -static const uint8_t vs_source_glsl410[194] = { - 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x6c,0x61, - 0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20, - 0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74, - 0x69,0x6f,0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61, - 0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65, - 0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74, - 0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69, - 0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x0a, - 0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20, - 0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20, - 0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f, - 0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x7d,0x0a, - 0x0a,0x00, +static const uint8_t vs_offscreen_source_glsl410[280] = { + 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x75,0x6e, + 0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x73,0x5f,0x70,0x61, + 0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28, + 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e, + 0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a, + 0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20, + 0x3d,0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x6e,0x72, + 0x6d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69, + 0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20, + 0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61, + 0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f, + 0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x76,0x73, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70, + 0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72, + 0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d, + 0x73,0x5b,0x33,0x5d,0x29,0x20,0x2a,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e, + 0x3b,0x0a,0x20,0x20,0x20,0x20,0x6e,0x72,0x6d,0x20,0x3d,0x20,0x6e,0x6f,0x72,0x6d, + 0x61,0x6c,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; /* #version 410 layout(location = 0) out vec4 frag_color; - layout(location = 0) in vec4 color; + layout(location = 0) in vec4 nrm; void main() { - frag_color = color; + frag_color = vec4((nrm.xyz * 0.5) + vec3(0.5), 1.0); } */ -static const uint8_t fs_source_glsl410[135] = { +static const uint8_t fs_offscreen_source_glsl410[166] = { 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x6c,0x61, 0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20, 0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67, 0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c, 0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20, - 0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69, - 0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66, - 0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f, - 0x72,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, + 0x76,0x65,0x63,0x34,0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20, + 0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61, + 0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x28, + 0x6e,0x72,0x6d,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x35,0x29,0x20,0x2b, + 0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x35,0x29,0x2c,0x20,0x31,0x2e,0x30,0x29, + 0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; -static inline const sg_shader_desc* triangle_shader_desc(sg_backend backend) { +/* + #version 410 + + uniform vec4 vs_params[4]; + layout(location = 0) in vec4 position; + layout(location = 1) out vec2 uv; + layout(location = 2) in vec2 texcoord0; + layout(location = 0) out vec4 nrm; + layout(location = 1) in vec4 normal; + + void main() + { + mat4 _22 = mat4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]); + gl_Position = _22 * position; + uv = texcoord0; + nrm = _22 * normal; + } + +*/ +static const uint8_t vs_default_source_glsl410[400] = { + 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x75,0x6e, + 0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x73,0x5f,0x70,0x61, + 0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28, + 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e, + 0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a, + 0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20, + 0x3d,0x20,0x31,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76, + 0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f, + 0x6e,0x20,0x3d,0x20,0x32,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x74, + 0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74, + 0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x6f, + 0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x6c,0x61,0x79, + 0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31, + 0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c, + 0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b, + 0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x74,0x34,0x20,0x5f,0x32,0x32,0x20,0x3d,0x20, + 0x6d,0x61,0x74,0x34,0x28,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30, + 0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c, + 0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x76, + 0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,0x3b,0x0a,0x20,0x20, + 0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20, + 0x5f,0x32,0x32,0x20,0x2a,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a, + 0x20,0x20,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72, + 0x64,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6e,0x72,0x6d,0x20,0x3d,0x20,0x5f,0x32, + 0x32,0x20,0x2a,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, + +}; +/* + #version 410 + + uniform sampler2D tex_smp; + + layout(location = 1) in vec2 uv; + layout(location = 0) in vec4 nrm; + layout(location = 0) out vec4 frag_color; + + void main() + { + frag_color = vec4(texture(tex_smp, uv * vec2(20.0, 10.0)).xyz * fma(clamp(dot(nrm.xyz, vec3(0.57735025882720947265625, 0.57735025882720947265625, -0.57735025882720947265625)), 0.0, 1.0), 2.0, 0.25), 1.0); + } + +*/ +static const uint8_t fs_default_source_glsl410[379] = { + 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x75,0x6e, + 0x69,0x66,0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,0x44,0x20, + 0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x3b,0x0a,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74, + 0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69, + 0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75, + 0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20, + 0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x6c,0x61,0x79, + 0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30, + 0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f, + 0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69, + 0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63, + 0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x28,0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x75,0x76,0x20, + 0x2a,0x20,0x76,0x65,0x63,0x32,0x28,0x32,0x30,0x2e,0x30,0x2c,0x20,0x31,0x30,0x2e, + 0x30,0x29,0x29,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x66,0x6d,0x61,0x28,0x63,0x6c, + 0x61,0x6d,0x70,0x28,0x64,0x6f,0x74,0x28,0x6e,0x72,0x6d,0x2e,0x78,0x79,0x7a,0x2c, + 0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x35,0x37,0x37,0x33,0x35,0x30,0x32,0x35, + 0x38,0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37,0x32,0x36,0x35,0x36,0x32,0x35,0x2c, + 0x20,0x30,0x2e,0x35,0x37,0x37,0x33,0x35,0x30,0x32,0x35,0x38,0x38,0x32,0x37,0x32, + 0x30,0x39,0x34,0x37,0x32,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x2d,0x30,0x2e,0x35, + 0x37,0x37,0x33,0x35,0x30,0x32,0x35,0x38,0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37, + 0x32,0x36,0x35,0x36,0x32,0x35,0x29,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31, + 0x2e,0x30,0x29,0x2c,0x20,0x32,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x32,0x35,0x29,0x2c, + 0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, +}; +static inline const sg_shader_desc* default_shader_desc(sg_backend backend) { if (backend == SG_BACKEND_GLCORE) { static sg_shader_desc desc; static bool valid; if (!valid) { valid = true; - desc.vertex_func.source = (const char*)vs_source_glsl410; + desc.vertex_func.source = (const char*)vs_default_source_glsl410; desc.vertex_func.entry = "main"; - desc.fragment_func.source = (const char*)fs_source_glsl410; + desc.fragment_func.source = (const char*)fs_default_source_glsl410; desc.fragment_func.entry = "main"; desc.attrs[0].glsl_name = "position"; - desc.attrs[1].glsl_name = "color0"; - desc.label = "triangle_shader"; + desc.attrs[1].glsl_name = "normal"; + desc.attrs[2].glsl_name = "texcoord0"; + desc.uniform_blocks[0].stage = SG_SHADERSTAGE_VERTEX; + desc.uniform_blocks[0].layout = SG_UNIFORMLAYOUT_STD140; + desc.uniform_blocks[0].size = 64; + desc.uniform_blocks[0].glsl_uniforms[0].type = SG_UNIFORMTYPE_FLOAT4; + desc.uniform_blocks[0].glsl_uniforms[0].array_count = 4; + desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "vs_params"; + desc.images[0].stage = SG_SHADERSTAGE_FRAGMENT; + desc.images[0].image_type = SG_IMAGETYPE_2D; + desc.images[0].sample_type = SG_IMAGESAMPLETYPE_FLOAT; + desc.images[0].multisampled = false; + desc.samplers[0].stage = SG_SHADERSTAGE_FRAGMENT; + desc.samplers[0].sampler_type = SG_SAMPLERTYPE_FILTERING; + desc.image_sampler_pairs[0].stage = SG_SHADERSTAGE_FRAGMENT; + desc.image_sampler_pairs[0].image_slot = 0; + desc.image_sampler_pairs[0].sampler_slot = 0; + desc.image_sampler_pairs[0].glsl_name = "tex_smp"; + desc.label = "default_shader"; + } + return &desc; + } + return 0; +} +static inline const sg_shader_desc* offscreen_shader_desc(sg_backend backend) { + if (backend == SG_BACKEND_GLCORE) { + static sg_shader_desc desc; + static bool valid; + if (!valid) { + valid = true; + desc.vertex_func.source = (const char*)vs_offscreen_source_glsl410; + desc.vertex_func.entry = "main"; + desc.fragment_func.source = (const char*)fs_offscreen_source_glsl410; + desc.fragment_func.entry = "main"; + desc.attrs[0].glsl_name = "position"; + desc.attrs[1].glsl_name = "normal"; + desc.uniform_blocks[0].stage = SG_SHADERSTAGE_VERTEX; + desc.uniform_blocks[0].layout = SG_UNIFORMLAYOUT_STD140; + desc.uniform_blocks[0].size = 64; + desc.uniform_blocks[0].glsl_uniforms[0].type = SG_UNIFORMTYPE_FLOAT4; + desc.uniform_blocks[0].glsl_uniforms[0].array_count = 4; + desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "vs_params"; + desc.label = "offscreen_shader"; } return &desc; } diff --git a/data/config/rbuilder.log b/data/config/rbuilder.log index a9719b3..ead50f5 100644 --- a/data/config/rbuilder.log +++ b/data/config/rbuilder.log @@ -1 +1,2 @@ [Info] settings.load projectpath nil, using default settings. +[Info] panel.loadconfig: Loaded path - .\projects\cube_sapp\cube_sapp.slp diff --git a/editor/editor.lua b/editor/editor.lua index f464ab7..7197c0f 100644 --- a/editor/editor.lua +++ b/editor/editor.lua @@ -133,7 +133,7 @@ local function frame() local t = (sapp.sapp_frame_duration() * 60.0) local dt = sapp.sapp_frame_duration() - local ctx = nk.snk_new_frame() + local ctx = nk.snk_new_frame(false) if(engineState.ready == true and mainState.ctx == nil) then mainState.ctx = ctx ErrorCheck( pcall( engineState.init, w, h ) ) diff --git a/lua/cgltf.lua b/engine/cgltf.lua similarity index 100% rename from lua/cgltf.lua rename to engine/cgltf.lua diff --git a/lua/engine/gameobject.lua b/engine/gameobject.lua similarity index 100% rename from lua/engine/gameobject.lua rename to engine/gameobject.lua diff --git a/lua/geometry/bins.lua b/engine/geometry/bins.lua similarity index 100% rename from lua/geometry/bins.lua rename to engine/geometry/bins.lua diff --git a/lua/geometry/meshes.lua b/engine/geometry/meshes.lua similarity index 100% rename from lua/geometry/meshes.lua rename to engine/geometry/meshes.lua diff --git a/lua/gltfloader/geometry-utils.lua b/engine/gltfloader/geometry-utils.lua similarity index 100% rename from lua/gltfloader/geometry-utils.lua rename to engine/gltfloader/geometry-utils.lua diff --git a/lua/gltfloader/gltfloader.lua b/engine/gltfloader/gltfloader.lua similarity index 100% rename from lua/gltfloader/gltfloader.lua rename to engine/gltfloader/gltfloader.lua diff --git a/lua/gltfloader/image-utils.lua b/engine/gltfloader/image-utils.lua similarity index 100% rename from lua/gltfloader/image-utils.lua rename to engine/gltfloader/image-utils.lua diff --git a/engine/nuklear.lua b/engine/nuklear.lua new file mode 100644 index 0000000..21919be --- /dev/null +++ b/engine/nuklear.lua @@ -0,0 +1,203 @@ + +local nk = sg +local stb = require("stb") + +local ffi = require("ffi") + +-- -------------------------------------------------------------------------------------- + +local function checkstring(val) + local t = type(val) + if t == "string" then + return val + elseif t == "number" then + return tostring(val) + elseif t == "cdata" then + return ffi.string(val) + else + error("bad argument: string or number expected, got " .. t, 2) + end +end + +-- -------------------------------------------------------------------------------------- + +nuklear_renderer = {} + +-- -------------------------------------------------------------------------------------- + +nuklear_renderer.get_size = function() + local r = renderer.rect + -- print("get_size", r.w, r.h) + return r.w, r.h +end + +-- -------------------------------------------------------------------------------------- + +nuklear_renderer.set_clip_rect = function(x, y, w, h) + local canvas = renderer.canvas + local r = renderer.rect + local rect = nk.nk_rect(x + r.x, y + r.y, w, h) + -- print("set_clip_rect", rect.x, rect.y, rect.w, rect.h) + nk.nk_push_scissor(canvas, rect) +end + +-- -------------------------------------------------------------------------------------- + +nuklear_renderer.draw_rect = function(x, y, w, h, color) + local canvas = renderer.canvas + local r = renderer.rect + -- local ncol = nk.nk_rgba(color.r, color.g, color.b, color.a) + local ncol = nk.nk_rgba(color[1], color[2], color[3], color[4]) + -- print("draw_rect", x, y, w, h) + -- nk.nk_layout_space_begin(renderer.ctx, nk.NK_STATIC, r.w, 1) + -- nk.nk_layout_space_push(renderer.ctx, r) + nk.nk_fill_rect(canvas, nk.nk_rect( x+r.x, y+r.y, w, h), 0, ncol) + -- nk.nk_layout_space_end(renderer.ctx) +end + +-- -------------------------------------------------------------------------------------- + +nuklear_renderer.draw_text = function(font, text, x, y, color) + local canvas = renderer.canvas + -- local hcolor = nk.nk_rgba(color.r, color.g, color.b, color.a) + local hcolor = nk.nk_rgba(color[1], color[2], color[3], color[4]) + local r = renderer.rect + local w = font:get_width(text) + local h = font:get_height() + local rect = nk.nk_rect(x+r.x, y+r.y, w, h) + local font_handle = font.font.handle + local text = checkstring(text) + local text_len = #text + -- print("draw_text", x, y, text) + if(text == "CRLF" or #text == 0) then return x end + if(string.byte(text, -1, -1) == 10) then text_len = text_len - 1 end + -- nk.nk_layout_space_begin(renderer.ctx, nk.NK_STATIC, r.w, 1) + -- nk.nk_layout_space_push(renderer.ctx, r) + -- font:set_tab_width( font.tab_width ) + nk.nk_draw_text(canvas, rect, text, text_len, font_handle, hcolor, hcolor) + -- nk.nk_layout_space_end(renderer.ctx) + return w + x, h +end + +-- -------------------------------------------------------------------------------------- + +nuklear_renderer.load_image = function(filename, no_ui) + + local x = ffi.new("int[1]", {0}) + local y = ffi.new("int[1]", {0}) + local n = ffi.new("int[1]", {4}) + local data = stb.stbi_load(filename, x, y, n, 4) + if (data == nil) then error("[STB]: failed to load image: "..filename); return nil end + -- print("Original channels in file:", n[0]) + print("Image Loaded: "..filename.." Width: "..x[0].." Height: "..y[0].." Channels: "..n[0]) + + -- Auto free when data handles are released + ffi.gc(data, stb.stbi_image_free) + local pixformat = sg.SG_PIXELFORMAT_RGBA8 + + local sg_img_desc = ffi.new("sg_image_desc[1]", {}) + sg_img_desc[0].width = x[0] + sg_img_desc[0].height = y[0] + sg_img_desc[0].pixel_format = pixformat + sg_img_desc[0].sample_count = 1 + + sg_img_desc[0].data.subimage[0][0].ptr = data + sg_img_desc[0].data.subimage[0][0].size = x[0] * y[0] * 4 + + if(sg.sg_isvalid() == false) then return nil, sg_img_desc, data end + local new_img = sg.sg_make_image(sg_img_desc) + if(no_ui) then return new_img, sg_img_desc, data end + + -- // create a sokol-nuklear image object which associates an sg_image with an sg_sampler + local img_desc = ffi.new("snk_image_desc_t[1]") + img_desc[0].image = new_img + local snk_img = nk.snk_make_image(img_desc) + local nk_hnd = nk.snk_nkhandle(snk_img) + local nk_img = nk.nk_image_handle(nk_hnd); + + return nk_img, sg_img_desc +end + +-- -------------------------------------------------------------------------------------- + +nuklear_renderer.load_image_buffer = function( name, buf, bufsize, no_ui ) + + name = name or "image" + local x = ffi.new("int[1]", {0}) + local y = ffi.new("int[1]", {0}) + local n = ffi.new("int[1]", {4}) + local data = stb.stbi_load_from_memory(buf, bufsize, x, y, n, 4) + if (data == nil) then + print("[STB]: failed to load image: ", name) + return nil, nil + end + print("Original channels in file:", n[0]) + print("Image Buffer Loaded: "..name.." Width: "..x[0].." Height: "..y[0].." Channels: "..n[0]) + + local pixformat = sg.SG_PIXELFORMAT_RGBA8 + + local sg_img_desc = ffi.new("sg_image_desc[1]") + sg_img_desc[0].width = x[0] + sg_img_desc[0].height = y[0] + sg_img_desc[0].pixel_format = pixformat + sg_img_desc[0].sample_count = 1 + + sg_img_desc[0].data.subimage[0][0].ptr = data + sg_img_desc[0].data.subimage[0][0].size = x[0] * y[0] * 4 + + if(sg.sg_isvalid() == false) then return nil, sg_img_desc, data end + local new_img = sg.sg_make_image(sg_img_desc) + if(no_ui) then return new_img, sg_img_desc, data end + + -- // create a sokol-nuklear image object which associates an sg_image with an sg_sampler + local img_desc = ffi.new("snk_image_desc_t[1]") + img_desc[0].image = new_img + local snk_img = nk.snk_make_image(img_desc) + local nk_hnd = nk.snk_nkhandle(snk_img) + local nk_img = nk.nk_image_handle(nk_hnd); + + stb.stbi_image_free(data) + return nk_img, sg_img_desc +end + +-- -------------------------------------------------------------------------------------- + +nuklear_renderer.draw_image = function(img, x, y, w, h, color) + color = color or {0xff, 0xff, 0xff, 0xff} + local canvas = renderer.canvas + local r = renderer.rect + local rect = nk.nk_rect(x+r.x, y+r.y, w, h) + local icolor = nk.nk_rgba(color[1], color[2], color[3], color[4]) + nk.nk_draw_image(canvas, rect, img, icolor ) +end + +-- -------------------------------------------------------------------------------------- + +nuklear_renderer.set_cursor = function() + + if(renderer.ctx == nil) then return end + local cursor_name, rect = renderer.cursor.name, renderer.cursor.rect + local r = nk.nk_rect(rect.position.x, rect.position.y, rect.size.x, rect.size.y) + + nk.nk_layout_space_begin(renderer.ctx, nk.NK_STATIC, 27, 1) + nk.nk_layout_space_push(renderer.ctx, r) + if (nk.nk_widget_is_hovered(renderer.ctx) == true) then + + if(cursor_name == "arrow") then + nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_ARROW) + elseif(cursor_name == "ibeam") then + nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_TEXT) + elseif(cursor_name == "hsplit") then + nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_RESIZE_HORIZONTAL) + elseif(cursor_name == "sizeh") then + nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_RESIZE_HORIZONTAL) + elseif(cursor_name == "sizev") then + nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_RESIZE_VERTICAL) + end + else + nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_ARROW); + end + nk.nk_layout_space_end(renderer.ctx) +end + +-- -------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/engine/renderer.lua b/engine/renderer.lua new file mode 100644 index 0000000..8369267 --- /dev/null +++ b/engine/renderer.lua @@ -0,0 +1,337 @@ + +local stb = require("stb") +local nk = sg + +local utils = require("lua.utils") +-- require("engine.nuklear") + +local ffi = require("ffi") + +local tinsert = table.insert + +-- -------------------------------------------------------------------------------------- + +table.unpack = unpack + +-- -------------------------------------------------------------------------------------- + +local function checkstring(val) + local t = type(val) + if t == "string" then + return val + elseif t == "number" then + return tostring(val) + elseif t == "cdata" then + return ffi.string(val) + else + error("bad argument: string or number expected, got " .. t, 2) + end +end + +-- -------------------------------------------------------------------------------------- + +renderer = { + ctx = nil, + all_fonts = {}, + cursor = { name = "arrow", rect = { position = {x=0,y=0}, size ={x=1,y=1} } }, +} + +renderer.font = { + ctx = nil, +} + +-- -------------------------------------------------------------------------------------- + +local atlas = ffi.new("struct nk_font_atlas[1]") +local fonts = {} + +-- -------------------------------------------------------------------------------------- + +local master_img_width = ffi.new("int[1]", 2048) +local master_img_height = ffi.new("int[1]", 4096) + +-- -------------------------------------------------------------------------------------- + +local function adjust_glyph(font_handle, unicode, width) + + local font = ffi.cast("struct nk_font *", font_handle.ptr) + local g = font.glyphs[unicode] + g.xadvance = width +end + +-- -------------------------------------------------------------------------------------- + +local function get_glyph_xadvance(font_handle, unicode) + + local font = ffi.cast("struct nk_font *", font_handle.ptr) + local g = font.glyphs[unicode] + return g.xadvance +end + +-- -------------------------------------------------------------------------------------- + +local function find_glyph(font, codepoint) + local glyph_ptr = font.glyphs + while glyph_ptr ~= nil and glyph_ptr[0].codepoint ~= 0 do + if tonumber(glyph_ptr[0].codepoint) == codepoint then + return glyph_ptr + end + glyph_ptr = glyph_ptr + 1 + end + return nil +end + +-- -------------------------------------------------------------------------------------- + +local function fix_tab_glyph(glyph, space) + + glyph[0].xadvance = space * 4 + glyph[0].w, glyph[0].h = 0, 0 + glyph[0].x0, glyph[0].y0, glyph[0].x1, glyph[0].y1 = 0, 0, 0, 0 + glyph[0].u0, glyph[0].v0, glyph[0].u1, glyph[0].v1 = 0, 0, 0, 0 +end + +-- -------------------------------------------------------------------------------------- + +local rune_ranges = ffi.new("nk_rune[9]", { + 0x0009, 0x000A, -- tab + 0x0020, 0x00FF, -- basic Latin + Latin-1 + 0x2500, 0x2BFF, -- box-drawing, arrows + 0xE000, 0xF8FF, -- private use / Nerd Font symbols + 0 +}) + +local fa_rune_ranges = ffi.new("nk_rune[9]", { + 0xE000, 0xF8FF, -- private use / Nerd Font symbols + 0 +}) + +-- -------------------------------------------------------------------------------------- + +local function font_loader( atlas, font_file, font_size) + + local config = nk.nk_font_config(font_size) + -- Special case where the glyphs need to be default + if(string.match(font_file, "icons.ttf$")) then + config.range = nk.nk_font_default_glyph_ranges() + elseif(string.match(font_file, "fontawesome")) then + config.range = fa_rune_ranges + else + config.range = rune_ranges + end + -- config.merge_mode = nk.nk_false + local newfont = nk.nk_font_atlas_add_from_file(atlas, font_file, font_size, config) + + -- local image = nk.nk_font_atlas_bake(atlas, master_img_width, master_img_height, nk.NK_FONT_ATLAS_RGBA32) + return nil, newfont +end + +-- -------------------------------------------------------------------------------------- + +local function font_atlas_img( image, debug ) + local sg_img_desc = ffi.new("sg_image_desc[1]") + sg_img_desc[0].width = master_img_width[0] + sg_img_desc[0].height = master_img_height[0] + sg_img_desc[0].pixel_format = sg.SG_PIXELFORMAT_RGBA8 + sg_img_desc[0].sample_count = 1 + + sg_img_desc[0].data.subimage[0][0].ptr = image + sg_img_desc[0].data.subimage[0][0].size = master_img_width[0] * master_img_height[0] * 4 + local new_img = sg.sg_make_image(sg_img_desc) + + -- // create a sokol-nuklear image object which associates an sg_image with an sg_sampler + local img_desc = ffi.new("snk_image_desc_t[1]") + img_desc[0].image = new_img + + local snk_img = nk.snk_make_image(img_desc) + local nk_hnd = nk.snk_nkhandle(snk_img) + + if(debug) then + -- Dump the atlas to check it. + stb.stbi_write_png( "data/fonts/atlas_font.png", master_img_width[0], master_img_height[0], 4, image, master_img_width[0] * 4) + end + + return nk_hnd +end + +-- -------------------------------------------------------------------------------------- +-- Load font into a font pool - need to regen font atlas for this +local function load_font(font_path, font_size) + + if(font_size == 0.0) then font_size = 16.0 end + local ctx = renderer.ctx + if(ctx == nil) then return nil end + -- Reset image + local image = nil + local new_font = nil + + nk.nk_font_atlas_init_default(atlas) + nk.nk_font_atlas_begin(atlas) + + -- image = nk.nk_font_atlas_bake(atlas, master_img_width, master_img_height, nk.NK_FONT_ATLAS_RGBA32) + + -- Reload previous fonts. + for i, font in ipairs(fonts) do + image, fonts.font = font_loader(atlas, font.path, font.size) + + local glyph = find_glyph(font.font, 9) + local space = get_glyph_xadvance(font.font.handle.userdata, 32) + if(glyph) then fix_tab_glyph(glyph, space) end + + -- atlas[0].config.range = rune_ranges -- nk.nk_font_default_glyph_ranges() + end + + -- local cfg = ffi.new("struct nk_font_config[1]", {nk.nk_font_config(font_size)}) + -- cfg[0].merge_mode = nk.nk_true + -- cfg.coord_type = nk.NK_COORD_PIXEL + + image, new_font = font_loader(atlas, font_path, font_size) + image = nk.nk_font_atlas_bake(atlas, master_img_width, master_img_height, nk.NK_FONT_ATLAS_RGBA32) + local glyph = find_glyph(new_font, 9) + local space = get_glyph_xadvance(new_font.handle.userdata, 32) + if(glyph) then fix_tab_glyph(glyph, space) end + + + local nk_img = font_atlas_img(image, true) + nk.nk_font_atlas_end(atlas, nk_img, nil) + nk.nk_font_atlas_cleanup(atlas) + + nk.nk_style_load_all_cursors(ctx, atlas[0].cursors) + nk.nk_style_set_font(ctx, new_font.handle) + + local tab_size = get_glyph_xadvance(new_font.handle.userdata, 9) + + -- print(master_img_width[0], master_img_height[0], tab_size) + local new_font_tbl = { tab_width = tab_size, font = new_font, path = font_path, size = font_size, cfg = nil } + tinsert(fonts, new_font_tbl) + + return new_font_tbl +end + +-- -------------------------------------------------------------------------------------- + +renderer.get_font = function( font_id ) + return renderer.all_fonts[font_id] +end + +-- -------------------------------------------------------------------------------------- + +renderer.font.load = function(path, size) + local new_font = load_font(path, size) + if(new_font == nil) then return nil end + new_font.set_tab_width = function(self, width) + if(width == self.tab_width) then return end + adjust_glyph( self.font.handle.userdata, 9, width ) + self.tab_width = width + end + new_font.get_tab_width = function(self, width) + return self.tab_width + end + new_font.get_width = function(self, text) + if(text==nil) then print(debug.traceback()) end + local text = checkstring(text) + return self.font.handle.width(self.font.handle.userdata, self.font.handle.height, text, #text) + end + new_font.get_height = function(self) return self.font.handle.height end + new_font.get_size = function(self) return self.size end + new_font.set_size = function(self, size) self.size = size end + new_font.get_path = function(self) return self.path end + new_font.get_handle = function(self) return self.font.handle end + + local font_id = #renderer.all_fonts+1 + new_font.get_id = function(self) return font_id end + + tinsert(renderer.all_fonts, new_font) + return setmetatable(new_font, { __index = new_font }) +end + +-- -------------------------------------------------------------------------------------- + +renderer.show_debug = function(enable) +end + +-- -------------------------------------------------------------------------------------- + +renderer.get_size = function() + return nuklear_renderer.get_size() +end + +-- -------------------------------------------------------------------------------------- +-- Not really needed +renderer.begin_frame = function() +end + +-- -------------------------------------------------------------------------------------- +-- Hrm.. needed? +renderer.end_frame = function() + +end + +-- -------------------------------------------------------------------------------------- + +renderer.set_clip_rect = function(x, y, w, h) + nuklear_renderer.set_clip_rect(x, y, w, h) +end + +-- -------------------------------------------------------------------------------------- + +renderer.draw_rect = function(x, y, w, h, color) + nuklear_renderer.draw_rect(x, y, w, h, color) +end + +-- -------------------------------------------------------------------------------------- + +renderer.draw_text = function(font, text, x, y, color) + return nuklear_renderer.draw_text(font, text, x, y, color) +end + +-- -------------------------------------------------------------------------------------- + +renderer.draw_cursor = function() + local icolor = nk.nk_rgba(0xff, 0xff, 0xff, 0xff) + local r = nk.nk_rect(renderer.ctx.input.mouse.pos.x, renderer.ctx.input.mouse.pos.y, 12, 19) + nk.nk_draw_image(renderer.canvas, r, renderer.ctx.style.cursor_active.img, icolor) +end + +-- -------------------------------------------------------------------------------------- + +renderer.load_image = function(filename, no_ui) + local img, img_info = nuklear_renderer.load_image(filename, no_ui) + return img, img_info +end + +-- -------------------------------------------------------------------------------------- + +renderer.load_image_buffer = function(name, buf, bufsize, no_ui) + local img, img_info = nuklear_renderer.load_image_buffer(name, buf, bufsize, no_ui) + return img, img_info +end + +-- -------------------------------------------------------------------------------------- + +renderer.draw_image = function(image, x, y, w, h) + return nuklear_renderer.draw_image(image, x, y, w, h) +end + +-- -------------------------------------------------------------------------------------- + +renderer.load_model = function(filename) + return threed_renderer.load_model(filename) +end + +-- -------------------------------------------------------------------------------------- + +renderer.draw_model = function(model, x, y, w, h) + + return threed_renderer.draw_model(model, x, y, w, h) +end + +-- -------------------------------------------------------------------------------------- + +renderer.set_cursor = function() + nuklear_renderer.set_cursor() +end + +-- -------------------------------------------------------------------------------------- + +renderer.find_glyph = find_glyph \ No newline at end of file diff --git a/lua/engine/base_texture.glsl b/engine/shaders/base_texture.glsl similarity index 100% rename from lua/engine/base_texture.glsl rename to engine/shaders/base_texture.glsl diff --git a/lua/engine/cgltf-sapp.glsl b/engine/shaders/cgltf-sapp.glsl similarity index 100% rename from lua/engine/cgltf-sapp.glsl rename to engine/shaders/cgltf-sapp.glsl diff --git a/lua/engine/cube_simple.glsl b/engine/shaders/cube_simple.glsl similarity index 100% rename from lua/engine/cube_simple.glsl rename to engine/shaders/cube_simple.glsl diff --git a/projects/examples/samples/offscreen_nuklear_sapp.lua b/projects/examples/samples/offscreen_nuklear_sapp.lua index ffca9ef..17f4492 100644 --- a/projects/examples/samples/offscreen_nuklear_sapp.lua +++ b/projects/examples/samples/offscreen_nuklear_sapp.lua @@ -337,9 +337,9 @@ local function frame() -- // and the display-pass, rendering a rotating textured sphere which uses the -- // previously rendered offscreen render-target as texture - local w = sapp.sapp_width() - local h = sapp.sapp_height() - def_vs_params[0].mvp = compute_mvp(-state[0].rx * 0.25, state[0].ry * 0.25, w/h, 3.0) + -- local w = sapp.sapp_width() + -- local h = sapp.sapp_height() + def_vs_params[0].mvp = compute_mvp(0.0, 0.0, 1.0, 3.0) -- local pass = ffi.new("sg_pass[1]") -- pass[0].action = state[0].display.pass_action diff --git a/tools/vfs/dirtools.lua b/tools/vfs/dirtools.lua index 690c733..b1dbbd6 100644 --- a/tools/vfs/dirtools.lua +++ b/tools/vfs/dirtools.lua @@ -206,11 +206,11 @@ else if(path == nil) then return nil end - run_popen("file "..path, "r", function(fh) + run_popen("file "..path, function(fh) local res = fh:read("*a") local folder = string.match(res, ".-: directory$") return (folder ~= nil) - end) + end, "r") return nil end end @@ -363,9 +363,9 @@ dirtools.get_folderslist = function(path, cache_update) table.insert(files, 1, { name = ".." }) -- Fill with temp file list of dir /b - local res = run_popen(string.format(allfolders_cmd, path), "r", function(fh) + local res = run_popen(string.format(allfolders_cmd, path), function(fh) return fh:read("*a") - end) + end, "r") if(res == nil) then return files end for f in string.gmatch(res, "(.-)\n") do