diff --git a/bin/data/config.json b/bin/data/config.json new file mode 100644 index 00000000..1e253eea --- /dev/null +++ b/bin/data/config.json @@ -0,0 +1,397 @@ +{ + "engine": { + "scenes": { + "start": "SourceEngine", + "matrix": { "reverseInfinite": true }, + "meshes": { "interleaved": false }, + "lights": { "enabled": true, + "useLightmaps": true, + "max": 32, + "shadows": { + "enabled": true, + "update": 4, + "max": 8, + "samples": 4 + }, + "bloom": { + "scale": 1.0, + "strength": 0.125, + "sigma": 0.8, + "samples": 5, + "threshold": 1.0 + } + }, + "textures": { + "max": { + "2D": 1024, + "cube": 1024, + "3D": 128 + } + }, + "vxgi": { + "limiter": 0.125, + // "limiter": 0.125, + "size": 192, + "dispatch": 8, + "cascades": 3, + "cascadePower": 1.5, + "granularity": 12, + "voxelizeScale": 1, + "occlusionFalloff": 2, + "traceStartOffsetFactor": 1, + "shadows": 0, + "extents": { + "min": [ -4, -4, -4 ], + "max": [ 4, 4, 4 ] + } + }, + "rt": { + // "size": [ 1280, 720 ], + "full": false, + "filter": "nearest", + "defaultRayBounds": [ 0.75, 256.0 ], + "alphaTestOffset": 0.05, + "samples": 1, + "paths": 2, + "frameAccumulationMinimum": 0, + "readyTimer": 3 + } + }, + "graph": { + "initial buffer elements": 1024 + }, + "ext": { + "vulkan": { + "version": 1.3, + "validation": { + "enabled": false, + "messages": false, + "checkpoints": false, + "filters": [ + "0x71500fba" // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup) + ,"0xe5d1743c" // VUID-vkCmdDispatch-None-02699 (problem when using VXGI) + + // ,"0x141cb623" // UNASSIGNED-Threading-MultipleThreads ("false-positive" multithreading) + + /* + "0x609a13b" // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls) + ,"0x35d7ea98" // VUID-vkUpdateDescriptorSets-None-03047 (bitches without VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT or VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT) + ,"0x8e1000ad" // VUID-vkCmdDrawIndexedIndirect-None-04008 (bitches without nullDescriptor) + ,"0x9dd97212" // VUID-vkCmdDrawIndexedIndirect-None-02721 (bitches without nullDescriptor) + ,"0x36481fcb" // VUID-vkCmdBindVertexBuffers-pBuffers-04001 (bitches without nullDescriptor) + */ + // ,"0x4dae5635" // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout + ] + }, + "framebuffer": { + "msaa": 1, + "size": 1 + // "size": [ 640, 480, "NEAREST" ] + // "size": [ 1280, 720 ] + // "size": [ 960, 540 ] + // "size": [ 640, 480 ] + }, + "gpu": 7817, // 2060 + // "gpu": 29631, // 6800XT + "experimental": { + "rebuild on tick begin": false, + "batch queue submissions": true, + "dedicated thread": false, + "memory budget": false + }, + "invariant": { + "default stage buffers": true, + "default defer buffer destroy": true, + "default command buffer immediate": true, + "multithreaded recording": true + }, + "pipelines": { + "deferred": true, + "vsync": true, + "hdr": true, + "vxgi": true, + "culling": true, + "bloom": true, + "rt": false, + "fsr": false, + "postProcess": false // "postProcess.chromab" // false + }, + "formats": { + "depth": "D32_SFLOAT", + "color": "R16G16B16A16_SFLOAT", // "R32G32B32A32_SFLOAT", + "normal": "R16G16B16A16_SFLOAT", + "position": "R16G16B16A16_SFLOAT" + }, + "versions": { + "1.0": { + "extensions": { + "instance": [], + "device": [ + "VK_KHR_swapchain" + ] + }, + "features": [ + "shaderDrawParameters", + "multiDrawIndirect", + "fillModeNonSolid", + "wideLines", + "independentBlend", + "deviceCoherentMemory", + "robustBufferAccess", + "samplerAnisotropy", + "sampleRateShading" + ], + "featureChain": [] + }, + "1.1": { + "extensions": { + "instance": [ + "VK_KHR_get_physical_device_properties2" + ,"VK_KHR_get_surface_capabilities2" + ], + "device": [ + "VK_EXT_memory_budget" + ,"VK_EXT_descriptor_indexing" + ,"VK_KHR_buffer_device_address" + ,"VK_NV_device_diagnostic_checkpoints" + ] + }, + "features": [ + "nullDescriptor" + ,"fragmentStoresAndAtomics" + ,"geometryShader" + ,"multiViewport" + ,"shaderInt16" + ,"shaderFloat16" + ,"shaderInt64" + ,"shaderFloat64" + ,"shaderSubgroupClock" + ,"shaderSampledImageArrayDynamicIndexing" + ,"shaderStorageImageArrayDynamicIndexing" + ,"shaderStorageImageMultisample" + + ,"shaderSampledImageArrayNonUniformIndexing" + ,"shaderStorageImageArrayNonUniformIndexing" + + ,"descriptorIndexing" + ,"bufferDeviceAddress" + ], + "featureChain": [ + "physicalDevice2" + ,"shaderDrawParameters" + ,"robustness" + ,"shaderClock" + + ,"descriptorIndexing" + ,"bufferDeviceAddress" + ] + }, + "1.2": { + "extensions": { + "instance": [ + "VK_KHR_get_physical_device_properties2", + "VK_KHR_get_surface_capabilities2" + ], + "device": [ + "VK_KHR_deferred_host_operations" + ,"VK_EXT_shader_viewport_index_layer" + ,"VK_KHR_spirv_1_4" + ,"VK_KHR_shader_float_controls" + ,"VK_KHR_shader_clock" + ,"VK_EXT_subgroup_size_control" + ,"VK_KHR_acceleration_structure" + ,"VK_KHR_ray_tracing_pipeline" + ,"VK_KHR_ray_query" + + // ,"VK_AMD_shader_explicit_vertex_parameter" + // ,"VK_KHR_fragment_shader_barycentric" + ] + }, + "features": [ + "hostQueryReset", + + "runtimeDescriptorArray", + "descriptorBindingVariableDescriptorCount", + + "shaderOutputViewportIndex", + "shaderOutputLayer" + ], + "featureChain": [ + "physicalDeviceVulkan12" + // for advanced gbuffer + ,"fragmentShaderBarycentric" + // for ray-tracing + ,"rayTracingPipeline" + ,"rayQuery" + ,"accelerationStructure" + // for FSR2 + ,"subgroupSizeControl" + ] + }, + "1.3": { + "extensions": { + "instance": [], + "device": [] + }, + "features": [], + "featureChain": [] + } + } + }, + "opengl": { + "validation": { "enabled": false }, + "framebuffer": { "size": 1, "msaa": 1 }, + "experimental": { + "rebuild on tick begin": true + }, + "pipelines": { + "culling": true + }, + "experimental": { + "rebuild on tick begin": true + }, + "invariant": { + "multithreaded recording": false + }, + "formats": { + "depth": "D32_SFLOAT", + "color": "R8G8B8A8_UNORM", // "R32G32B32A32_SFLOAT", + "normal": "R16G16B16A16_SFLOAT", + "position": "R16G16B16A16_SFLOAT" + }, + "features": [], + "extensions": { "instance": [], "device": [] } + }, + "lua": { + "enabled": true, + "main": "/main.lua", + "modules": { + "json": "/json.lua" + } + }, + "json": { + "encoding": "msgpack", + "compression": "gz" + }, + "imgui": { + "enabled": true + }, + "fsr": { + "enabled": true, + "sharpness": 1, + "jitter scale": 0.0625, + "preset": "native" // native (1x), quality (1.5x), balanced (1.7x), performance (2.0x), ultra (3.0x) + }, + "reactphysics": { + "timescale": 0.01666666666, + "interpolate": false, + "gravity": { + "mode": "universal", + "constant": 6.67408e-11 + }, + "debug draw": { + "enabled": false, + "line width": 8, + // "layer": "Gui", + "rate": 0.0125 + } + }, + "vr" : { + "enable" : false, + "manifest": "./data/openvr_manifest.json", + "swap eyes": false, + "dominant eye": 0, + "scale": 1.0 + }, + "ultralight": { "enabled": true, "scale": 1.5 }, + "discord": { "enabled": false } + }, + "audio": { + "mute": false, + "buffers": { + "size": 32768, + "count": 4 + }, + "volumes": { + "sfx": 0.35, + "bgm": 0.15, + "voice": 1.0 + }, + "streams by default": true + }, + "memory pool": { + "enabled": true, + "subPools": true, + "alignment": 64, + "override": false, + "size": "512 MiB", + "pools": { + "entity": "128 MiB", + "userdata": "128 MiB", + "component": "128 MiB" + } + }, + "render modes": { "gui": true, "deferred": true }, + "limiters": { + "deltaTime": 5, + "framerate": "auto" + }, + "threads": { + "workers" : "auto", + "frame limiter": 0 // "auto" + }, + "debug": { + "framerate": { + "print": true, + "every": 2 + }, + "garbage collection": { + "enabled": true, + "mode": 1, + "rate": 4, + "announce": true + }, + "entity": { + "delete children on destroy": false, + "delete components on destroy": false + }, + "userdata": { + "auto destruct": true, + "auto validate": false + }, + "loader": { + "assert": true + }, + "hooks": { + "defer lazy calls": true + }, + "scene": { + "print task calls": false + } + } + }, + "window" : { + "terminal" : { + "ncurses" : false, + "visible" : true + }, + "keyboard" : { + "repeat" : false + }, + "mouse" : { + "visible" : true, + "center" : false, + "sensitivity": [ 2, 2 ], + "smoothing": [ 4, 4 ] + }, + "mode" : "windowed", // fullscreen, borderless, windowed + "icon" : "./data/textures/icon.png", + // "size" : [ 1920, 1080 ], + "size" : [ 1280, 720 ], + // "size" : [ 960, 540 ], + // "size" : [ 640, 480 ], + // "size" : [ 256, 224 ], + "title" : "Grimgram", + "visible" : true + } +} \ No newline at end of file diff --git a/bin/data/entities/burger.json b/bin/data/entities/burger.json new file mode 100644 index 00000000..5fe475e9 --- /dev/null +++ b/bin/data/entities/burger.json @@ -0,0 +1,55 @@ +{ + "type": "Object", + "name": "Burger", + "ignore": false, + "import": "/model.json", + "assets": [ + // "/burger/burger.glb" + // "/burger/burger_simpler.glb" + // "/burger/burger/graph.json" + "/burger/burger_simpler/graph.json" + ], + "behaviors": [], + "transform": { + "position": [ -0.574743, 2.3547, -5.05161 ], + // "position": [ -4.66561, 0.0736207, -5.98057 ], + "rotation": { + "axis": [ 0, 1, 0 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "system": { + "hot reload": { + "enabled": true + } + }, + "metadata": { + "holdable": true, + + "physics": { + "gravity": [ 0, -9.81, 0 ], + "inertia": [ 0, 0, 0 ], + + "mass": 10, + "type": "bounding box", + "recenter": false + }, + "graph": { + "exporter": { + "enabled": true, + "unwrap": false, + "optimize": false + }, + "baking": { + "enabled": false + }, + "renderer": { + "flip textures": false + }, + "lighting": { + "lightmap": false + } + } + } +} \ No newline at end of file diff --git a/bin/data/entities/cornell.json b/bin/data/entities/cornell.json new file mode 100644 index 00000000..8033b870 --- /dev/null +++ b/bin/data/entities/cornell.json @@ -0,0 +1,39 @@ +{ + "type": "Object", + "name": "Cornell Box", + "ignore": false, + "import": "/model.json", + "assets": [ + // "/cornell/cornell.glb" + { "filename": "/cornell/cornell/graph.json" } + ], + "behaviors": [], + "transform": { + "position": [ -0.23807, -0.984829, -30.4967 ], + "rotation": { + "axis": [ 0, 1, 0 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "system": { + "hot reload": { + "enabled": true + } + }, + "metadata": { + "track": true, + "hide": true, + "graph": { + "lightmap": false, + "exporter": { + "enabled": false, + "unwrap": false, + "optimize": false + }, + "baking": { + "enabled": false + } + } + } +} \ No newline at end of file diff --git a/bin/data/entities/door.json b/bin/data/entities/door.json new file mode 100644 index 00000000..66d00173 --- /dev/null +++ b/bin/data/entities/door.json @@ -0,0 +1,14 @@ +{ + "assets": ["./scripts/door.lua"], + "behaviors": [ + "SoundEmitterBehavior" + ], + "metadata": { + "physics": { + "mass": 0, + "inertia": [0, 0, 0], + "type": "bounding box", + "recenter": true + } + } +} \ No newline at end of file diff --git a/bin/data/entities/gui.json b/bin/data/entities/gui.json new file mode 100644 index 00000000..c0a9d77e --- /dev/null +++ b/bin/data/entities/gui.json @@ -0,0 +1,8 @@ +{ + "name": "Gui Manager", + "type": "Object", + "behaviors": [ + "GuiManagerBehavior" + ], + "ignore": false +} \ No newline at end of file diff --git a/bin/data/entities/gui/hud/hud.json b/bin/data/entities/gui/hud/hud.json new file mode 100644 index 00000000..a9a3af99 --- /dev/null +++ b/bin/data/entities/gui/hud/hud.json @@ -0,0 +1,20 @@ +{ + "name": "HUD", + "type": "Gui", + "ignore": false, + "assets": [ + "./scripts/hud.lua" + ], + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 16, 16, 16 ] + }, + "metadata": { + "clickable": false, + "hoverable": false, + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/hud/overlay.json b/bin/data/entities/gui/hud/overlay.json new file mode 100644 index 00000000..2f75c02b --- /dev/null +++ b/bin/data/entities/gui/hud/overlay.json @@ -0,0 +1,35 @@ +{ + "name": "HUD Overlay", + "type": "Gui", + "ignore": false, + "assets": [ + { "filename": "./textures/mp.png", "hash": "68e7c459f9aecd6815ff7df1e2eefa82db60a23713b0134f0bfc15d82f55453d" } + // { "filename": "./textures/ss2.png" } + ], + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + // "scale": [ 1.7776, -1, -1 ] + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "clickable": false, + "hoverable": false, + + "uv": [ 0, 0, 1, 1 ], + // "color": [ 0.8, 0.8, 1, 1 ], + // "color": [ 0.416, 0.573, 0.667, 1 ], + "color": [ 1, 1, 1, 1 ], + "location": "", + "scaling": "relative", + // "depth": 0.1, + // "alpha": 0.5, + "alpha": 0.75, + "mode": 1, + "gui layer": true, + "only model": true + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/hud/scripts/hud.lua b/bin/data/entities/gui/hud/scripts/hud.lua new file mode 100644 index 00000000..b04077af --- /dev/null +++ b/bin/data/entities/gui/hud/scripts/hud.lua @@ -0,0 +1,154 @@ +local scene = entities.currentScene() +local controller = entities.controller() +local metadata = ent:getComponent("Metadata") +local masterdata = scene:getComponent("Metadata") + +local visorLayers = 5 +local children = {} +for i=1, visorLayers do + children[i] = ent:loadChild("./overlay.json",true) +end + +local soundEmitter = ent:loadChild("./sound.json",true) + +local timer = Timer.new() +if not timer:running() then timer:start() end + +Static = { + values = {}, + get = function( obj ) + if obj == nil then + obj = scene + end + if Static.values[""..obj:uid()] == nil then + Static.values[""..obj:uid()] = {} + end + return Static.values[""..obj:uid()] + end +} + +local lerper = { + to = Quaternion(0,0,0,1), + from = Quaternion(0,0,0,1), + a = 0 +} + +local rotate = function( delta ) + delta.x = delta.x * 0.1 + delta.y = delta.y * 0.1 + + local transform = ent:getComponent("Transform") + local rotation = { + x = Quaternion.axisAngle( Vector3f(0, 1, 0), delta.x ), + y = Quaternion.axisAngle( Vector3f(1, 0, 0), delta.y ) + } + + lerper.a = 0 + lerper.from = Quaternion.multiply( transform.orientation, rotation.x:multiply(rotation.y) ) + transform.orientation = lerper.from + for k, obj in pairs(children) do + obj:getComponent("Transform").orientation = transform.orientation + end +end + +local windowSize = masterdata["system"]["config"]["window"]["size"]; +local entTransform = ent:getComponent("Transform") +entTransform.scale.x = entTransform.scale.x * windowSize.x / windowSize.y; + +for k, obj in pairs(children) do + local transform = obj:getComponent("Transform") + transform.scale = entTransform.scale; + transform.position.z = -0.5 + ((k-1) * 0.005) +end + +ent:addHook( "window:Resized", function( payload ) + if entTransform.scale.y == entTransform.scale.z then + entTransform.scale.x = entTransform.scale.y * payload["window"]["size"][1] / payload["window"]["size"][2]; + end + + for k, obj in pairs(children) do + local transform = obj:getComponent("Transform") + transform.scale = entTransform.scale; + end +end ) + +ent:addHook( "controller:Camera.Rotated", function( payload ) + rotate( { + x = -payload.angle.yaw, + y = -payload.angle.pitch + }) +--[[ + local transform = ent:getComponent("Transform") + lerper.a = 0 + local counterOrientation = Quaternion( payload.delta[1], payload.delta[2], payload.delta[3], payload.delta[4] ):inverse() + lerper.from = Quaternion.multiply( transform.orientation, counterOrientation ) + transform.orientation = lerper.from + for k, obj in pairs(children) do + obj:getComponent("Transform").orientation = transform.orientation + end +]] +end ) +--[[ +ent:addHook( "window:Mouse.Moved", function( payload ) + if payload.invoker ~= "client" then return end + + local delta = payload.mouse.delta + local size = payload.mouse.size + + if delta == nil or size == nil then return end + if delta.x == 0 or delta.y == 0 then return end + + delta.x = -delta.x / size.x + delta.y = -delta.y / size.y + + rotate( delta ) +end ) +]] + +ent:bind( "tick", function(self) + for k, obj in pairs(children) do + local metadata = obj:getComponent("Metadata") + local glow = math.sin(time.current()) * 0.5 + 0.5 -- constrained to [0,1] + glow = glow * 0.2 + 0.65 -- constrained to [0.65, 0.85] + metadata["alpha"] = glow + obj:setComponent("Metadata", metadata) + end + + local controllerTransform = controller:getComponent("Transform") + local controllerCamera = controller:getComponent("Camera") + local controllerCameraTransform = controllerCamera:getTransform() + local transform = ent:getComponent("Transform") + + local speed = 2.5 + if lerper.a == 1 then return end + lerper.a = lerper.a + time.delta() * speed + if lerper.a > 1 then lerper.a = 1 end + + transform.orientation = lerper.from:slerp( lerper.to, lerper.a ) + local orientation = transform.orientation + for k, obj in pairs(children) do + local transform = obj:getComponent("Transform") + transform.orientation = orientation + transform.model = controllerCamera:getProjection() * Matrix4f.translate( transform.position ) * transform.orientation:matrix() * Matrix4f.scale( transform.scale ) --Matrix4f.scale( Vector3f( 1.7776 * 2, 2, 2 ) ) + end +end ) + +--[[ + controller:callHook( "object:UpdateMetadata.%UID%", { + path = "overlay.position", + value = { + [1] = position.x, + [2] = position.y, + [3] = position.z + } + } ) + controller:callHook( "object:UpdateMetadata.%UID%", { + path = "overlay.orientation", + value = { + [1] = orientation.x, + [2] = orientation.y, + [3] = orientation.z, + [4] = orientation.w + } + } ) +]] \ No newline at end of file diff --git a/bin/data/entities/gui/hud/sound.json b/bin/data/entities/gui/hud/sound.json new file mode 100644 index 00000000..521052cd --- /dev/null +++ b/bin/data/entities/gui/hud/sound.json @@ -0,0 +1,38 @@ +{ + "type": "Object", + "name": "Sound Emitter", + "ignore": false, + "assets": [ + ], + "behaviors": [ + "SoundEmitterBehavior" + ], + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 1, 0 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "system": { + "hot reload": { + "enabled": true + }, + "defaults": { + "render": true, + "asset load": true + }, + "load": { + "ignore": true + } + }, + "metadata": { + "audio": { + "spatial": false, + "loop": false, + "volume": "sfx", + "rolloffFactor": 2 + } + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/mainmenu/circle-in.json b/bin/data/entities/gui/mainmenu/circle-in.json new file mode 100644 index 00000000..e1fce4e2 --- /dev/null +++ b/bin/data/entities/gui/mainmenu/circle-in.json @@ -0,0 +1,26 @@ +{ + "name": "Menu: Circle Inner", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ 0.86, 0.86, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "clickable": false, + "hoverable": false, + + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0.8 ], + "location": "", + "scaling": [ 0.64, 1 ], + "mode": "flat" + }, + "assets": [ + "textures/circle-in.png" + ] +} \ No newline at end of file diff --git a/bin/data/entities/gui/mainmenu/circle-out.json b/bin/data/entities/gui/mainmenu/circle-out.json new file mode 100644 index 00000000..fc92eb84 --- /dev/null +++ b/bin/data/entities/gui/mainmenu/circle-out.json @@ -0,0 +1,26 @@ +{ + "name": "Menu: Circle Outer", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ 0.86, 0.86, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "clickable": false, + "hoverable": true, + + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0.8 ], + "location": "", + "scaling": [ 0.64, 1 ], + "mode": "flat" + }, + "assets": [ + "textures/circle-out.png" + ] +} \ No newline at end of file diff --git a/bin/data/entities/gui/mainmenu/main-text.json b/bin/data/entities/gui/mainmenu/main-text.json new file mode 100644 index 00000000..a1897789 --- /dev/null +++ b/bin/data/entities/gui/mainmenu/main-text.json @@ -0,0 +1,26 @@ +{ + "name": "Menu: Main Text", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ -0.922623, -0.854923, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "location": "", + "scaling": "relative", + "debug": { + "moveable": false + }, + "text settings": { + "scale": 2, + "font": "Coolvetica.ttf", + "string": "Grimgram" + } + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/mainmenu/menu.json b/bin/data/entities/gui/mainmenu/menu.json new file mode 100644 index 00000000..e0bf0047 --- /dev/null +++ b/bin/data/entities/gui/mainmenu/menu.json @@ -0,0 +1,28 @@ +{ + "name": "Gui: Menu", + "type": "Gui", + "ignore": false, + "assets": [ + "./textures/menu.png", + "./scripts/menu.lua" + ], + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "clickable": true, + "hoverable": true, + + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 1 ], + "location": "", + "scaling": "relative", + "depth": 0, + "mode": "flat" + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/mainmenu/quit.json b/bin/data/entities/gui/mainmenu/quit.json new file mode 100644 index 00000000..a8e02a8f --- /dev/null +++ b/bin/data/entities/gui/mainmenu/quit.json @@ -0,0 +1,36 @@ +{ + "name": "Menu: Close Option", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ -0.75622, 0.638136, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "clickable": true, + "hoverable": true, + + "uv": [ 0, 0, 1, 1 ], + "location": "", + "scaling": "relative", + "debug": { + "moveable": false + }, + "events": { + "click": { + "name": "system:Quit", + "payload": { + "scene": "StartMenu" + } + } + }, + "text settings": { + "legacy": false, + "string": "Quit" + } + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/mainmenu/scripts/menu.lua b/bin/data/entities/gui/mainmenu/scripts/menu.lua new file mode 100644 index 00000000..232ef7a1 --- /dev/null +++ b/bin/data/entities/gui/mainmenu/scripts/menu.lua @@ -0,0 +1,169 @@ +Static = { + values = {}, + get = function( obj ) + if Static.values[""..obj:uid()] == nil then + Static.values[""..obj:uid()] = {} + end + return Static.values[""..obj:uid()] + end +} + +local ent = ent +local scene = entities.currentScene() +local controller = entities.controller() +local camera = controller:getComponent("Camera") +local metadata = ent:getComponent("Metadata") +local masterdata = scene:getComponent("Metadata") + +local children = { + mainText = ent:loadChild("./main-text.json",true), + circleOut = ent:loadChild("./circle-out.json",true), + circleIn = ent:loadChild("./circle-in.json",true), + start = ent:loadChild("./start.json",true), + quit = ent:loadChild("./quit.json",true), +} + +local timer = Timer.new() +if not timer:running() then timer:start() end + +local playSound = function( key ) + local url = "/ui/" .. key .. ".ogg" +-- local assetLoader = scene:getComponent("Asset") +-- assetLoader:cache(ent:formatHookName("asset:Load.%UID%"), string.resolveURI(url)) +end +local destination = function( obj, x, y, z ) + local static = Static.get(obj) + local transform = obj:getComponent("Transform") + static.from = Vector3f(x or transform.position.x, y or transform.position.y, z or transform.position.z) +end + +--[[ +pcall( function() + local metadata = controller:getComponent("Metadata") + local json = json.readFromFile("./data/entities/player.json"); + controller:callHook("object:UpdateMetadata.%UID%", { + overlay = json["metadata"]["overlay"] + }) + camera:update(true); +end ) +]] + +destination(children.mainText, nil, -2, 0) +destination(children.circleOut, nil, -2, 0) +destination(children.circleIn, nil, 2, 0) +destination(children.start, -1.5, nil, 0) +destination(children.quit, -1.5, nil, 0) + +ent:addHook("asset:Load.%UID%", function( json ) + local filename = json["filename"] + if filename == "" or string.extension( filename ) ~= "ogg" then return false end + + local sfx = ent:getComponent("Audio") + if not sfx:playing() then sfx:stop() end + sfx:load( filename ) + sfx:setVolume( masterdata["volumes"]["sfx"] ) + sfx:play() + + return true +end ) +if os.arch() == "Dreamcast" then + ent:bind( "tick", function(self) + -- circle in + if children.circleIn:uid() > 0 then + local transform = children.circleIn:getComponent("Transform") + transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), time.current() * -0.0125 ) + end + -- circle out + if children.circleIn:uid() > 0 then + local transform = children.circleIn:getComponent("Transform") + transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), time.current() * 0.0125 ) + end + + if (window.keyPressed("Enter") or inputs.key("START")) and timer:elapsed() >= 1 then + timer:reset() + children.start:callHook("gui:Clicked.%UID%", {}) + end + end ) +else + ent:bind( "tick", function(self) + if (window.keyPressed("Enter") or inputs.key("START")) and timer:elapsed() >= 1 then + timer:reset() + children.start:callHook("gui:Clicked.%UID%", {}) + end + + local static = Static.get(self) + if not static.alpha then + static.alpha = 0 + end + + metadata["initialized"] = true; + if static.alpha >= 1.0 then + static.alpha = 1.0 + else + static.alpha = static.alpha + time.delta() * 1.5 + end + + -- make background glow + local glow = 1 + math.sin(1.25 * time.current()) * 0.125 + metadata["color"][1] = glow + metadata["color"][2] = glow + metadata["color"][3] = glow + metadata["alpha"] = static.alpha; + self:setComponent("Metadata", metadata) + + camera:update(true); + + -- iterate children in batch + for k, v in pairs(children) do + if v:uid() <= 0 then goto continue end + + -- set alpha + local metadata = v:getComponent("Metadata") + metadata["alpha"] = static.alpha + v:setComponent("Metadata", metadata) + + local transform = v:getComponent("Transform") + local static = Static.get(v) + -- translation + if not static.from then goto continue end + if not static.to then static.to = Vector3f(transform.position) end + if not static.delta then static.delta = 0 end + + if static.delta >= 1 then + static.delta = 1 + else + static.delta = static.delta + time.delta() * 1.5 + transform.position = Vector3f.lerp( static.from, static.to, static.delta ) + end + + ::continue:: + end + + -- circle in + child = children.circleIn + if child:uid() > 0 then + local static = Static.get( child ) + + local transform = child:getComponent("Transform") + local metadata = child:getComponent("Metadata") + + -- rotation + local speed = metadata["hovered"] and 0.25 or 0.0125 + static.time = (static.time or 0) + time.delta() * -speed + transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time ) + end + -- circle out + child = children.circleOut + if child:uid() > 0 then + local static = Static.get( child ) + + local transform = child:getComponent("Transform") + local metadata = child:getComponent("Metadata") + + -- rotation + local speed = metadata["hovered"] and 0.25 or 0.0125 + static.time = (static.time or 0) + time.delta() * speed + transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time ) + end + end ) +end \ No newline at end of file diff --git a/bin/data/entities/gui/mainmenu/sound.json b/bin/data/entities/gui/mainmenu/sound.json new file mode 100644 index 00000000..e69de29b diff --git a/bin/data/entities/gui/mainmenu/start.json b/bin/data/entities/gui/mainmenu/start.json new file mode 100644 index 00000000..23fc52ca --- /dev/null +++ b/bin/data/entities/gui/mainmenu/start.json @@ -0,0 +1,34 @@ +{ + "name": "Menu: Start Option", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ -0.75622, 0.446468, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "clickable": true, + "hoverable": true, + + "uv": [ 0, 0, 1, 1 ], + "location": "", + "scaling": "relative", + "debug": { + "moveable": false + }, + "events": { + "click": { + "name": "game:Scene.Load", + "payload": { "scene": "SourceEngine" } + } + }, + "text settings": { + "string": "Start", + "string1": "スタート" + } + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/circle-in.json b/bin/data/entities/gui/pause/circle-in.json new file mode 100644 index 00000000..b015536d --- /dev/null +++ b/bin/data/entities/gui/pause/circle-in.json @@ -0,0 +1,23 @@ +{ + "name": "Menu: Circle Inner", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ -0.86, 0.86, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0.8 ], + "location": "", + "scaling": [ 0.64, 1 ], + "mode": "flat" + }, + "assets": [ + "./textures/circle-in.png" + ] +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/circle-out.json b/bin/data/entities/gui/pause/circle-out.json new file mode 100644 index 00000000..58fb28c5 --- /dev/null +++ b/bin/data/entities/gui/pause/circle-out.json @@ -0,0 +1,26 @@ +{ + "name": "Menu: Circle Outer", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ -0.86, 0.86, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "clickable": false, + "hoverable": true, + + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0.8 ], + "location": "", + "scaling": [ 0.64, 1 ], + "mode": "flat" + }, + "assets": [ + "textures/circle-out.png" + ] +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/close.json b/bin/data/entities/gui/pause/close.json new file mode 100644 index 00000000..69f3f9f8 --- /dev/null +++ b/bin/data/entities/gui/pause/close.json @@ -0,0 +1,31 @@ +{ + "name": "Menu: Close Option", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ -0.65544, -0.339642, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 0.156407, 0.0788377, 1 ] + }, + "metadata": { + "clickable": true, + "hoverable": true, + + "uv": [ 0, 0, 1, 1 ], + "location": "", + "scaling": "relative", + "events": { + "click": { + "name": "menu:Close.%P-UID%", + "payload": {} + } + }, + "text settings": { + "string": "Close", + "string1": "クローズ" + } + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/command-text.json b/bin/data/entities/gui/pause/command-text.json new file mode 100644 index 00000000..303cd2b1 --- /dev/null +++ b/bin/data/entities/gui/pause/command-text.json @@ -0,0 +1,25 @@ +{ + "name": "Menu: Command Text", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ -0.830591, -0.699509, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 0.258737, 0.115371, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "location": "", + "scaling": "relative", + "text settings": { + "stroke": [ 1, 0.749, 0.368, 1 ], + "color": [ 1, 0.749, 0.368, 1 ], + + "string": "Menu", + "string1": "コマンド" + } + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/icon.json b/bin/data/entities/gui/pause/icon.json new file mode 100644 index 00000000..3176abf4 --- /dev/null +++ b/bin/data/entities/gui/pause/icon.json @@ -0,0 +1,25 @@ +{ + "name": "Gui: Icon", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "gui": { + "position": [ -0.875, -0.775, 0 ], + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 1 ], + "location": "", + "scaling": "fixed" + } + }, + "assets": [ + "https://cdn..xyz//unity/Android/icon/icon_agyou01_skin1.png" + ] +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/main-text.json b/bin/data/entities/gui/pause/main-text.json new file mode 100644 index 00000000..244c0a0f --- /dev/null +++ b/bin/data/entities/gui/pause/main-text.json @@ -0,0 +1,23 @@ +{ + "name": "Menu: Main Scroller", + "type": "Gui", + "ignore": true, + "transform": { + "position": [ 0.98, -2, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 1.5707963 + }, + "scale": [ 0.16, 1, 1 ] + }, + "hoverable": true, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "color": [ 0.113, 0.756, 0.988, 0.4 ], + "location": "", + "scaling": "relative" + }, + "assets": [ + "./textures/main.png" + ] +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/menu.json b/bin/data/entities/gui/pause/menu.json new file mode 100644 index 00000000..4c981bf9 --- /dev/null +++ b/bin/data/entities/gui/pause/menu.json @@ -0,0 +1,29 @@ +{ + "name": "Gui: Menu", + "type": "Gui", + "behaviors": [ + "GuiBehavior" + ], + "ignore": false, + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "color": [ 0.1, 0.05, 0.1, 0.5 ], + "location": "", + "scaling": "relative", + // "depth": 0.2, + "alpha": 1, + "mode": 1 + }, + "assets": [ + // "./textures/menu.png", + "./scripts/menu.lua" + ] +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/quit.json b/bin/data/entities/gui/pause/quit.json new file mode 100644 index 00000000..a127fb1b --- /dev/null +++ b/bin/data/entities/gui/pause/quit.json @@ -0,0 +1,45 @@ +{ + "name": "Menu: Close Option", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ -0.65544, -0.157698, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 0.156407, 0.0788377, 1 ] + }, + "metadata": { + "clickable": true, + "hoverable": true, + + "uv": [ 0, 0, 1, 1 ], + "location": "", + "scaling": "relative", + "debug": { + "moveable": true + }, + "events": { + "click": [ + { + "name": "menu:Close.%P-UID%", + "payload": { + "callback": { + "name": "game:Scene.Load", + "payload": { + "scene": "StartMenu" + }, + "scope": "scene", + "delay": 0 + } + } + } + ] + }, + "text settings": { + "string": "Quit", + "string1": "終了する" + } + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/scripts/menu.lua b/bin/data/entities/gui/pause/scripts/menu.lua new file mode 100644 index 00000000..51f93b96 --- /dev/null +++ b/bin/data/entities/gui/pause/scripts/menu.lua @@ -0,0 +1,276 @@ +local ent = ent +local scene = entities.currentScene() +local controller = entities.controller() +local metadata = ent:getComponent("Metadata") +local masterdata = scene:getComponent("Metadata") + +local children = { + mainText = ent:loadChild("./main-text.json",true), + circleOut = ent:loadChild("./circle-out.json",true), + circleIn = ent:loadChild("./circle-in.json",true), + coverBar = ent:loadChild("./yellow-box.json",true), + commandText = ent:loadChild("./command-text.json",true), + tenkouseiOption = ent:loadChild("./tenkousei.json",true), + closeOption = ent:loadChild("./close.json",true), + quit = ent:loadChild("./quit.json",true), +} + +local soundEmitter = ent:loadChild("./sound.json",true) + +local timer = Timer.new() +if not timer:running() then timer:start() end + +Static = { + values = {}, + get = function( obj ) + if obj == nil then + obj = scene + end + if Static.values[""..obj:uid()] == nil then + Static.values[""..obj:uid()] = {} + end + return Static.values[""..obj:uid()] + end +} + +local destination = function( obj, x, y, z ) + local static = Static.get(obj) + local transform = obj:getComponent("Transform") + static.from = Vector3f(x or transform.position.x, y or transform.position.y, z or transform.position.z) +end +-- circleOut +destination(children.circleOut, nil, -2, 0) +destination(children.circleIn, nil, 2, 0) +destination(children.coverBar, -1.5, nil, 0) +destination(children.commandText, -1.5, nil, 0) +destination(children.tenkouseiOption, -1.5, nil, 0) +destination(children.closeOption, -1.5, nil, 0) +destination(children.quit, -1.5, nil, 0) + +local playSound = function( key ) + local url = "/ui/" .. key .. ".ogg" +-- local assetLoader = scene:getComponent("Asset") +-- assetLoader:cache(soundEmitter:formatHookName("asset:Load.%UID%"), string.resolveURI(url), "") +end + +ent:addHook("menu:Close.%UID%", function( json ) + playSound("menu close") + if metadata["system"]["hooks"] == nil then metadata["system"]["hooks"] = {} end + metadata["system"]["hooks"]["onClose"] = json["callback"]; + metadata["system"]["closing"] = true; + ent:setComponent("Metadata", metadata) +end ) + +playSound("menu open") + +if os.arch() == "Dreamcast" then + ent:bind( "tick", function(self) + local static = Static.get(self) + if not static.alpha then + static.alpha = 0 + end + + if (window.keyPressed("Escape") or inputs.key("START")) and timer:elapsed() >= 1 then + timer:reset() + self:callHook("menu:Close.%UID%", {}) + end + + -- handle closing + if metadata["system"]["closing"] then + if static.alpha <= 0 then + static.alpha = 0 + metadata["system"]["closing"] = false + metadata["system"]["closed"] = true + else + static.alpha = static.alpha - time.delta() + end + elseif metadata["system"]["closed"] then + timer:stop() + local callback = metadata["system"]["hooks"]["onClose"] + if callback then + local payload = callback["payload"] + local target = self + if callback["scope"] == "parent" then + target = ent:getParent() + elseif callback["scope"] == "scene" then + target = scene + end + + if type(callback["delay"]) == "number" and target:uid() ~= self:uid() then + target:queueHook( callback["name"], payload, callback["delay"] ); + else + target:callHook( callback["name"], payload ); + end + end + + controller:callHook("system:Control.%UID%", { + control = true + }) + + entities.destroy(self) + -- scene:queueHook("system:Destroy", { uid = self:uid() }, 0) + return + else + if not metadata["initialized"] then + static.alpha = 0 + end + metadata["initialized"] = true; + if static.alpha >= 1.0 then + static.alpha = 1.0 + else + static.alpha = static.alpha + time.delta() * 1.5 + end + end + + -- main text + local child = children.mainText + if child:uid() > 0 then + local transform = child:getComponent("Transform") + local speed = 0.5 + transform.position.y = transform.position.y + time.delta() * speed + if transform.position.y > 2 then + transform.position.y = -2 + end + end + -- circle in + if children.circleIn:uid() > 0 then + local static = Static.get( children.circleIn ) + local transform = children.circleIn:getComponent("Transform") + + -- rotation + local speed = 0.0125 + static.time = (static.time or 0) + time.delta() * -speed + transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time ) + end + -- circle out + if children.circleOut:uid() > 0 then + local static = Static.get( children.circleOut ) + + local transform = children.circleOut:getComponent("Transform") + + -- rotation + local speed = 0.0125 + static.time = (static.time or 0) + time.delta() * speed + transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time ) + end + end ) +else + ent:bind( "tick", function(self) + local static = Static.get(self) + if not static.alpha then + static.alpha = 0 + end + + if (window.keyPressed("Escape") or inputs.key("START")) and timer:elapsed() >= 1 then + timer:reset() + self:callHook("menu:Close.%UID%", {}) + end + + -- handle closing + if metadata["system"]["closing"] then + if static.alpha <= 0 then + static.alpha = 0 + metadata["system"]["closing"] = false + metadata["system"]["closed"] = true + else + static.alpha = static.alpha - time.delta() + end + elseif metadata["system"]["closed"] then + timer:stop() + local callback = metadata["system"]["hooks"]["onClose"] + if callback then + local payload = callback["payload"] + local target = self + if callback["scope"] == "parent" then + target = ent:getParent() + elseif callback["scope"] == "scene" then + target = scene + end + + if type(callback["delay"]) == "number" and target:uid() ~= self:uid() then + target:queueHook( callback["name"], payload, callback["delay"] ); + else + target:callHook( callback["name"], payload ); + end + end + + entities.destroy(self) + -- scene:queueHook("system:Destroy", { uid = self:uid() }, 0) + return + else + if not metadata["initialized"] then + static.alpha = 0 + end + metadata["initialized"] = true; + if static.alpha >= 1.0 then + static.alpha = 1.0 + else + static.alpha = static.alpha + time.delta() * 1.5 + end + end + + + metadata["alpha"] = static.alpha; + -- set alphas + for k, v in pairs(children) do + if v:uid() <= 0 then goto continue end + + -- set alpha + local metadata = v:getComponent("Metadata") + metadata["alpha"] = static.alpha + + local transform = v:getComponent("Transform") + local static = Static.get(v) + -- translation + if not static.from then goto continue end + if not static.to then static.to = Vector3f(transform.position) end + if not static.delta then static.delta = 0 end + + if static.delta >= 1 then + static.delta = 1 + else + static.delta = static.delta + time.delta() * 1.5 + transform.position = Vector3f.lerp( static.from, static.to, static.delta ) + v:setComponent("Metadata", metadata) + end + + ::continue:: + end + + -- main text + local child = children.mainText + if child:uid() > 0 then + local transform = child:getComponent("Transform") + local metadata = child:getComponent("Metadata") + local speed = metadata["gui"]["hovered"] and 0.75 or 0.5 + transform.position.y = transform.position.y + time.delta() * speed + if transform.position.y > 2 then + transform.position.y = -2 + end + end + -- circle in + if children.circleIn:uid() > 0 then + local static = Static.get( children.circleIn ) + + local transform = children.circleIn:getComponent("Transform") + local metadata = children.circleIn:getComponent("Metadata") + + -- rotation + local speed = metadata["gui"]["hovered"] and 0.25 or 0.0125 + static.time = (static.time or 0) + time.delta() * -speed + transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time ) + end + -- circle out + if children.circleOut:uid() > 0 then + local static = Static.get( children.circleOut ) + + local transform = children.circleOut:getComponent("Transform") + local metadata = children.circleOut:getComponent("Metadata") + + -- rotation + local speed = metadata["gui"]["hovered"] and 0.25 or 0.0125 + static.time = (static.time or 0) + time.delta() * speed + transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time ) + end + end ) +end \ No newline at end of file diff --git a/bin/data/entities/gui/pause/sound.json b/bin/data/entities/gui/pause/sound.json new file mode 100644 index 00000000..521052cd --- /dev/null +++ b/bin/data/entities/gui/pause/sound.json @@ -0,0 +1,38 @@ +{ + "type": "Object", + "name": "Sound Emitter", + "ignore": false, + "assets": [ + ], + "behaviors": [ + "SoundEmitterBehavior" + ], + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 1, 0 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "system": { + "hot reload": { + "enabled": true + }, + "defaults": { + "render": true, + "asset load": true + }, + "load": { + "ignore": true + } + }, + "metadata": { + "audio": { + "spatial": false, + "loop": false, + "volume": "sfx", + "rolloffFactor": 2 + } + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/tenkousei.json b/bin/data/entities/gui/pause/tenkousei.json new file mode 100644 index 00000000..de0f3362 --- /dev/null +++ b/bin/data/entities/gui/pause/tenkousei.json @@ -0,0 +1,25 @@ +{ + "name": "Menu: Tenkousei Option", + "type": "Gui", + "ignore": true, + "transform": { + "position": [ -0.65544, -0.52853, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 0.156407, 0.0788377, 1 ] + }, + "metadata": { + "clickable": true, + "hoverable": true, + + "uv": [ 0, 0, 1, 1 ], + "location": "", + "scaling": "relative", + "text settings": { + "string": "", + "string1": "「転光生」" + } + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/transient-portrait.json b/bin/data/entities/gui/pause/transient-portrait.json new file mode 100644 index 00000000..1a8843af --- /dev/null +++ b/bin/data/entities/gui/pause/transient-portrait.json @@ -0,0 +1,23 @@ +{ + "name": "Menu: Transient Portrait", + "type": "Gui", + "ignore": true, + "transform": { + "position": [ 0.76, 0.2, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 0.43, 1, 1 ] + }, + "metadata": { + "clickable": true, + "hoverable": false, + + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0 ], + "location": "", + "scaling": "relative", + "depth": 0.1 + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/transient-shadow.json b/bin/data/entities/gui/pause/transient-shadow.json new file mode 100644 index 00000000..908f7c47 --- /dev/null +++ b/bin/data/entities/gui/pause/transient-shadow.json @@ -0,0 +1,21 @@ +{ + "name": "Menu: Transient Shadow", + "type": "Gui", + "ignore": true, + "transform": { + "position": [ 0.46, 0, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 0.43, 1, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0 ], + "location": "", + "scaling": "relative", + "shader": 1, + "depth": 0.1 + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/pause/yellow-box.json b/bin/data/entities/gui/pause/yellow-box.json new file mode 100644 index 00000000..49d36850 --- /dev/null +++ b/bin/data/entities/gui/pause/yellow-box.json @@ -0,0 +1,25 @@ +{ + "name": "Menu: Left Rectangle", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ -0.933374, 0, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 0.067, 1, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + // "color": [ 1, 0.749, 0.368, 1 ], + "color": [ 1, 0.749, 0.368, 1 ], + "location": "", + "scaling": "relative", + "shader": 1, + "mode": "flat" + }, + "assets": [ + "./textures/square.png" + ] +} \ No newline at end of file diff --git a/bin/data/entities/gui/text/letter.json b/bin/data/entities/gui/text/letter.json new file mode 100644 index 00000000..c4e85168 --- /dev/null +++ b/bin/data/entities/gui/text/letter.json @@ -0,0 +1,22 @@ +{ + "name": "Gui: Text", + "type": "Object", + "behaviors": [ + "GuiBehavior" + ], + "ignore": false, + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 1 ], + "location": "", + "scaling": "relative" + } +} \ No newline at end of file diff --git a/bin/data/entities/gui/text/string.json b/bin/data/entities/gui/text/string.json new file mode 100644 index 00000000..0eecab28 --- /dev/null +++ b/bin/data/entities/gui/text/string.json @@ -0,0 +1,43 @@ +{ + "name": "Gui: Text", + "type": "Gui", + "ignore": true, + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 0, 1 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "text settings": { + "legacy": false, + "padding": [ 1, 1 ], + "spread": 4, + "weight": 0.48, + // "size": 36, "scale": 3, + // "size": 45, "scale": 2, + "size": 60, "scale": 1.5, + // "size": 72, "scale": 1.25, + // "size": 90, "scale": 1, + "sdf": false, + "font": "TAZUGANEGOTHICSTDN-BOLD.otf", + "kerning": 24, + // "font": "Coolvetica.ttf", + + "stroke": [ 0, 0, 0, 0 ], + "color": [ 1, 1, 1, 1 ], + + "direction": "down", + "align": "left", + "origin": [ 0, 0 ], + + "string": "", + + "world": false, + // "depth": 0, + "wrap": true + } + } +} \ No newline at end of file diff --git a/bin/data/entities/hud.json b/bin/data/entities/hud.json new file mode 100644 index 00000000..1d99139b --- /dev/null +++ b/bin/data/entities/hud.json @@ -0,0 +1,29 @@ +{ + "name": "HUD Text", + "type": "Gui", + "ignore": false, + "transform": { + "position": [ -0.830591, -0.899509, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 0.258737, 0.115371, 1 ] + }, + "system": { + "hot reload": { + "enabled": true + } + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "location": "", + "scaling": "relative", + "text settings": { + "stroke": [ 1, 0.749, 0.368, 1 ], + "color": [ 1, 0.749, 0.368, 1 ], + "depth": 0.5, + "string": "." + } + } +} \ No newline at end of file diff --git a/bin/data/entities/light.json b/bin/data/entities/light.json new file mode 100644 index 00000000..cac15456 --- /dev/null +++ b/bin/data/entities/light.json @@ -0,0 +1,37 @@ +{ + "type": "Object", + "name": "Light", + "behaviors": [ "LightBehavior" ], + "ignore": false, + "transform": { + "reference": true + }, + "system": { + "renderer": { + // "limiter": 128 + // "mode": "round robin" + // "mode": "once" + "mode": "in-range" + }, + "hot reload": { + "enabled": true + } + }, + "metadata": { + "light": { + "type": "point", + "color": [1, 1, 1], + "power": 100, + "fov": 90, + "bias": { + "constant": 1.25, + "slope": 1.75, + "shader": 0.000005 // 0.000005 //0.000000005 + }, + "radius": [0.5, 0], + "resolution": 512, + "shadows": true, + "dynamic": true + } + } +} \ No newline at end of file diff --git a/bin/data/entities/model.json b/bin/data/entities/model.json new file mode 100644 index 00000000..a245e19b --- /dev/null +++ b/bin/data/entities/model.json @@ -0,0 +1,79 @@ +{ + "name": "Graph", + "type": "Object", + "ignore": false, +// "behaviors": [ "LoadingBehavior" ], + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { "axis": [ 0, 1, 0 ], "angle": 0 }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "graph": { + "debug": { + "no cleanup": false, + "print": { + "tree": false, + "stats": false, + "lights": false, + "meshes": false, + "materials": false, + "textures": false + } + }, + "sanitizer": { + "winding order": true + }, + "exporter": { + "enabled": true, + "pretty": false, + "encoding": "auto", + "compression": "auto", + "quantize": false, + "precision": 4, + "combined": false, + "encode buffers": true, + "unwrap": "tagged", + "quit": true + }, + "baking": { + "enabled": true, + "resolution": 2048, + "shadows": 1024, + "layers": 1, + "trigger": { "mode": "rendered", "quit": true }, + // "trigger": { "mode": "key", "value": "B" }, + "output": "./lightmap.%i.png", + "settings": { + "useInputMeshUvs": true, + "maxIterations": 4, + // "maxChartSize": 0, + "padding": 2, + // "texelsPerUnit": 0, + "bilinear": true, + "blockAlign": true, + "bruteForce": false, + + "rotateChartsToAxis": false, + "rotateCharts": true + } + }, + "renderer": { + "front face": "auto", + "cull mode": "back", + "filter": "linear", + + "atlas": false, + "invert": true, + "skinned": false, + "render": true, + "separate": false + }, + "lights": { + "lightmap": "auto", + // "disable if lightmapped": false, + "shadows": true + } + } + } +} \ No newline at end of file diff --git a/bin/data/entities/player.json b/bin/data/entities/player.json new file mode 100644 index 00000000..d03fdc72 --- /dev/null +++ b/bin/data/entities/player.json @@ -0,0 +1,111 @@ +{ + "name": "Player", + "type": "Object", + "behaviors": [ + "PlayerBehavior", + "SoundEmitterBehavior" + ], + "ignore": false, +/* + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 1, 0 ], + "angle": 0 + }, + "scale": [ 1, 1, 1 ] + }, +*/ + "assets": [ + // { "filename": "./playerModel.json", "delay": 0 }, + "./playerModel.json", + "./playerLight.json", + "./playerHands.json", + "./scripts/player.lua" + ], + "system": { + "hot reload": { + "enabled": true + } + }, + "metadata": { + "overlay": { + "transform": { + "position": [ 0, 0, -3 ], + "scale": [ 1.77778, -1, 1 ], + "orientation": [ 0, 0, 0, 1 ] + }, + "floating": false, + "enabled": true, + "alpha": 1.0, + "cursor": { + "type": "mouse", + "radius": 0.05, + "color": [ 0.2, 0.2, 1.0, 1.0 ], + "enabled": false + } + }, + "audio": { + "footstep": { + "volume": 0.5, + "list": [ + "/footstep/1.ogg", + "/footstep/2.ogg" + ] + } + }, + "movement": { + "walk": 1, + "move": 4, + "run": 16, + "rotate": 1.5, + "air": 0.1, + + "crouch": 1, + "jump": [ 0, 3, 0 ], + "look": 1, + "floored": { + "feet": [ 0, -1.5, 0 ], + // "floor": [ 0, -0.5, 0 ], + "floor": [ 0, -1.0, 0 ], + "print": false + } + }, + "physics": { + "gravity": [ 0, -9.81, 0 ], + "inertia": [ 0, 0, 0 ], + + "type": "capsule", + "radius": 1, + "height": 2, + + "mass": 100, + "friction": 0.95, + "restitution": 0.0, + + "shared": false + }, + "camera": { + "offset": [ 0, 0, 0 ], + "position" : [ 0, 1.8, 0 ], + "scale": [ 1, 1, 1 ], + "invert": [ false, false, false ], + "limit": { + // "minima": [ null, -1.57079633, null ], + // "maxima": [ null, 1.57079633, null ], + + "minima": [ null, -1.0, null ], + "maxima": [ null, 1.0, null ], + "current":[ null, 0, null ] + }, + "settings": { + "fov" : 90.0, + "clip" : [ 0.1, 64.0 ], + "size" : [ 0, 0 ] + } + }, + "use": { + "length": 5 + } + } +} \ No newline at end of file diff --git a/bin/data/entities/playerHands.json b/bin/data/entities/playerHands.json new file mode 100644 index 00000000..45774fbd --- /dev/null +++ b/bin/data/entities/playerHands.json @@ -0,0 +1,76 @@ +{ + "name": "Hands", + "type": "Object", + "ignore": true, + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 1, 0 ], + "angle": 0.0 + }, + "scale": [ 1, 1, 1 ] + }, + "assets": [ + ], + "behaviors": [ + "PlayerHandBehavior" + ], + "metadata": { + "hands": { + "left": { + "controller": { + "model": "{indexcontroller}valve_controller_knu_1_0_left", + "color": [ 1, 1, 1, 1 ] + }, + "light": { + "should": false, + "type": 3, + "color": [1, 1, 1], + "power": 50, + "fov": 80, + "shadows": true, + "bias": 0.000005, + "resolution": 512, + "static": false + }, + "pointer": { + "color": [ 1, 0, 1, 1 ], + "length": 0, //128, + "width": 8, + "offset": [ 0, 0, 0 ], + "orientation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + } + } + }, + "right": { + "controller": { + "model": "{indexcontroller}valve_controller_knu_1_0_right", + "color": [ 1, 1, 1, 1 ] + }, + "light": { + "should": false, + "type": 3, + "color": [1, 1, 1], + "power": 50, + "fov": 80, + "shadows": true, + "bias": 0.000005, + "resolution": 512, + "static": false + }, + "pointer": { + "color": [ 1, 0, 1, 1 ], + "length": 0, //128, + "width": 8, + "offset": [ 0, 0, 0 ], + "orientation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + } + } + } + } + } +} \ No newline at end of file diff --git a/bin/data/entities/playerLight.json b/bin/data/entities/playerLight.json new file mode 100644 index 00000000..6f83eba5 --- /dev/null +++ b/bin/data/entities/playerLight.json @@ -0,0 +1,32 @@ +{ + "import": "/light.json", + "ignore": false, + "assets": [ + ], + "transform": { + // "track": "parent", + "position": [ 0, 1.7, 0 ] + }, + "system": { + "hot reload": { + "enabled": true + } + }, + "metadata": { + "light": { + "type": "spot", + "color": [1, 1, 1], + "power": 30, + "fov": 90, + "bias": { + "constant": 1.25, + "slope": 1.75, + "shader": 0.000005 //0.000000005 + }, + "radius": [0.001, 0], + "resolution": 512, + "shadows": false, + "dynamic": true + } + } +} \ No newline at end of file diff --git a/bin/data/entities/playerModel.json b/bin/data/entities/playerModel.json new file mode 100644 index 00000000..c8f1796e --- /dev/null +++ b/bin/data/entities/playerModel.json @@ -0,0 +1,62 @@ +{ + "type": "Object", + "name": "Player: Model", + "ignore": true, + "import": "/model.json", + "assets": [ + "/player/bear.glb" + // { "filename": "/player/bear/graph.json" } + ], + "behaviors": [ + "PlayerModelBehavior" + ], + "transform": { + "position": [ 0, -2.0, 0 ], + // "position": [ 12.5715, 3.53811, 7.6238 ], + // "position": [ 1.635, -0.384, -20.409 ], // -0.384 + "rotation": { + "axis": [ 0, 1, 0 ], + "angle": 0 + }, + "scale": [ 0.16, 0.16, 0.16 ] + }, + "system": { + "hot reload": { + "enabled": true + } + }, + "metadata": { + "track": true, + "hide": true, + "graph": { + "debug": { + "print": { + "animations": true + } + }, + "exporter": { + "enabled": false, + "unwrap": false, + "optimize": false + }, + "baking": { + "enabled": false + }, + "renderer": { + "cull mode": "back", + "filter": "linear" + }, + "lights": { + "lightmap": false + }, + "renderer": { + "flip textures": false, + "invert": false, + "skinned": true + }, + "animations": { + "animation": "wank" + } + } + } +} \ No newline at end of file diff --git a/bin/data/entities/prop.json b/bin/data/entities/prop.json new file mode 100644 index 00000000..a44b9326 --- /dev/null +++ b/bin/data/entities/prop.json @@ -0,0 +1,17 @@ +{ + "assets": [], + "behaviors": [ + "SoundEmitterBehavior" + ], + "metadata": { + "holdable": true, + "physics": { + // "gravity": [ 0, -9.81, 0 ], + // "inertia": [10, 10, 10], + // "mass": 10, + + "type": "bounding box", + "recenter": false + } + } +} \ No newline at end of file diff --git a/bin/data/entities/scene.json b/bin/data/entities/scene.json new file mode 100644 index 00000000..9ce19331 --- /dev/null +++ b/bin/data/entities/scene.json @@ -0,0 +1,10 @@ +{ + "name": "Scene", + "assets": [ + "/gui.json" + ], + "behaviors": [ + "SceneBehavior", + "ExtSceneBehavior" + ] +} \ No newline at end of file diff --git a/bin/data/entities/scripts/door.lua b/bin/data/entities/scripts/door.lua new file mode 100644 index 00000000..b32db393 --- /dev/null +++ b/bin/data/entities/scripts/door.lua @@ -0,0 +1,117 @@ +local ent = ent +local scene = entities.currentScene() +local controller = entities.controller() + +local timer = Timer.new() +if not timer:running() then + timer:start(); +end + +local polarity = 1 +local state = 0 +local targetAlpha = 1 +local alpha = 0 +local target = Vector3f(0,0,0) +local transform = ent:getComponent("Transform") +local metadata = ent:getComponent("Metadata") +local speed = metadata["speed"] or 1.0 +local normal = Vector3f(0,0,-1) +if metadata["normal"] ~= nil then + local sign = -1 + if metadata["angle"] < 0 then sign = 1 end + normal = Vector3f( metadata["normal"][1] * sign, metadata["normal"][2] * sign, metadata["normal"][3] * sign ):normalize() +end +local starting = Quaternion(transform.orientation) +local ending = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), metadata["angle"] )) + +-- local soundEmitter = ent:loadChild("/sound.json",true) +local soundEmitter = ent + +local playSound = function( key, loop ) + if not loop then loop = false end + local url = "/door/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Emit.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]), + spatial = true, + streamed = true, + volume = "sfx", + loop = loop + }, 0) +end +local stopSound = function( key ) + local url = "/door/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Stop.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]) + }, 0) +end +local playSoundscape = function( key ) + local url = "/soundscape/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Emit.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]), + spatial = false, + volume = "sfx", + loop = true, + streamed = true + }, 0) +end +local stopSoundscape = function( key ) + local url = "/soundscape/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Stop.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]) + }, 0) +end +-- on tick +ent:bind( "tick", function(self) +-- transform.orientation = starting:slerp( ending, math.cos(time.current() * speed) * 0.5 + 0.5 ) + if state == 1 then + alpha = alpha + time.delta() * speed + + if alpha > targetAlpha then + state = 2 + alpha = targetAlpha + playSound("default_stop") + end + + end + if state == 3 then + alpha = alpha - time.delta() * speed + + if alpha < 0 then + state = 0 + alpha = 0 + playSound("default_stop") + end + end + + if state > 0 then + transform.orientation = starting:slerp( ending, alpha * polarity ) + end +end ) +-- on use +ent:addHook( "entity:Use.%UID%", function( payload ) + if payload.user == ent:uid() then return end + +-- if timer:elapsed() <= 0.125 then return end +-- timer:reset() + + print("Processing use: " .. ent:name() .. " | " .. payload["depth"] ) + + if state == 0 or state == 3 then + state = 1 + playSound("default_move") + if payload.uid ~= nil then + local user = entities.get( payload.user ) + local userTransform = user:getComponent("Transform") + local delta = transform.position - userTransform.position + local side = normal:dot(delta) + if side > 0 then + polarity = 1 + elseif side < 0 then + polarity = -1 + end + end + elseif state == 2 --[[or state == 1]] then + state = 3 + playSound("default_move") + end +end ) \ No newline at end of file diff --git a/bin/data/entities/scripts/player.lua b/bin/data/entities/scripts/player.lua new file mode 100644 index 00000000..d105b432 --- /dev/null +++ b/bin/data/entities/scripts/player.lua @@ -0,0 +1,241 @@ +local ent = ent +local scene = entities.currentScene() +local metadata = ent:getComponent("Metadata") +local transform = ent:getComponent("Transform") +local physicsState = ent:getComponent("PhysicsState") +local camera = ent:getComponent("Camera") +local cameraTransform = camera:getTransform() + +-- setup all timers +local timers = { + use = Timer.new(), + holp = Timer.new(), + flashlight = Timer.new(), + physcannon = Timer.new() +} +if not timers.use:running() then timers.use:start(); end +if not timers.holp:running() then timers.holp:start(); end +if not timers.flashlight:running() then timers.flashlight:start(); end +if not timers.physcannon:running() then timers.physcannon:start(); end + +-- setup held object locals +local heldObject = { + uid = 0, + distance = 0, + smoothSpeed = 4, + scrollSpeed = 16, + momentum = Vector3f(0,0,0), + rotate = false, +} +-- setup light locals +local light = { + entity = nil +} +for k, v in pairs(ent:getChildren()) do + if v:name() == "Light" then + light.entity = v + end +end + +if light.entity == nil then + light.entity = ent:loadChild("./playerLight.json",true) +end +light.metadata = light.entity:getComponent("Metadata") +light.transform = light.entity:getComponent("Transform") +light.power = light.metadata["light"]["power"] +light.origin = Vector3f(light.transform.position) +light.entity:setComponent("Metadata", { light = { power = 0 } }) + +-- sound emitter +local playSound = function( key, loop ) + if not loop then loop = false end + local url = "/ui/" .. key .. ".ogg" + ent:callHook("sound:Emit.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]), + spatial = true, + streamed = true, + volume = "sfx", + loop = loop + }, 0) +end +local stopSound = function( key ) + local url = "/ui/" .. key .. ".ogg" + ent:callHook("sound:Stop.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]) + }, 0) +end + +local useDistance = 6 +local pullDistance = useDistance * 4 + +-- on tick +ent:bind( "tick", function(self) + -- eye transform + local flattenedTransform = cameraTransform:flatten() + flattenedTransform.forward = ( transform.forward + Vector3f( 0, cameraTransform.forward.y, 0 ) ):normalize(); + + -- toggle flashlight + if light.enabled then + local center = flattenedTransform.position + local direction = flattenedTransform.forward * 8 + + local offset = 0.25 + local _, depth = physicsState:rayCast( center, direction ) + if depth >= 0.5 then + depth = 0.5 + elseif depth < 0 then + depth = 0.5 + end + light.transform.position = center + direction * (depth - offset) + end + + if timers.flashlight:elapsed() > 0.5 and inputs.key("F") then + timers.flashlight:reset() + + local metadata = { light = { power = light.power } } + if light.entity:getComponent("Metadata")["light"]["power"] ~= light.power then + metadata["light"]["power"] = light.power + light.enabled = true + else + metadata["light"]["power"] = 0 + light.enabled = false + end + light.entity:setComponent("Metadata", metadata) + + playSound("flashlight") + end + + -- fire use ray + if timers.use:elapsed() > 0.5 and (inputs.key("E") or inputs.key("R_Y")) then + timers.use:reset() + + local center = flattenedTransform.position + local direction = flattenedTransform.forward * useDistance + + local prop, depth = physicsState:rayCast( center, direction ) + local payload = { + user = ent:uid(), + uid = prop and prop:uid() or 0, + depth = depth, + } + if prop then + prop:lazyCallHook("entity:Use.%UID%", payload) + end + ent:lazyCallHook("entity:Use.%UID%", payload) + end + + -- update HOLP + if heldObject.uid == 0 then + local mouse2 = inputs.key("Mouse2") or inputs.key("R_TRIGGER"); + if mouse2 then + --[[ + local center = transform.position + cameraTransform.position + local direction = transform.forward + Vector3f( 0, cameraTransform.forward.y, 0 ) + direction = direction:normalize() * 4 + ]] + local center = flattenedTransform.position + local direction = flattenedTransform.forward * pullDistance + local prop, depth = physicsState:rayCast( center, direction ) + if depth >= 0 and prop and not string.matched( prop:name(), "/^worldspawn/" ) then + local heldObjectTransform = prop:getComponent("Transform") + local heldObjectPhysicsState = prop:getComponent("PhysicsState") + + local strength = 500 + local distanceSquared = (heldObjectTransform.position - flattenedTransform.position):magnitude() + + heldObjectPhysicsState:applyImpulse( flattenedTransform.forward * -heldObjectPhysicsState:getMass() * strength / distanceSquared ) + if timers.physcannon:elapsed() > 1.0 then + timers.physcannon:reset() + + playSound("phys_tooHeavy") + end + end + end + else + local mouse1 = inputs.key("Mouse1") or inputs.key("L_TRIGGER"); + local mouse3 = inputs.key("Mouse3"); + local wheel = inputs.analog("MouseWheel") + + if wheel ~= 0 then + heldObject.distance = heldObject.distance + (wheel / 120 * heldObject.scrollSpeed) * time.delta() + end + if mouse3 then + heldObject.rotate = not heldObject.rotate + end + + local prop = entities.get( heldObject.uid ) + local heldObjectTransform = prop:getComponent("Transform") + local heldObjectPhysicsState = prop:getComponent("PhysicsState") + + if mouse1 and timers.physcannon:elapsed() > 0.5 then + timers.physcannon:reset() + + heldObject.uid = 0 + heldObjectPhysicsState:enableGravity(true) + heldObjectPhysicsState:applyImpulse( flattenedTransform.forward * heldObjectPhysicsState:getMass() * 1000 ) + + playSound("phys_launch"..math.random(1,4)) + else + if heldObject.rotate then + heldObjectTransform.orientation = Quaternion.lookAt( (heldObjectTransform.position - flattenedTransform.position):normalize(), transform.up ) + end + + local forward = flattenedTransform.forward * heldObject.distance --flattenedTransform.orientation:rotate( Vector3f(0,0,1) ) + if heldObject.smoothSpeed ~= 0 then + local target = flattenedTransform.position + forward + local offset = target - heldObjectTransform.position + local delta = offset * time.delta() * heldObject.smoothSpeed + + local distance = delta:norm() + if distance > 0.001 then + if timers.holp:elapsed() > 0.125 then + timers.holp:reset() + heldObjectPhysicsState:setVelocity( delta * 20 ) + end + else + heldObjectPhysicsState:setVelocity( Vector3f(0,0,0) ) + end + else + heldObjectTransform.position = flattenedTransform.position + forward + end + end + end +end ) +-- on use +ent:addHook( "entity:Use.%UID%", function( payload ) + if payload.user ~= ent:uid() then return end + + local validUse = false + + if heldObject.uid == 0 and payload.depth > 0 then + local prop = entities.get( payload.uid ) + local propMetadata = prop:getComponent("Metadata") + if propMetadata["holdable"] then + validUse = true + local offset = transform.position - prop:getComponent("Transform").position + + heldObject.uid = payload.uid + heldObject.distance = offset:norm() + + prop:getComponent("PhysicsState"):enableGravity(false) + else + validUse = not string.matched( prop:name(), "/^worldspawn/" ) + end + elseif heldObject.uid ~= 0 then + validUse = true + local prop = entities.get( heldObject.uid ) + local heldObjectPhysicsState = prop:getComponent("PhysicsState") + heldObjectPhysicsState:enableGravity(true) + heldObjectPhysicsState:applyImpulse( heldObject.momentum ) + + heldObject.uid = 0 + heldObject.distance = 0 + heldObject.momentum = Vector3f(0,0,0) + end + + if validUse then + playSound("select") + else + playSound("deny") + end +end ) \ No newline at end of file diff --git a/bin/data/entities/sound.json b/bin/data/entities/sound.json new file mode 100644 index 00000000..7160ee15 --- /dev/null +++ b/bin/data/entities/sound.json @@ -0,0 +1,20 @@ +{ + "type": "Object", + "name": "Sound Emitter", + "ignore": false, + "assets": [], + "behaviors": [ "SoundEmitterBehavior" ], + "transform": { "reference": true }, + "system": { + "hot reload": { "enabled": true } + }, + "metadata": { + "audio": { + "spatial": true, + "loop": false, + "volume": 1, + "rolloffFactor": 0.5, + "epsilon": 0.5 + } + } +} \ No newline at end of file diff --git a/bin/data/entities/test/html.json b/bin/data/entities/test/html.json new file mode 100644 index 00000000..5a5a0a76 --- /dev/null +++ b/bin/data/entities/test/html.json @@ -0,0 +1,31 @@ +{ + "name": "Gui: HTML", + "type": "Gui", + "ignore": true, + "assets": [], + "behaviors": [ + "GuiHtmlBehavior" + ], + "transform": { + "position": [ 0, 4, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 3.14159 + }, + "scale": [ 2, 2, 2 ] + }, + "metadata": { + "clickable": true, + "hoverable": true, + + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 1 ], + "location": "", + "scaling": "relative", + "depth": 0.2, + "world": true, + "size": [ 1600, 1600 ], + "html": "https://youtube.com/", + "ignore inputs": false + } +} \ No newline at end of file diff --git a/bin/data/entities/test/loading.json b/bin/data/entities/test/loading.json new file mode 100644 index 00000000..0dfa50a5 --- /dev/null +++ b/bin/data/entities/test/loading.json @@ -0,0 +1,34 @@ +{ + "name": "Gui: Loading", + "type": "Object", + "behaviors": [ + // "GuiBehavior" + ], + "assets": [ + { "filename": "./mcdonalds.json", "delay": 0 } + // { "filename": "./sh.json", "delay": 0 } + // { "filename": "./medsci.json", "delay": 0 } + ], + "ignore": false, + "transform": { + "position": [ -0.830591, -0.699509, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 0.258737, 0.115371, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0.1 ], + "location": "", + "scaling": "relative", + "text settings": { + "stroke": [ 1, 0.749, 0.368, 1 ], + "color": [ 1, 0.749, 0.368, 1 ], + + "string": "Loading", + "string1": "コマンド" + } + } +} \ No newline at end of file diff --git a/bin/data/openvr_bindings_default.json b/bin/data/openvr_bindings_default.json new file mode 100644 index 00000000..767330f3 --- /dev/null +++ b/bin/data/openvr_bindings_default.json @@ -0,0 +1,261 @@ +{ + "controller_type" : "generic", + "description" : "Default bindings", + "name" : "Generic Bindings", + "bindings": { + "/actions/global": { + "sources": [ + { + "path": "/user/hand/right/input/a", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/leftA" + } + } + }, + { + "path": "/user/hand/left/input/a", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/rightA" + } + } + }, + { + "path": "/user/hand/left/input/b", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/leftB" + } + } + }, + { + "path": "/user/hand/right/input/b", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/rightB" + } + } + }, + { + "path": "/user/hand/left/input/trackpad", + "mode": "trackpad", + "inputs": { + "position": { + "output": "/actions/global/in/leftTrackpad" + }, + "touch": { + "output": "/actions/global/in/leftTouchpad" + } + } + }, + { + "path": "/user/hand/right/input/trackpad", + "mode": "trackpad", + "inputs": { + "position": { + "output": "/actions/global/in/rightTrackpad" + }, + "touch": { + "output": "/actions/global/in/rightTouchpad" + } + } + }, + { + "path": "/user/hand/left/input/trackpad", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/leftClickpad" + } + } + }, + { + "path": "/user/hand/right/input/trackpad", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/right_Clickpad" + } + } + }, + { + "path": "/user/hand/left/input/grip", + "mode": "force_sensor", + "inputs": { + "force": { + "output": "/actions/global/in/leftGrip" + } + } + }, + { + "path": "/user/hand/right/input/grip", + "mode": "force_sensor", + "inputs": { + "force": { + "output": "/actions/global/in/rightGrip" + } + } + }, + { + "path": "/user/hand/left/input/grip", + "mode": "grab", + "inputs": { + "grab": { + "output": "/actions/global/in/leftGrab" + } + } + }, + { + "path": "/user/hand/right/input/grip", + "mode": "grab", + "inputs": { + "grab": { + "output": "/actions/global/in/rightGrab" + } + } + }, + { + "path": "/user/hand/left/input/trigger", + "mode": "button", + "parameters": { + "haptic_amplitude": "0" + }, + "inputs": { + "click": { + "output": "/actions/global/in/leftClick" + } + } + }, + { + "path": "/user/hand/right/input/trigger", + "mode": "button", + "parameters": { + "haptic_amplitude": "0" + }, + "inputs": { + "click": { + "output": "/actions/global/in/rightClick" + } + } + }, + { + "path": "/user/hand/left/input/trigger", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/leftTrigger" + } + } + }, + { + "path": "/user/hand/right/input/trigger", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/rightTrigger" + } + } + }, + { + "path": "/user/hand/left/input/thumbstick", + "mode": "dpad_touch", + "parameters": { + "deadzone_pct": "85", + "overlap_pct": "0", + "sticky": "true" + }, + "inputs": { + "north": { + "output": "/actions/global/in/leftDPadUp" + }, + "south": { + "output": "/actions/global/in/leftDPadDown" + }, + "east": { + "output": "/actions/global/in/leftDPadRight" + }, + "west": { + "output": "/actions/global/in/leftDPadLeft" + } + } + }, + { + "path": "/user/hand/right/input/thumbstick", + "mode": "dpad_touch", + "parameters": { + "deadzone_pct": "85", + "overlap_pct": "0", + "sticky": "true" + }, + "inputs": { + "north": { + "output": "/actions/global/in/rightDPadUp" + }, + "south": { + "output": "/actions/global/in/rightDPadDown" + }, + "east": { + "output": "/actions/global/in/rightDPadRight" + }, + "west": { + "output": "/actions/global/in/rightDPadLeft" + } + } + }, + { + "path": "/user/hand/left/input/thumbstick", + "mode": "joystick", + "inputs": { + "position": { + "output": "/actions/global/in/leftThumbstick" + } + } + }, + { + "path": "/user/hand/right/input/thumbstick", + "mode": "joystick", + "inputs": { + "position": { + "output": "/actions/global/in/rightThumbstick" + } + } + } + ], + "poses": [ + { + "output": "/actions/global/in/leftHandPose", + "path": "/user/hand/left/pose/raw" + }, + { + "output": "/actions/global/in/rightHandPose", + "path": "/user/hand/right/pose/raw" + } + ], + "haptics": [ + { + "output": "/actions/global/out/leftHapticVibration", + "path": "/user/hand/left/output/haptic" + }, + { + "output": "/actions/global/out/rightHapticVibration", + "path": "/user/hand/right/output/haptic" + } + ], + "skeleton": [ + { + "output": "/actions/global/in/leftHandSkeleton", + "path": "/user/hand/left/input/skeleton/left" + }, + { + "output": "/actions/global/in/rightHandSkeleton", + "path": "/user/hand/right/input/skeleton/right" + } + ] + } + } +} \ No newline at end of file diff --git a/bin/data/openvr_bindings_knuckles.json b/bin/data/openvr_bindings_knuckles.json new file mode 100644 index 00000000..8abec4a3 --- /dev/null +++ b/bin/data/openvr_bindings_knuckles.json @@ -0,0 +1,275 @@ +{ + "controller_type" : "knuckles", + "description" : "Default Index Knuckles bindings", + "name" : "Knuckles Bindings", + "bindings": { + "/actions/global": { + "sources": [ + { + "path": "/user/hand/left/input/a", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/a.left" + } + } + }, + { + "path": "/user/hand/right/input/a", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/a.right" + } + } + }, + { + "path": "/user/hand/left/input/b", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/b.left" + } + } + }, + { + "path": "/user/hand/right/input/b", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/b.right" + } + } + }, + { + "path": "/user/hand/left/input/trackpad", + "mode": "trackpad", + "inputs": { + "position": { + "output": "/actions/global/in/trackpad.left" + }, + "touch": { + "output": "/actions/global/in/touchpad.left" + } + } + }, + { + "path": "/user/hand/right/input/trackpad", + "mode": "trackpad", + "inputs": { + "position": { + "output": "/actions/global/in/trackpad.right" + }, + "touch": { + "output": "/actions/global/in/touchpad.right" + } + } + }, + { + "path": "/user/hand/left/input/trackpad", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/clickpad.left" + } + } + }, + { + "path": "/user/hand/right/input/trackpad", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/global/in/clickpad.right" + } + } + }, + { + "path": "/user/hand/left/input/grip", + "mode": "force_sensor", + "inputs": { + "force": { + "output": "/actions/global/in/grip.left" + } + } + }, + { + "path": "/user/hand/right/input/grip", + "mode": "force_sensor", + "inputs": { + "force": { + "output": "/actions/global/in/grip.right" + } + } + }, + { + "path": "/user/hand/left/input/grip", + "mode": "grab", + "inputs": { + "grab": { + "output": "/actions/global/in/grab.left" + } + } + }, + { + "path": "/user/hand/right/input/grip", + "mode": "grab", + "inputs": { + "grab": { + "output": "/actions/global/in/grab.right" + } + } + }, + { + "path": "/user/hand/left/input/trigger", + "mode": "button", + "parameters": { + "haptic_amplitude": "0" + }, + "inputs": { + "click": { + "output": "/actions/global/in/click.left" + } + } + }, + { + "path": "/user/hand/right/input/trigger", + "mode": "button", + "parameters": { + "haptic_amplitude": "0" + }, + "inputs": { + "click": { + "output": "/actions/global/in/click.right" + } + } + }, + { + "path": "/user/hand/left/input/trigger", + "mode": "trigger", + "inputs": { + "click": { + "output": "/actions/global/in/trigger.left" + } + } + }, + { + "path": "/user/hand/right/input/trigger", + "mode": "trigger", + "inputs": { + "click": { + "output": "/actions/global/in/trigger.right" + } + } + }, + { + "path": "/user/hand/left/input/thumbstick", + "mode": "dpad_touch", + "parameters": { + "deadzone_pct": "85", + "overlap_pct": "0", + "sticky": "true" + }, + "inputs": { + "north": { + "output": "/actions/global/in/dpadUp.left" + }, + "south": { + "output": "/actions/global/in/dpadDown.left" + }, + "east": { + "output": "/actions/global/in/dpadRight.left" + }, + "west": { + "output": "/actions/global/in/dpadLeft.left" + } + } + }, + { + "path": "/user/hand/right/input/thumbstick", + "mode": "dpad_touch", + "parameters": { + "deadzone_pct": "85", + "overlap_pct": "0", + "sticky": "true" + }, + "inputs": { + "north": { + "output": "/actions/global/in/dpadUp.right" + }, + "south": { + "output": "/actions/global/in/dpadDown.right" + }, + "east": { + "output": "/actions/global/in/dpadRight.right" + }, + "west": { + "output": "/actions/global/in/dpadLeft.right" + } + } + }, + { + "path": "/user/hand/left/input/thumbstick", + "mode": "joystick", + "inputs": { + "position": { + "output": "/actions/global/in/thumbstick.left" + }, + "click": { + "output": "/actions/global/in/thumbclick.left" + } + } + }, + { + "path": "/user/hand/right/input/thumbstick", + "mode": "joystick", + "inputs": { + "position": { + "output": "/actions/global/in/thumbstick.right" + }, + "click": { + "output": "/actions/global/in/thumbclick.right" + } + } + } + ], + "poses": [ + { + "output": "/actions/global/in/handPose.left", + "path": "/user/hand/left/pose/raw" + }, + { + "output": "/actions/global/in/handPose.right", + "path": "/user/hand/right/pose/raw" + }, + { + "output": "/actions/global/in/handTip.left", + "path": "/user/hand/left/pose/tip" + }, + { + "output": "/actions/global/in/handTip.right", + "path": "/user/hand/right/pose/tip" + } + ], + "haptics": [ + { + "output": "/actions/global/out/hapticVibration.left", + "path": "/user/hand/left/output/haptic" + }, + { + "output": "/actions/global/out/hapticVibration.right", + "path": "/user/hand/right/output/haptic" + } + ], + "skeleton": [ + { + "output": "/actions/global/in/handSkeleton.left", + "path": "/user/hand/left/input/skeleton/left" + }, + { + "output": "/actions/global/in/handSkeleton.right", + "path": "/user/hand/right/input/skeleton/right" + } + ] + } + } +} \ No newline at end of file diff --git a/bin/data/openvr_manifest.json b/bin/data/openvr_manifest.json new file mode 100644 index 00000000..6e2ded5d --- /dev/null +++ b/bin/data/openvr_manifest.json @@ -0,0 +1,165 @@ +{ + "default_bindings": [ + { + "controller_type": "knuckles", + "binding_url": "./openvr_bindings_knuckles.json" + } + ], + "actions": [ + { + "name": "/actions/global/in/a.left", + "type": "boolean" + }, + { + "name": "/actions/global/in/a.right", + "type": "boolean" + }, + { + "name": "/actions/global/in/b.left", + "type": "boolean" + }, + { + "name": "/actions/global/in/b.right", + "type": "boolean" + }, + { + "name": "/actions/global/in/trackpad.left", + "type": "vector2" + }, + { + "name": "/actions/global/in/touchpad.left", + "type": "vector2" + }, + { + "name": "/actions/global/in/trackpad.right", + "type": "vector2" + }, + { + "name": "/actions/global/in/touchpad.right", + "type": "vector2" + }, + { + "name": "/actions/global/in/clickpad.left", + "type": "boolean" + }, + { + "name": "/actions/global/in/clickpad.right", + "type": "boolean" + }, + { + "name": "/actions/global/in/grip.left", + "type": "vector1" + }, + { + "name": "/actions/global/in/grip.right", + "type": "vector1" + }, + { + "name": "/actions/global/in/grab.left", + "type": "boolean" + }, + { + "name": "/actions/global/in/grab.right", + "type": "boolean" + }, + { + "name": "/actions/global/in/click.left", + "type": "boolean" + }, + { + "name": "/actions/global/in/click.right", + "type": "boolean" + }, + { + "name": "/actions/global/in/trigger.left", + "type": "vector1" + }, + { + "name": "/actions/global/in/trigger.right", + "type": "vector1" + }, + { + "name": "/actions/global/in/dpadUp.left", + "type": "boolean" + }, + { + "name": "/actions/global/in/dpadDown.left", + "type": "boolean" + }, + { + "name": "/actions/global/in/dpadRight.left", + "type": "boolean" + }, + { + "name": "/actions/global/in/dpadLeft.left", + "type": "boolean" + }, + { + "name": "/actions/global/in/dpadUp.right", + "type": "boolean" + }, + { + "name": "/actions/global/in/dpadDown.right", + "type": "boolean" + }, + { + "name": "/actions/global/in/dpadRight.right", + "type": "boolean" + }, + { + "name": "/actions/global/in/dpadLeft.right", + "type": "boolean" + }, + { + "name": "/actions/global/in/thumbclick.left", + "type": "boolean" + }, + { + "name": "/actions/global/in/thumbclick.right", + "type": "boolean" + }, + { + "name": "/actions/global/in/thumbstick.left", + "type": "vector2" + }, + { + "name": "/actions/global/in/thumbstick.right", + "type": "vector2" + }, + { + "name": "/actions/global/in/handPose.left", + "type": "pose" + }, + { + "name": "/actions/global/in/handPose.right", + "type": "pose" + }, + { + "name": "/actions/global/in/handTip.left", + "type": "pose" + }, + { + "name": "/actions/global/in/handTip.right", + "type": "pose" + }, + { + "name": "/actions/global/out/hapticVibration.left", + "type": "vibration" + }, + { + "name": "/actions/global/out/hapticVibration.right", + "type": "vibration" + } + ], + "action_sets": [ + { + "name": "/actions/global", + "usage": "leftright" + } + ], + "localization" : [ + { + "language_tag": "en_us" + } + ] +} \ No newline at end of file diff --git a/bin/data/scenes/scene.json b/bin/data/scenes/scene.json new file mode 100644 index 00000000..5a3c92cd --- /dev/null +++ b/bin/data/scenes/scene.json @@ -0,0 +1,60 @@ +{ + "name": "Scene", + "assets": [ + "/gui.json" + ], + "behaviors": [ + "SceneBehavior", + "ExtSceneBehavior" + ], + "system": { + "hot reload": { + "enabled": true + }, + "renderer": { + "clear values": [ + [ 0, 0, 0, 0 ] + ], + "shader": { + "mode": 0, + "scalar": 16, + "parameters": [ 0, 0, 0, "time" ] + } + } + }, + "metadata": { + // sky, and not skybox, so i can supply parameters for global lighting + "sky": { + // sky.box.filename, so i can add in additional parameters, for example, using it as a render target + "box": { + "filename": "/skybox/%d.png" + } + }, + "menus": { + "pause": "/gui/pause/menu.json" + }, + "light": { + "enabled": true, + + "ambient": [ 0.0, 0.0, 0.0 ], + // "ambient": [ 0.1, 0.1, 0.2 ], + + "exposure": 0.125, + "gamma": 2.2, + + "bloom": { + "threshold": 1.0, + "scale": 1.0, + "strength": 0.25, + "sigma": 1.0, + "samples": 4 + }, + "shadows": { + "enabled": true + } + }, + "noise": { + "size": [ 32, 32, 32 ] + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sm64/loading.json b/bin/data/scenes/sm64/loading.json new file mode 100644 index 00000000..2a86c7c5 --- /dev/null +++ b/bin/data/scenes/sm64/loading.json @@ -0,0 +1,32 @@ +{ + "name": "Gui: Loading", + "type": "Object", + "behaviors": [ + // "GuiBehavior" + ], + "assets": [ + { "filename": "./sm64.json", "delay": 0 } + ], + "ignore": false, + "transform": { + "position": [ -0.830591, -0.699509, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 0.258737, 0.115371, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0.1 ], + "location": "", + "scaling": "relative", + "text settings": { + "stroke": [ 1, 0.749, 0.368, 1 ], + "color": [ 1, 0.749, 0.368, 1 ], + + "string": "Loading...", + "string1": "コマンド" + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sm64/player.json b/bin/data/scenes/sm64/player.json new file mode 100644 index 00000000..f56e6fd8 --- /dev/null +++ b/bin/data/scenes/sm64/player.json @@ -0,0 +1,19 @@ +{ + "import": "/player.json", + "assets": [ + // { "filename": "/gui/hud/hud.json", "delay": 0 } + ], + "metadata": { + "movement": { + "jump": [0, 1, 0], + "floored": { + "feet": [ 0, 0, 0 ], + "floor": [ 0, -0.8, 0 ] + } + }, + "physics": { + "radius": 0.25, + "height": 0.25 + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sm64/scene.json b/bin/data/scenes/sm64/scene.json new file mode 100644 index 00000000..30226890 --- /dev/null +++ b/bin/data/scenes/sm64/scene.json @@ -0,0 +1,21 @@ +{ + "import": "/scene.json", + "assets": [ + // "./loading.json", + "./sm64.json" + ], + "metadata": { + "light": { + // "ambient": [ 0, 0, 0 ], + // "ambient": [ 0.025, 0.025, 0.025 ], + // "ambient": [ 0.075, 0.075, 0.075 ], + "ambient": [ 0.1, 0.1, 0.1 ], + // "ambient": [ 0.4, 0.4, 0.4 ], + // "ambient": [ 0.8, 0.8, 0.8 ], + + "fog-": { + + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sm64/sm64.json b/bin/data/scenes/sm64/sm64.json new file mode 100644 index 00000000..6ccfe8c8 --- /dev/null +++ b/bin/data/scenes/sm64/sm64.json @@ -0,0 +1,30 @@ +{ + "import": "/model.json", + "assets": [ + { "filename": "./models/sm64_bbb.glb" } + // { "filename": "./models/sm64_bbb/graph.json" } + ], + "metadata": { + "graph": { + "baking": { "enabled": true }, + "renderer": { + "cull mode": "none", + "filter": "nearest" + }, + "tags": { + "/^worldspawn/": { + "physics": { "type": "mesh", "static": true }, + "grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true }, + "optimize mesh": { "simplify": 0 }, + "unwrap mesh": true + }, + "info_player_spawn": { "action": "attach", "filename": "./player.json" }, + + "Material.071_574B138E_c.bmp": { "material": { "modeAlpha": "blend" } }, + "Material.070_41A41EE3_c.bmp": { "material": { "modeAlpha": "blend" } }, + + "light_sun": { "light": { "power": 25000000 } } + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/base_sourceengine.json b/bin/data/scenes/sourceengine/base_sourceengine.json new file mode 100644 index 00000000..c2207110 --- /dev/null +++ b/bin/data/scenes/sourceengine/base_sourceengine.json @@ -0,0 +1,48 @@ +{ + "import": "/model.json", + "metadata": { + "graph": { + // "renderer": { "separate": true }, + "baking": { "enabled": true }, + "tags": { + // exact matches + "worldspawn": { + "physics": { "type": "mesh", "static": true }, + "grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true }, + "unwrap mesh": true, + "optimize mesh": { "simplify": 0 } + }, + "worldspawn_skybox": { + "grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true }, + "unwrap mesh": true, + "optimize mesh": { "simplify": 0 } + }, + "info_player_spawn": { "action": "attach", "filename": "./player.json", "transform": { "orientation": [ 0, 1, 0, 0 ] } }, + "light_environment": { "ignore": true, "transform": { "orientation": [0,0,0,1] }, "light": { + // "color": [0.1, 0.1, 0.1], + "power": 10000, + "global": true, + "bias": { + "constant": 1.25, + "slope": 1.75, + "shader": 0.000000000005 + }, + "radius": [8, 0], + "resolution": 1024 + } }, + // "/^light_[^e]/": { "ignore": true }, + + // regexp matches + "/^worldspawn_/": { "physics": { "type": "mesh", "static": true } }, + "/^func_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, + "/^prop_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, + "/^prop_static/": { /*"action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } }*/ }, + "/^prop_dynamic/": { /*"action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } }*/ }, + "/^func_physbox/": { "action": "load", "payload": { "import": "/prop.json" } }, + "/^prop_physics/": { "action": "load", "payload": { "import": "/prop.json" } }, + + "/^tools\\/toolsnodraw/": { "material": { "base": [ 1.0, 1.0, 1.0, 0.0 ] } } + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/gm_construct.json b/bin/data/scenes/sourceengine/gm_construct.json new file mode 100644 index 00000000..2be4952e --- /dev/null +++ b/bin/data/scenes/sourceengine/gm_construct.json @@ -0,0 +1,27 @@ +{ + "import": "./base_sourceengine.json", + "assets": [ + // { "filename": "./models/gm_construct.glb" } + { "filename": "./models/gm_construct/graph.json" } + ], + "metadata": { + "graph": { + "assets": [ + "./audio/soundscape/ambience.ogg" + ], + "tags": { + // exact matches + // "worldspawn_skybox": { "ignore": true }, + "worldspawn_water": {}, + + // regex matches + "/^gm_construct\\/water/": { "material": { + "base": [ 0.027, 0.227, 0.259, 0.5 ], + "fRoughness": 0.3, + "fAlphaCutoff": 0.5, + "modeAlpha": "blend" + } } + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/loading.json b/bin/data/scenes/sourceengine/loading.json new file mode 100644 index 00000000..61eab28b --- /dev/null +++ b/bin/data/scenes/sourceengine/loading.json @@ -0,0 +1,32 @@ +{ + "name": "Gui: Loading", + "type": "Object", + "behaviors": [ + "GuiBehavior" + ], + "assets": [ + { "filename": "./sourceengine.json", "delay": 0 } + ], + "ignore": false, + "transform": { + "position": [ -0.830591, -0.699509, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 0.258737, 0.115371, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0.1 ], + "location": "", + "scaling": "relative", + "text settings": { + "stroke": [ 1, 0.749, 0.368, 1 ], + "color": [ 1, 0.749, 0.368, 1 ], + + "string": "Loading...", + "string1": "コマンド" + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/mds_mcdonalds.json b/bin/data/scenes/sourceengine/mds_mcdonalds.json new file mode 100644 index 00000000..525f3a4d --- /dev/null +++ b/bin/data/scenes/sourceengine/mds_mcdonalds.json @@ -0,0 +1,37 @@ +{ + "import": "./base_sourceengine.json", + "assets": [ + // { "filename": "./models/mds_mcdonalds.glb" } + { "filename": "./models/mds_mcdonalds/graph.json" }, + { "filename": "/burger.json", "delay": 1 } + ], + "metadata": { + "graph": { + "assets": [ + "./audio/soundscape/sh2_ambience.ogg" + ], + "tags": { + // exact matches + "func_door_rotating_5473": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } }, + "func_door_rotating_5509": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } }, + "func_door_rotating_5568": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } }, + "func_door_rotating_5584": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } }, + + // regex matches + // "/^prop_physics_override/": { "action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } } }, + // "/^prop_physics_[^o]/": { "action": "load", "payload": { "import": "/prop.json" } }, + + "/^tools\\/toolsnodraw/": { "material": { + "base": [ 1.0, 1.0, 1.0, 1.0 ], + "emissive": [ 0.0, 0.0, 0.0, 0.0 ], + "fMetallic": 0.0, + "fRoughness": 0.10000000149011612, + "fOcclusion": 1.0, + "fAlphaCutoff": 0.5, + "iAlbedo": 27, + "modeAlpha": 1 + } } + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/player.json b/bin/data/scenes/sourceengine/player.json new file mode 100644 index 00000000..b41da045 --- /dev/null +++ b/bin/data/scenes/sourceengine/player.json @@ -0,0 +1,10 @@ +{ + "import": "/player.json", + "assets": [ +// { "filename": "/gui/hud/hud.json", "delay": 0 } + ], + "transform": { + "orientation": [ 0, 1, 0, 0 ] + } +// "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } +} \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/rp_downtown_v2.json b/bin/data/scenes/sourceengine/rp_downtown_v2.json new file mode 100644 index 00000000..8da0ecc6 --- /dev/null +++ b/bin/data/scenes/sourceengine/rp_downtown_v2.json @@ -0,0 +1,24 @@ +{ + "import": "./base_sourceengine.json", + "assets": [ + // { "filename": "./models/rp_downtown_v2.glb" } + { "filename": "./models/rp_downtown_v2/graph.json" } + ], + "metadata": { + "graph": { + "assets": [ + "./audio/soundscape/ambience.ogg" + ], + "renderer": { "separate": true }, + "tags": { + // exact matches + "worldspawn_skybox": { "ignore": true }, + + // regex matches + "/^light_/": { "ignore": true }, + "/^func/": { "ignore": true }, + "/^prop/": { "ignore": true } + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/scene.json b/bin/data/scenes/sourceengine/scene.json new file mode 100644 index 00000000..d8328c78 --- /dev/null +++ b/bin/data/scenes/sourceengine/scene.json @@ -0,0 +1,44 @@ +{ + "import": "/scene.json", + "assets": [ + "./sourceengine.json" + // { "filename": "./loading.json", "delay": 0.5 } + ], + "metadata": { + "light": { + "ambient": [ 0, 0, 0 ], + // "ambient": [ 0.05, 0.05, 0.05 ], + // "ambient": [ 0.15, 0.15, 0.15 ], + // "ambient": [ 0.5, 0.5, 0.5 ], + // "ambient": [ 0.8, 0.8, 0.8 ], + // "ambient": [ 0.1, 0.1, 0.2 ], + + "exposure": 0.125, + "gamma": 2.2, // 2.2, + + "bloom": { + "threshold": 1.2, + "scale": 1.0, + "strength": 1, + "sigma": 2.0, + "samples": 4 + }, + + "fog-": { + // "color": [ 0.1, 0.1, 0.1 ], + // "color": [ 0.2, 0.2, 0.2 ], + "color": [ 0.3, 0.3, 0.3 ], + "range": [ 64, 256 ], + "step scale": 4, + "absorbtion": 0.0125, + "density": { + "threshold": 0.35, + "multiplier": 2.0, + "scale": 25.0, + "offset": [0.2, 0, 1], + "timescale": 32 + } + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/sh2_mcdonalds.json b/bin/data/scenes/sourceengine/sh2_mcdonalds.json new file mode 100644 index 00000000..fd55500e --- /dev/null +++ b/bin/data/scenes/sourceengine/sh2_mcdonalds.json @@ -0,0 +1,56 @@ +{ + "import": "./base_sourceengine.json", + "assets": [ + // { "filename": "./models/sh2_mcdonalds.glb" } + { "filename": "./models/sh2_mcdonalds/graph.json" } + ], + "metadata": { + "graph": { + "lights": { + "scale": 2 + }, + "assets": [ + "./audio/soundscape/sh2_ambience.ogg" + ], + "tags": { + // exact matches + /* + "worldspawn_sh2": { + "physics": { "type": "mesh", "static": true }, + "grid": { "size": [9,1,9], "epsilon": 1.0, "cleanup": true, "print": true }, + "unwrap mesh": true, + "optimize mesh": { "simplify": 0 } + }, + */ + "/^worldspawn_barrier$/": { "ignore": true }, + // "/^worldspawn_skybox/": { "ignore": true }, + + "func_door_rotating_5473": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } }, + "func_door_rotating_5509": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } }, + "func_door_rotating_5568": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } }, + "func_door_rotating_5584": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } }, + "func_door_rotating_9120": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [0,0,1] } } }, + + // regex matches + // "/^prop_physics_[^o]/": { "action": "load", "payload": { "import": "/prop.json" } }, + // "/^prop_physics_override/": { "action": "load", "payload": {} }, + // "/^prop_physics_/": { "action": "load", "payload": {} }, + // "/^func_physbox/": { "action": "load", "payload": {} }, + "/^.+?_phys.+?[^o]/": { "action": "load", "payload": { "import": "/prop.json" } }, + + "materials/models/props_wasteland/prison_lamp001a": { "material": { "emissive": [0, 0, 0, 0] } }, + "/^tools\\/toolsnodraw/": { "material": { + "base": [ 1.0, 1.0, 1.0, 1.0 ], + "emissive": [ 0.0, 0.0, 0.0, 0.0 ], + "fMetallic": 0.0, + "fRoughness": 0.10000000149011612, + "fOcclusion": 1.0, + "fAlphaCutoff": 0.5, + "iAlbedo": 27, + "modeAlpha": 1 + } }, + "/alpha_mtl/": { "material": { "modeAlpha": "blend" } } + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/sourceengine.json b/bin/data/scenes/sourceengine/sourceengine.json new file mode 100644 index 00000000..74277413 --- /dev/null +++ b/bin/data/scenes/sourceengine/sourceengine.json @@ -0,0 +1,7 @@ +{ +// "import": "./rp_downtown_v2.json" + "import": "./ss2_medsci1.json" +// "import": "./sh2_mcdonalds.json" +// "import": "./mds_mcdonalds.json" +// "import": "./gm_construct.json" +} \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/ss2_medsci1.json b/bin/data/scenes/sourceengine/ss2_medsci1.json new file mode 100644 index 00000000..552b382f --- /dev/null +++ b/bin/data/scenes/sourceengine/ss2_medsci1.json @@ -0,0 +1,18 @@ +{ + "import": "./base_sourceengine.json", + "assets": [ + // { "filename": "./models/ss2_medsci1_small.glb" } + { "filename": "./models/ss2_medsci1_small/graph.json" } + ], + "metadata": { + "graph": { + "assets": [ + "./audio/music/medsci1.ogg" + ], + "tags": { + "/^prop_/": { "action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } } }, + "/^func_/": { "action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } } } + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/startmenu/player.json b/bin/data/scenes/startmenu/player.json new file mode 100644 index 00000000..255c5ff8 --- /dev/null +++ b/bin/data/scenes/startmenu/player.json @@ -0,0 +1,16 @@ +{ + "import": "/player.json", + "assets": [ + { "filename": "/hands.json", "delay": 0 } + ], + "system": { + "physics": { + "gravity": [ 0, 0, 0 ], + "clamp": { + "x": [0, 0], + "y": [0, 0], + "z": [0, 0] + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/startmenu/scene.json b/bin/data/scenes/startmenu/scene.json new file mode 100644 index 00000000..ec98cb20 --- /dev/null +++ b/bin/data/scenes/startmenu/scene.json @@ -0,0 +1,19 @@ +{ + "type": "Main Menu", + "behaviors": [ + "SceneBehavior", + "ExtSceneBehavior" + ], + "assets": [ + "/gui.json", + "/ui/main menu.ogg", + "/gui/mainmenu/menu.json" + ], + "metadata": { + "volumes": { + "sfx": 0.25, + "bgm": 0.15, + "voice": 1.0 + } + } +} \ No newline at end of file diff --git a/bin/data/scripts/json.lua b/bin/data/scripts/json.lua new file mode 100644 index 00000000..a9f78820 --- /dev/null +++ b/bin/data/scripts/json.lua @@ -0,0 +1,389 @@ +-- +-- json.lua +-- +-- Copyright (c) 2020 rxi +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of +-- this software and associated documentation files (the "Software"), to deal in +-- the Software without restriction, including without limitation the rights to +-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +-- of the Software, and to permit persons to whom the Software is furnished to do +-- so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all +-- copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +-- SOFTWARE. +-- + +local json = { _version = "0.1.2" } + +------------------------------------------------------------------------------- +-- Encode +------------------------------------------------------------------------------- + +local encode + +local escape_char_map = { + [ "\\" ] = "\\", + [ "\"" ] = "\"", + [ "\b" ] = "b", + [ "\f" ] = "f", + [ "\n" ] = "n", + [ "\r" ] = "r", + [ "\t" ] = "t", +} + +local escape_char_map_inv = { [ "/" ] = "/" } +for k, v in pairs(escape_char_map) do + escape_char_map_inv[v] = k +end + + +local function escape_char(c) + return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte())) +end + + +local function encode_nil(val) + return "null" +end + + +local function encode_table(val, stack) + local res = {} + stack = stack or {} + + -- Circular reference? + if stack[val] then error("circular reference") end + + stack[val] = true + + if rawget(val, 1) ~= nil or next(val) == nil then + -- Treat as array -- check keys are valid and it is not sparse + local n = 0 + for k in pairs(val) do + if type(k) ~= "number" then + error("invalid table: mixed or invalid key types") + end + n = n + 1 + end + if n ~= #val then + error("invalid table: sparse array") + end + -- Encode + for i, v in ipairs(val) do + table.insert(res, encode(v, stack)) + end + stack[val] = nil + return #res == 0 and "{}" or "[" .. table.concat(res, ",") .. "]" +-- return "[" .. table.concat(res, ",") .. "]" + + else + -- Treat as an object + for k, v in pairs(val) do + if type(k) ~= "string" then + error("invalid table: mixed or invalid key types") + end + table.insert(res, encode(k, stack) .. ":" .. encode(v, stack)) + end + stack[val] = nil + return "{" .. table.concat(res, ",") .. "}" + end +end + + +local function encode_string(val) + return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"' +end + + +local function encode_number(val) + -- Check for NaN, -inf and inf + if val ~= val or val <= -math.huge or val >= math.huge then + error("unexpected number value '" .. tostring(val) .. "'") + end + return string.format("%.14g", val) +end + + +local type_func_map = { + [ "nil" ] = encode_nil, + [ "table" ] = encode_table, + [ "string" ] = encode_string, + [ "number" ] = encode_number, + [ "boolean" ] = tostring, +} + + +encode = function(val, stack) + local t = type(val) + local f = type_func_map[t] + if f then + return f(val, stack) + end + error("unexpected type '" .. t .. "'") +end + + +function json.encode(val) + return ( encode(val) ) +end + + +------------------------------------------------------------------------------- +-- Decode +------------------------------------------------------------------------------- + +local parse + +local function create_set(...) + local res = {} + for i = 1, select("#", ...) do + res[ select(i, ...) ] = true + end + return res +end + +local space_chars = create_set(" ", "\t", "\r", "\n") +local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") +local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") +local literals = create_set("true", "false", "null") + +local literal_map = { + [ "true" ] = true, + [ "false" ] = false, + [ "null" ] = nil, +} + + +local function next_char(str, idx, set, negate) + for i = idx, #str do + if set[str:sub(i, i)] ~= negate then + return i + end + end + return #str + 1 +end + + +local function decode_error(str, idx, msg) + local line_count = 1 + local col_count = 1 + for i = 1, idx - 1 do + col_count = col_count + 1 + if str:sub(i, i) == "\n" then + line_count = line_count + 1 + col_count = 1 + end + end + error( string.format("%s at line %d col %d", msg, line_count, col_count) ) +end + + +local function codepoint_to_utf8(n) + -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa + local f = math.floor + if n <= 0x7f then + return string.char(n) + elseif n <= 0x7ff then + return string.char(f(n / 64) + 192, n % 64 + 128) + elseif n <= 0xffff then + return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128) + elseif n <= 0x10ffff then + return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, + f(n % 4096 / 64) + 128, n % 64 + 128) + end + error( string.format("invalid unicode codepoint '%x'", n) ) +end + + +local function parse_unicode_escape(s) + local n1 = tonumber( s:sub(1, 4), 16 ) + local n2 = tonumber( s:sub(7, 10), 16 ) + -- Surrogate pair? + if n2 then + return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) + else + return codepoint_to_utf8(n1) + end +end + + +local function parse_string(str, i) + local res = "" + local j = i + 1 + local k = j + + while j <= #str do + local x = str:byte(j) + + if x < 32 then + decode_error(str, j, "control character in string") + + elseif x == 92 then -- `\`: Escape + res = res .. str:sub(k, j - 1) + j = j + 1 + local c = str:sub(j, j) + if c == "u" then + local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1) + or str:match("^%x%x%x%x", j + 1) + or decode_error(str, j - 1, "invalid unicode escape in string") + res = res .. parse_unicode_escape(hex) + j = j + #hex + else + if not escape_chars[c] then + decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string") + end + res = res .. escape_char_map_inv[c] + end + k = j + 1 + + elseif x == 34 then -- `"`: End of string + res = res .. str:sub(k, j - 1) + return res, j + 1 + end + + j = j + 1 + end + + decode_error(str, i, "expected closing quote for string") +end + + +local function parse_number(str, i) + local x = next_char(str, i, delim_chars) + local s = str:sub(i, x - 1) + local n = tonumber(s) + if not n then + decode_error(str, i, "invalid number '" .. s .. "'") + end + return n, x +end + + +local function parse_literal(str, i) + local x = next_char(str, i, delim_chars) + local word = str:sub(i, x - 1) + if not literals[word] then + decode_error(str, i, "invalid literal '" .. word .. "'") + end + return literal_map[word], x +end + + +local function parse_array(str, i) + local res = {} + local n = 1 + i = i + 1 + while 1 do + local x + i = next_char(str, i, space_chars, true) + -- Empty / end of array? + if str:sub(i, i) == "]" then + i = i + 1 + break + end + -- Read token + x, i = parse(str, i) + res[n] = x + n = n + 1 + -- Next token + i = next_char(str, i, space_chars, true) + local chr = str:sub(i, i) + i = i + 1 + if chr == "]" then break end + if chr ~= "," then decode_error(str, i, "expected ']' or ','") end + end + return res, i +end + + +local function parse_object(str, i) + local res = {} + i = i + 1 + while 1 do + local key, val + i = next_char(str, i, space_chars, true) + -- Empty / end of object? + if str:sub(i, i) == "}" then + i = i + 1 + break + end + -- Read key + if str:sub(i, i) ~= '"' then + decode_error(str, i, "expected string for key") + end + key, i = parse(str, i) + -- Read ':' delimiter + i = next_char(str, i, space_chars, true) + if str:sub(i, i) ~= ":" then + decode_error(str, i, "expected ':' after key") + end + i = next_char(str, i + 1, space_chars, true) + -- Read value + val, i = parse(str, i) + -- Set + res[key] = val + -- Next token + i = next_char(str, i, space_chars, true) + local chr = str:sub(i, i) + i = i + 1 + if chr == "}" then break end + if chr ~= "," then decode_error(str, i, "expected '}' or ','") end + end + return res, i +end + + +local char_func_map = { + [ '"' ] = parse_string, + [ "0" ] = parse_number, + [ "1" ] = parse_number, + [ "2" ] = parse_number, + [ "3" ] = parse_number, + [ "4" ] = parse_number, + [ "5" ] = parse_number, + [ "6" ] = parse_number, + [ "7" ] = parse_number, + [ "8" ] = parse_number, + [ "9" ] = parse_number, + [ "-" ] = parse_number, + [ "t" ] = parse_literal, + [ "f" ] = parse_literal, + [ "n" ] = parse_literal, + [ "[" ] = parse_array, + [ "{" ] = parse_object, +} + + +parse = function(str, idx) + local chr = str:sub(idx, idx) + local f = char_func_map[chr] + if f then + return f(str, idx) + end + decode_error(str, idx, "unexpected character '" .. chr .. "'") +end + + +function json.decode(str) + if type(str) ~= "string" then + error("expected argument of type string, got " .. type(str)) + end + local res, idx = parse(str, next_char(str, 1, space_chars, true)) + idx = next_char(str, idx, space_chars, true) + if idx <= #str then + decode_error(str, idx, "trailing garbage") + end + return res +end + + +return json \ No newline at end of file diff --git a/bin/data/scripts/main.lua b/bin/data/scripts/main.lua new file mode 100644 index 00000000..b5ce3b8f --- /dev/null +++ b/bin/data/scripts/main.lua @@ -0,0 +1,2 @@ +local orientation = Quaternion() +print( orientation, orientation.x ) \ No newline at end of file diff --git a/engine/lib/win64/other/discord_game_sdk.bundle b/engine/lib/win64/other/discord_game_sdk.bundle deleted file mode 100644 index 34e2f559..00000000 Binary files a/engine/lib/win64/other/discord_game_sdk.bundle and /dev/null differ diff --git a/engine/lib/win64/other/openvr_api.dll.sig b/engine/lib/win64/other/openvr_api.dll.sig deleted file mode 100644 index 58c40fba..00000000 Binary files a/engine/lib/win64/other/openvr_api.dll.sig and /dev/null differ diff --git a/engine/lib/win64/other/openvr_api.pdb b/engine/lib/win64/other/openvr_api.pdb deleted file mode 100644 index d82ded06..00000000 Binary files a/engine/lib/win64/other/openvr_api.pdb and /dev/null differ