mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-19 07:03:16 +00:00
167 lines
4.7 KiB
Lua
167 lines
4.7 KiB
Lua
---Rectangle utilities.
|
|
---@module 'noitapatcher.nsew.rect'
|
|
|
|
---@class Rect
|
|
local rect = {}
|
|
|
|
local ffi = require("ffi")
|
|
local native_dll = require("noitapatcher.nsew.native_dll")
|
|
|
|
ffi.cdef([[
|
|
|
|
struct nsew_rectangle {
|
|
int32_t left;
|
|
int32_t top;
|
|
int32_t right;
|
|
int32_t bottom;
|
|
};
|
|
|
|
|
|
struct nsew_rectangle_optimiser;
|
|
|
|
struct nsew_rectangle_optimiser* rectangle_optimiser_new();
|
|
void rectangle_optimiser_delete(struct nsew_rectangle_optimiser* rectangle_optimiser);
|
|
void rectangle_optimiser_reset(struct nsew_rectangle_optimiser* rectangle_optimiser);
|
|
void rectangle_optimiser_submit(struct nsew_rectangle_optimiser* rectangle_optimiser, struct nsew_rectangle* rectangle);
|
|
void rectangle_optimiser_scan(struct nsew_rectangle_optimiser* rectangle_optimiser);
|
|
int32_t rectangle_optimiser_size(const struct nsew_rectangle_optimiser* rectangle_optimiser);
|
|
const struct nsew_rectangle* rectangle_optimiser_get(const struct nsew_rectangle_optimiser* rectangle_optimiser, int32_t index);
|
|
|
|
|
|
struct lua_nsew_rectangle_optimiser {
|
|
struct nsew_rectangle_optimiser* impl;
|
|
};
|
|
|
|
]])
|
|
|
|
---@class Rectangle_fields
|
|
---@field top integer
|
|
---@field bottom integer
|
|
---@field right integer
|
|
---@field left integer
|
|
|
|
---@alias Rectangle Rectangle_mt | Rectangle_fields
|
|
|
|
---@class Optimiser_fields
|
|
---@field top integer
|
|
---@field bottom integer
|
|
---@field right integer
|
|
---@field left integer
|
|
|
|
---@alias Optimiser Optimiser_fields | Optimiser_mt
|
|
|
|
---@class Rectangle_mt
|
|
local Rectangle_mt_index = {
|
|
---@param r Rectangle
|
|
---@return integer
|
|
area = function(r)
|
|
return (r.right - r.left) * (r.bottom - r.top)
|
|
end,
|
|
---@param r Rectangle
|
|
---@return integer
|
|
height = function(r)
|
|
return r.bottom - r.top
|
|
end,
|
|
---@param r Rectangle
|
|
---@return integer
|
|
width = function(r)
|
|
return r.right - r.left
|
|
end,
|
|
}
|
|
local Rectangle_mt = {
|
|
__index = Rectangle_mt_index,
|
|
}
|
|
|
|
---@type fun(left, top, right, bottom): Rectangle
|
|
---@diagnostic disable-next-line: assign-type-mismatch
|
|
rect.Rectangle = ffi.metatype("struct nsew_rectangle", Rectangle_mt)
|
|
|
|
---Given an iterator that returns rectangles, return an iterator where the
|
|
---rectangle extents never exceed `size`.
|
|
---@param iterator fun(): Rectangle? returning rectangles
|
|
---@param size integer maximum width and height
|
|
---@return fun(): Rectangle? rectangles where the extents never exceed `size`
|
|
function rect.parts(iterator, size)
|
|
local region
|
|
local posx
|
|
local posy
|
|
return function()
|
|
if region == nil then
|
|
region = iterator()
|
|
if region == nil then
|
|
return nil
|
|
end
|
|
posx = region.left
|
|
posy = region.top
|
|
end
|
|
|
|
local endx = math.min(posx + size, region.right)
|
|
local endy = math.min(posy + size, region.bottom)
|
|
|
|
local ret = rect.Rectangle(posx, posy, endx, endy)
|
|
|
|
-- Setup for next iteration: place to the right, wraparound, or
|
|
-- we're done with this region.
|
|
if endx ~= region.right then
|
|
posx = endx
|
|
elseif endy ~= region.bottom then
|
|
posx = region.left
|
|
posy = endy
|
|
else
|
|
region = nil
|
|
end
|
|
|
|
return ret
|
|
end
|
|
end
|
|
|
|
---@class Optimiser_mt
|
|
local Optimiser_mt_index = {
|
|
submit = function(opt, rectangle)
|
|
native_dll.lib.rectangle_optimiser_submit(opt.impl, rectangle)
|
|
end,
|
|
scan = function(opt)
|
|
native_dll.lib.rectangle_optimiser_scan(opt.impl)
|
|
end,
|
|
reset = function(opt)
|
|
native_dll.lib.rectangle_optimiser_reset(opt.impl)
|
|
end,
|
|
size = function(opt)
|
|
return native_dll.lib.rectangle_optimiser_size(opt.impl)
|
|
end,
|
|
get = function(opt, index)
|
|
return native_dll.lib.rectangle_optimiser_get(opt.impl, index)
|
|
end,
|
|
iterate = function(opt)
|
|
local size = native_dll.lib.rectangle_optimiser_size(opt.impl)
|
|
local index = 0
|
|
return function()
|
|
if index >= size then
|
|
return nil
|
|
end
|
|
|
|
local ret = native_dll.lib.rectangle_optimiser_get(opt.impl, index)
|
|
index = index + 1
|
|
return ret
|
|
end
|
|
end,
|
|
}
|
|
|
|
local Optimiser_mt = {
|
|
__gc = function(opt)
|
|
native_dll.lib.rectangle_optimiser_delete(opt.impl)
|
|
end,
|
|
__index = Optimiser_mt_index,
|
|
}
|
|
|
|
---@type fun(unknown): Optimiser
|
|
---@diagnostic disable-next-line: assign-type-mismatch
|
|
rect.Optimiser = ffi.metatype("struct lua_nsew_rectangle_optimiser", Optimiser_mt)
|
|
|
|
---Create a new rectangle Optimiser
|
|
---@return Optimiser optimiser
|
|
function rect.Optimiser_new()
|
|
return rect.Optimiser(native_dll.lib.rectangle_optimiser_new())
|
|
end
|
|
|
|
return rect
|