diff --git a/class/MockCellulo.lua b/class/MockCellulo.lua index e1c571a..9d12d52 100644 --- a/class/MockCellulo.lua +++ b/class/MockCellulo.lua @@ -1,29 +1,30 @@ local assertArgs = include "assertArgs" local util = include "util" local MockCellulo = lib "class" ("MockCellulo") MockCellulo:include(mixin "Angle") MockCellulo:include(mixin "Position") function MockCellulo:initialize() self:setPosition(0, 0, 0) self:setAngle(0, 0, 1, 0) return self end function MockCellulo:update(dt) end function MockCellulo:getX() return self.x end function MockCellulo:getY() return self.y end function MockCellulo:getTheta() return self.angle end function MockCellulo:getConnectionStatus() return 1 end function MockCellulo:setHapticBackdriveAssist(...) return end function MockCellulo:setGoalVelocity(...) return end function MockCellulo:setGoalPose(...) return end +function MockCellulo:setGoalPosition(...) return end function MockCellulo:getKidnapped() return false end return MockCellulo \ No newline at end of file diff --git a/class/SmoothCellulo.lua b/class/SmoothCellulo.lua index f8b2e89..12fae99 100644 --- a/class/SmoothCellulo.lua +++ b/class/SmoothCellulo.lua @@ -1,72 +1,73 @@ local assertArgs = include "assertArgs" local util = include "util" local SmoothCellulo = lib "class" ("SmoothCellulo") SmoothCellulo:include(mixin "Angle") SmoothCellulo:include(mixin "Position") SmoothCellulo:include(mixin "_has" ("Cellulo")) local KIDNAPPED_STABILIZE_DELAY = 0.3 function SmoothCellulo:initialize(args) assertArgs(args, "cellulo") self:setCellulo(args.cellulo) self:setPosition(args.cellulo:getX(), args.cellulo:getY(), 0) self:setAngle(args.cellulo:getTheta(), 0, 1, 0) self:updateTargetPose() self.kidnapped = true self.kidnappedTimer = KIDNAPPED_STABILIZE_DELAY return self end function SmoothCellulo:updateTargetPose() local x, y, theta = self:getCellulo():getX(), self:getCellulo():getY(), self:getCellulo():getTheta() if not (x and y and theta) then return end -- ensure no value is nil self.targetX, self.targetY, self.targetAngle = x, y, math.rad(theta) end function SmoothCellulo:update(dt) self:updateTargetPose() if self:getCellulo():getKidnapped() == 1 then self.kidnapped = true self.kidnappedTimer = KIDNAPPED_STABILIZE_DELAY end if self.kidnappedTimer then self.kidnappedTimer = self.kidnappedTimer - dt if self.kidnappedTimer <= 0 then self.kidnappedTimer = nil self.kidnapped = false -- released safely with stabilization, reset position to avoid jumping self.x, self.y, self.angle = self.targetX, self.targetY, self.targetAngle end end if not self.kidnapped then local LERP_POSITION = 5 local LERP_ANGLE = 5 self.x, self.y = util.lerp(self.x, self.targetX, LERP_POSITION * dt), util.lerp(self.y, self.targetY, LERP_POSITION * dt) self.angle = util.lerpAngle(self.angle, self.targetAngle, LERP_ANGLE * dt) end end function SmoothCellulo:getX() return self.x end function SmoothCellulo:getY() return self.y end function SmoothCellulo:getTheta() return self.angle end function SmoothCellulo:getConnectionStatus() return self:getCellulo():getConnectionStatus() end function SmoothCellulo:setHapticBackdriveAssist(...) return self:getCellulo():setHapticBackdriveAssist(...) end function SmoothCellulo:setGoalVelocity(...) return self:getCellulo():setGoalVelocity(...) end function SmoothCellulo:setGoalPose(...) return self:getCellulo():setGoalPose(...) end +function SmoothCellulo:setGoalPosition(...) return self:getCellulo():setGoalPosition(...) end function SmoothCellulo:getKidnapped() return self.kidnapped end return SmoothCellulo \ No newline at end of file diff --git a/scenes/menu.lua b/scenes/menu.lua index 542a3be..6f0216b 100644 --- a/scenes/menu.lua +++ b/scenes/menu.lua @@ -1,248 +1,248 @@ local state = lib "stager" local menu = state:new("Menu") local global = require "global" local game = require "scenes.game" -- local pointer = lib "pointer" local util = include "util" local config = require "conf" local Cellulo = require "cellulo" local CelluloPlane = class "CelluloPlane" local SmoothCellulo = class "SmoothCellulo" local world, buttons local handModel local celluloPlane local function refreshSource() pointer:setSource(lovr.headset.getHands()[2] or lovr.headset.getHands()[1] or "head") end local controls = { class "boids.controls.HybridControls", class "boids.controls.AbsoluteControls", class "boids.controls.RelativeControls" } function menu:load() global.ambience:pause() world = lovr.physics.newWorld(0, -9.81, 0, true, {}) buttons = { (class "Button"):new({ world = world, label = "Connect robot from pool", x = 1, y = 2, z = -1, width = 1, height = 0.5, angle = -math.pi/8, ax = 0, ay = 1, az = 0, callback = function(self) local robot = Cellulo:newRobotFromPool() if not robot then global.toastManager:addToast("Couldn't connect to robot") else global.robot = SmoothCellulo:new({ cellulo = robot }) global.playerBoid:setCellulo(global.robot) end end }), (class "Button"):new({ world = world, label = "control method\n" .. global.playerBoid:getControls().name, x = -0.5, y = 1.4, z = -1, width = 0.9, height = 0.5, angle = 0, ax = 0, ay = 1, az = 0, callback = function(self) global.playerBoid:setControls(util.next(controls, global.playerBoid:getControls())) - self:setLabel("control mode\n" .. global.playerBoid:getControls()) + self:setLabel("control mode\n" .. global.playerBoid:getControls().name) end }), (class "Button"):new({ world = world, label = "haptic feedback\n" .. (global.playerBoid:getHapticFeedbackEnabled() and "enabled" or "disabled"), x = 0.5, y = 1.4, z = -1, width = 0.9, height = 0.5, angle = 0, ax = 0, ay = 1, az = 0, callback = function(self) global.playerBoid:setHapticFeedbackEnabled( not global.playerBoid:getHapticFeedbackEnabled() ) self:setLabel("haptic feedback\n" .. (global.playerBoid:getHapticFeedbackEnabled() and "enabled" or "disabled")) end }), (class "Button"):new({ world = world, label = "Back to game", x = 0, y = 0.8, z = -1, width = 2, height = 0.5, angle = 0, ax = 0, ay = 1, az = 0, callback = function() state:pop() end }) } pointer:init({ source = "head", world = world }) handModel = lovr.graphics.newModel("models/oculus_touch/scene.gltf") celluloPlane = CelluloPlane:new(config.CELLULO_PLANE) --local s = "" --for k, v in pairs(game) do s = (s .. tostring(k) .. ", " .. tostring(v) .. "\n") end --assert(false, s) end function menu:unload() world:destroy() global.ambience:resume() end local previousHit function menu:update(dt) refreshSource() pointer:update() world:update(dt) local hit = pointer:getHit() if previousHit and not hit then previousHit.collider:getUserData():setHit(false) end if not previousHit and hit then hit.collider:getUserData():setHit(true) end if previousHit and hit and (previousHit.collider ~= hit.collider) then previousHit.collider:getUserData():setHit(false) hit.collider:getUserData():setHit(true) end previousHit = hit util.foreach(buttons, function(button) button:update(dt) end) --[[ if robot then local x, y = lovr.headset.getAxis("hand/right", "thumbstick") robot:setGoalVelocity(x * 100, -y * 100, 0) end --]] if robot then local status = Cellulo.ConnectionStatus[robot:getConnectionStatus()] if status == "connected" then local paperSize = 500 local x, y = robot:getX(), paperSize - robot:getY() local ox, oy = x - paperSize / 2, y - paperSize / 2 ox, oy = ox / 100, oy / 100 camera:setPosition(ox, 0, -oy) --camera:setAngle() end end return true end function menu:draw() lovr.graphics.setColor(0, 0, 0, 1) lovr.graphics.fill() lovr.graphics.setColor(1, 1, 1) lovr.graphics.setWireframe(false) --lovr.graphics.print(tonumber(Cellulo.lib.totalRobots()), 0, 3, -5) if robot then local status = Cellulo.ConnectionStatus[robot:getConnectionStatus()] lovr.graphics.print(robot:getConnectionStatus(), 0, 3, -5) if status == "connected" then local x, y = robot:getX(), robot:getY() lovr.graphics.print(math.floor(x*100)/100, 4, 2, -5) lovr.graphics.print(math.floor(y*100)/100, 4, 1, -5) end end lovr.graphics.setColor(1, 1, 1) --[[ local results = Cellulo.lib.getScanResultsLength() lovr.graphics.print("Results: " .. results, 0, 2, -5) for i = 1, results do lovr.graphics.print(Cellulo.lib.getScanResultAtIndex(i), 0, 1 + i, -5) end --]] lovr.graphics.setShader(shader) for _, hand in ipairs(lovr.headset.getHands()) do local x, y, z, angle, ax, ay, az = lovr.headset.getPose(hand) lovr.graphics.push() lovr.graphics.translate(x, y, z) lovr.graphics.rotate(angle, ax, ay, az) lovr.graphics.rotate(-math.pi/2, 0, 1, 0) lovr.graphics.rotate(math.pi/2 - 0.75, 0, 0, 1) lovr.graphics.translate(0.03, -0.1, 0) if hand == "hand/left" then lovr.graphics.rotate(math.pi, 0, 0, 1) handModel:draw(0, 0, 0, -0.001, 0, 0, 0, 0) else handModel:draw(0, 0, 0, 0.001, 0, 0, 0, 0) end lovr.graphics.pop() end lovr.graphics.setShader() util.foreachi(buttons, function(button) button:draw() end) lovr.graphics.line(pointer:getPath()) if robot then --robot:draw() end lovr.graphics.print( "game menu", 0, 2.6, -1.4, 0.25 ) if not global.robot then lovr.graphics.print( "no connected cellulo", 0, 2, -1.2, 0.1 ) else local status = Cellulo.ConnectionStatus[global.robot:getConnectionStatus()] lovr.graphics.print(status, -0.6, 2.2, -1.2, 0.1) if status == "connected" then local x, y = global.robot:getX(), global.robot:getY() local a = global.robot:getTheta() lovr.graphics.print(math.floor(x*100)/100, -0.8, 2, -1.2, 0.1) lovr.graphics.print(math.floor(y*100)/100, -0.4, 2, -1.2, 0.1) lovr.graphics.print(math.floor(a*100)/100, 0, 2, -1.2, 0.1) x, y = celluloPlane:normalizedRelative(x, y) lovr.graphics.print(math.floor(x*100)/100, -0.8, 1.9, -1.2, 0.1) lovr.graphics.print(math.floor(y*100)/100, -0.4, 1.9, -1.2, 0.1) end end return true end function menu:buttonpressed(device, button) if button == "trigger" then local hit = pointer:getHit() if hit then local button = hit.collider:getUserData() button.lerpedScale = 1.2 button:getCallback()(button) end end return true end function menu:controlleradded(...) refreshSource(...) end function menu:controllerremoved(...) refreshSource(...) end return menu \ No newline at end of file