diff --git a/scripts/cube_logic.lua b/scripts/cube_logic.lua index 9674e22..a36e1d1 100644 --- a/scripts/cube_logic.lua +++ b/scripts/cube_logic.lua @@ -37,6 +37,48 @@ local pyramid_indices = { local math3d = require("math3d") +local InputState = {} +InputState.__index = InputState + +function InputState:new() + local instance = { + mouseX = 0.0, + mouseY = 0.0, + mouseDown = false, + wheel = 0.0, + textInput = "", + keyStates = {}, + } + return setmetatable(instance, InputState) +end + +function InputState:resetTransient() + self.textInput = "" + self.wheel = 0.0 +end + +function InputState:setMouse(x, y, isDown) + self.mouseX = x + self.mouseY = y + self.mouseDown = isDown +end + +function InputState:setWheel(deltaY) + self.wheel = deltaY +end + +function InputState:setKey(keyName, isDown) + self.keyStates[keyName] = isDown +end + +function InputState:addTextInput(text) + if text then + self.textInput = self.textInput .. text + end +end + +gui_input = InputState:new() + local rotation_speeds = {x = 0.5, y = 0.7} local shader_variants = { @@ -63,6 +105,43 @@ local camera = { far = 10.0, } +local zoom_settings = { + min_distance = 2.0, + max_distance = 12.0, + speed = 0.25, +} + +local function clamp_distance(value, minValue, maxValue) + if minValue and value < minValue then + return minValue + end + if maxValue and value > maxValue then + return maxValue + end + return value +end + +local function update_camera_zoom(delta) + if delta == 0 then + return + end + local dx = camera.eye[1] - camera.center[1] + local dy = camera.eye[2] - camera.center[2] + local dz = camera.eye[3] - camera.center[3] + local distance = math.sqrt(dx * dx + dy * dy + dz * dz) + if distance == 0 then + return + end + local normalizedX = dx / distance + local normalizedY = dy / distance + local normalizedZ = dz / distance + local adjustment = -delta * zoom_settings.speed + local targetDistance = clamp_distance(distance + adjustment, zoom_settings.min_distance, zoom_settings.max_distance) + camera.eye[1] = camera.center[1] + normalizedX * targetDistance + camera.eye[2] = camera.center[2] + normalizedY * targetDistance + camera.eye[3] = camera.center[3] + normalizedZ * targetDistance +end + local function build_model(time) local y = math3d.rotation_y(time * rotation_speeds.y) local x = math3d.rotation_x(time * rotation_speeds.x) @@ -112,7 +191,14 @@ function get_shader_paths() return shader_variants end +function get_gui_commands() + return {} +end + function get_view_projection(aspect) + if gui_input then + update_camera_zoom(gui_input.wheel) + end local view = math3d.look_at(camera.eye, camera.center, camera.up) local projection = math3d.perspective(camera.fov, aspect, camera.near, camera.far) return math3d.multiply(projection, view)