You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
3.5 KiB
Lua

local base = string.match(..., "(.-)[^%.]+%.[^%.]+$")
local enums = require(base.."ev_api.decls").enums
local eh = require(base.."helper.enum")
local ffi = require("ffi")
local fh = require(base.."helper.ffi_struct")
local ff_trigger = require(base.."ev_api.ff_trigger").new
local ff_replay = require(base.."ev_api.ff_replay").new
local ff_constant_effect = require(base.."ev_api.ff_constant_effect").new
local ff_ramp_effect = require(base.."ev_api.ff_ramp_effect").new
local ff_condition_effect = require(base.."ev_api.ff_condition_effect").new
local ff_periodic_effect = require(base.."ev_api.ff_periodic_effect").new
local ff_rumble_effect = require(base.."ev_api.ff_rumble_effect").new
local format = string.format
local mt, index = {}, {}
-- COMMON CRAP
local FF_EFFECT = eh.filter_min_max(
enums.FF, enums.FF.EFFECT_MIN, enums.FF.EFFECT_MAX)
index.FF_EFFECT = FF_EFFECT
fh.gen_enum_accessor(index, FF_EFFECT, "type")
fh.gen_raw_accessor(index, "id")
local DIRECTION = eh.make_enum{
{"DOWN", 0}, {"LEFT", 0x4000}, {"UP", 0x8000}, {"RIGHT", 0xc000},
}
index.DIRECTION = DIRECTION
fh.gen_enum_accessor(index, DIRECTION, "direction")
fh.gen_wrap_accessor(index, "trigger", ff_trigger)
fh.gen_wrap_accessor(index, "replay", ff_replay)
-- UNION MAGIC
local function check_union(self, name, exp_type)
if self.raw.type ~= exp_type then
error("Wrong enum variant "..self.type.." while getting "..name)
end
end
local function typechecked_acc(name, exp_type, wrap)
index["get_"..name] = function(self)
check_union(self, name, exp_type)
return wrap(self.raw.u[name])
end
index["set_"..name] = function(self, ...)
check_union(self, name, exp_type)
self.raw.u[name] = wrap(...).raw
end
end
typechecked_acc("constant", FF_EFFECT.CONSTANT, ff_constant_effect)
typechecked_acc("ramp", FF_EFFECT.RAMP, ff_ramp_effect)
typechecked_acc("periodic", FF_EFFECT.PERIODIC, ff_periodic_effect)
local valid_conditions = {
[FF_EFFECT.SPRING] = true, [FF_EFFECT.FRICTION] = true,
[FF_EFFECT.DAMPER] = true, [FF_EFFECT.INERTIA] = true,
}
for i=0,1 do
name = "condition"..i
index["get_"..name] = function(self)
if not valid_conditions[self.raw.type] then
error("Wrong enum variant "..self.type.." while getting "..name)
end
return ff_condition_effect(self.raw.u.condition[i])
end
index["set_"..name] = function(self, ...)
if not valid_conditions[self.raw.type] then
error("Wrong enum variant "..self.type.." while getting "..name)
end
self.raw.u.condition[i] = ff_condition_effect(...).raw
end
end
typechecked_acc("rumble", FF_EFFECT.RUMBLE, ff_rumble_effect)
-- MISC
-- hack: we need to set type before setting code
local orig_set = fh.base_funcs.set_from_table
function index:set_from_table(tbl)
if tbl.type then self.type = tbl.type end
orig_set(self, tbl)
end
function index:tostring()
local t, subs = self.type, ""
if t == "CONSTANT" then subs = ", constant="..self.constant:tostring()
elseif t == "RAMP" then subs = ", ramp="..self.ramp:tostring()
elseif t == "PERIODIC" then subs = ", periodic="..self.periodic:tostring()
elseif t == "SPRING" or t == "FRICTION" or t == "DAMPER" or t == "INERTIA" then
subs = format(", condition0=%s, condition1=%s",
self.condition0, self.condition1)
elseif t == "RUMBLE" then subs = ", rumble="..self.rumble:tostring() end
return format(
"ff_effect{type=%s, id=%d, direction=%s, trigger=%s, replay=%s%s}",
self.type, self.id, self.direction, self.trigger, self.replay, subs)
end
mt.__tostring = index.tostring
return fh.base(mt, index, ffi.typeof("struct ff_effect"))