inputor

Evdev remapping utility in lua
git clone https://git.neptards.moe/u3shit/inputor.git
Log | Files | Refs

ff_effect.lua (3635B)


      1 local base = string.match(..., "(.-)[^%.]+%.[^%.]+$")
      2 local enums = require(base.."ev_api.decls").enums
      3 local eh = require(base.."helper.enum")
      4 local ffi = require("ffi")
      5 local fh = require(base.."helper.ffi_struct")
      6 
      7 local ff_trigger = require(base.."ev_api.ff_trigger").new
      8 local ff_replay = require(base.."ev_api.ff_replay").new
      9 
     10 local ff_constant_effect = require(base.."ev_api.ff_constant_effect").new
     11 local ff_ramp_effect = require(base.."ev_api.ff_ramp_effect").new
     12 local ff_condition_effect = require(base.."ev_api.ff_condition_effect").new
     13 local ff_periodic_effect = require(base.."ev_api.ff_periodic_effect").new
     14 local ff_rumble_effect = require(base.."ev_api.ff_rumble_effect").new
     15 
     16 local format = string.format
     17 
     18 local mt, index = {}, {}
     19 
     20 -- COMMON CRAP
     21 local FF_EFFECT = eh.filter_min_max(
     22   enums.FF, enums.FF.EFFECT_MIN, enums.FF.EFFECT_MAX)
     23 index.FF_EFFECT = FF_EFFECT
     24 fh.gen_enum_accessor(index, FF_EFFECT, "type")
     25 fh.gen_raw_accessor(index, "id")
     26 
     27 local DIRECTION = eh.make_enum{
     28   {"DOWN", 0}, {"LEFT", 0x4000}, {"UP", 0x8000}, {"RIGHT", 0xc000},
     29 }
     30 index.DIRECTION = DIRECTION
     31 fh.gen_enum_accessor(index, DIRECTION, "direction")
     32 
     33 fh.gen_wrap_accessor(index, "trigger", ff_trigger)
     34 fh.gen_wrap_accessor(index, "replay", ff_replay)
     35 
     36 -- UNION MAGIC
     37 local function check_union(self, name, exp_type)
     38   if self.raw.type ~= exp_type then
     39     error("Wrong enum variant "..self.type.." while getting "..name)
     40   end
     41 end
     42 
     43 local function typechecked_acc(name, exp_type, wrap)
     44   index["get_"..name] = function(self)
     45     check_union(self, name, exp_type)
     46     return wrap(self.raw.u[name])
     47   end
     48   index["set_"..name] = function(self, ...)
     49     check_union(self, name, exp_type)
     50     self.raw.u[name] = wrap(...).raw
     51   end
     52 end
     53 
     54 typechecked_acc("constant", FF_EFFECT.CONSTANT, ff_constant_effect)
     55 typechecked_acc("ramp", FF_EFFECT.RAMP, ff_ramp_effect)
     56 typechecked_acc("periodic", FF_EFFECT.PERIODIC, ff_periodic_effect)
     57 
     58 local valid_conditions = {
     59   [FF_EFFECT.SPRING] = true, [FF_EFFECT.FRICTION] = true,
     60   [FF_EFFECT.DAMPER] = true, [FF_EFFECT.INERTIA] = true,
     61 }
     62 for i=0,1 do
     63   name = "condition"..i
     64   index["get_"..name] = function(self)
     65     if not valid_conditions[self.raw.type] then
     66       error("Wrong enum variant "..self.type.." while getting "..name)
     67     end
     68     return ff_condition_effect(self.raw.u.condition[i])
     69   end
     70   index["set_"..name] = function(self, ...)
     71     if not valid_conditions[self.raw.type] then
     72       error("Wrong enum variant "..self.type.." while getting "..name)
     73     end
     74     self.raw.u.condition[i] = ff_condition_effect(...).raw
     75   end
     76 end
     77 
     78 typechecked_acc("rumble", FF_EFFECT.RUMBLE, ff_rumble_effect)
     79 
     80 -- MISC
     81 -- hack: we need to set type before setting code
     82 local orig_set = fh.base_funcs.set_from_table
     83 function index:set_from_table(tbl)
     84   if tbl.type then self.type = tbl.type end
     85   orig_set(self, tbl)
     86 end
     87 
     88 function index:tostring()
     89   local t, subs = self.type, ""
     90   if t == "CONSTANT" then subs = ", constant="..self.constant:tostring()
     91   elseif t == "RAMP" then subs = ", ramp="..self.ramp:tostring()
     92   elseif t == "PERIODIC" then subs = ", periodic="..self.periodic:tostring()
     93   elseif t == "SPRING" or t == "FRICTION" or t == "DAMPER" or t == "INERTIA" then
     94     subs = format(", condition0=%s, condition1=%s",
     95                   self.condition0, self.condition1)
     96   elseif t == "RUMBLE" then subs = ", rumble="..self.rumble:tostring() end
     97 
     98   return format(
     99     "ff_effect{type=%s, id=%d, direction=%s, trigger=%s, replay=%s%s}",
    100     self.type, self.id, self.direction, self.trigger, self.replay, subs)
    101 end
    102 mt.__tostring = index.tostring
    103 
    104 return fh.base(mt, index, ffi.typeof("struct ff_effect"))