-- cellulo.lua v0.1 -- Copyright (c) 2019 Ulysse Ramage -- 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 ffi = type(jit) == 'table' and jit.status() and require 'ffi' if not ffi then return end ffi.cdef [[ // Library initialization void initialize(); // Scanner bindings void startScanning(); void stopScanning(); void clearScanResults(); int getScanResultsLength(); const char * getScanResultAtIndex(int index); // Robot creation int64_t newRobotFromMAC(const char * address); int64_t newRobotFromPool(); // Robot bindings void setGoalVelocity(int64_t robot, float vx, float vy, float w); void setGoalPose(int64_t robot, float x, float y, float theta, float v, float w); void setGoalPosition(int64_t robot, float x, float y, float v); void clearTracking(int64_t robot); void clearHapticFeedback(int64_t robot); void setVisualEffect(int64_t robot, int64_t effect, int64_t r, int64_t g, int64_t b, int64_t value); void setCasualBackdriveAssistEnabled(int64_t robot, int64_t enabled); void setHapticBackdriveAssist(int64_t robot, float xAssist, float yAssist, float thetaAssist); void reset(int64_t robot); void simpleVibrate(int64_t robot, float iX, float iY, float iTheta, int64_t period, int64_t duration); float getX(int64_t robot); float getY(int64_t robot); float getTheta(int64_t robot); int64_t getKidnapped(int64_t robot); void destroyRobot(int64_t robot); // Check robot count int64_t totalRobots(); int64_t remainingRobots(); // Debug const char * getMacAddr(int64_t robot); int getConnectionStatus(int64_t robot); ]] if lovr.getOS() == "macOS" then ffi.load("./libcellulo-unity.1.0.0.dylib", true) elseif lovr.getOS() == "Android" then --ffi.load("qtforandroid", true) --[[ ffi.load("Qt5Core", true) ffi.load("Qt5AndroidExtras", true) ffi.load("Qt5Bluetooth", true) ffi.load("qtforandroid", true) --]] end local lib = ffi.C local new, cast, typeof, istype = ffi.new, ffi.cast, ffi.typeof, ffi.istype -- local Cellulo, CelluloRobot --[[ Cellulo This class wraps the entire library and acts as a robot manager, from which we can pull robots from the pool or create them from a MAC address (unsupported on Android) ]]-- Cellulo = { ffi = ffi, lib = lib } setmetatable(Cellulo, Cellulo) Cellulo.ConnectionStatus = {} Cellulo.ConnectionStatus[0] = "disconnected" Cellulo.ConnectionStatus[1] = "connecting" Cellulo.ConnectionStatus[2] = "connected" local function newRobot(mode, arg) local celluloRobot = {} setmetatable(celluloRobot, CelluloRobot) celluloRobot.id = mode == "mac" and lib.newRobotFromMAC(address) or lib.newRobotFromPool() if not checkId(celluloRobot.id) then debug.log("WARNING: using zero pointer as a Cellulo object, meaning the object creation failed.") return end return celluloRobot end function Cellulo:newRobotFromMAC(address) return newRobot("mac", address) end function Cellulo:newRobotFromPool() return newRobot("pool") end function checkId(id) return id and id ~= 0 end --[[ Cellulo Robot This class represents a single ]]-- CelluloRobot = { __index = function(self, key, args) return function(...) assert(lib[key], "method " .. key .. "does not exist in Cellulo library") if not checkId(self.id) then debug.log("WARNING: Robot is broken. Cannot make API call.") return end local args = {...} args[1] = args[1].id return lib[key](unpack(args)) end end } setmetatable(CelluloRobot, CelluloRobot) function CelluloRobot:draw() end return Cellulo