789 lines
20 KiB
Lua
789 lines
20 KiB
Lua
local mpp_util = require("mpp.mpp_util")
|
|
local color = require("mpp.color")
|
|
|
|
local floor, ceil = math.floor, math.ceil
|
|
local min, max = math.min, math.max
|
|
local EAST, NORTH, SOUTH, WEST = mpp_util.directions()
|
|
|
|
local render_util = {}
|
|
|
|
---@class RendererParams
|
|
---@field origin MapPosition?
|
|
---@field target MapPosition?
|
|
---@field x number?
|
|
---@field y number?
|
|
---@field w number?
|
|
---@field h number?
|
|
---@field r number?
|
|
---@field color Color?
|
|
---@field width number?
|
|
---@field c Color?
|
|
---@field left_top MapPosition?
|
|
---@field right_bottom MapPosition?
|
|
|
|
---this went off the rails
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
---@return MppRendering
|
|
function render_util.renderer(event)
|
|
|
|
---@param t RendererParams
|
|
local function parametrizer(t, overlay)
|
|
|
|
for k, v in pairs(overlay or {}) do t[k] = v end
|
|
if t.x and t.y then t.origin = {t.x, t.y} end
|
|
local target = t.origin or t.left_top --[[@as MapPosition]]
|
|
local left_top, right_bottom = t.left_top or t.origin or target, t.right_bottom or t.origin
|
|
|
|
if t.origin and t.w or t.h then
|
|
t.w, t.h = t.w or t.h, t.h or t.w
|
|
right_bottom = {(target[1] or target.x) + t.w, (target[2] or target.y) + t.h}
|
|
elseif t.r then
|
|
local r = t.r
|
|
local ox, oy = target[1] or target.x, target[2] or target.y
|
|
left_top = {ox-r, oy-r}
|
|
right_bottom = {ox+r, oy+r}
|
|
end
|
|
|
|
local new = {
|
|
surface = event.surface,
|
|
players = {event.player_index},
|
|
filled = false,
|
|
radius = t.r or 1,
|
|
color = t.c or t.color or {1, 1, 1},
|
|
left_top = left_top,
|
|
right_bottom = right_bottom,
|
|
target = target, -- circles
|
|
from = left_top,
|
|
to = right_bottom, -- lines
|
|
width = 1,
|
|
}
|
|
for k, v in pairs(t) do new[k]=v end
|
|
for _, v in ipairs{"x", "y", "h", "w", "r", "origin"} do new[v]=nil end
|
|
return new
|
|
end
|
|
|
|
local meta_renderer_meta = {}
|
|
meta_renderer_meta.__index = function(self, k)
|
|
return function(t, t2)
|
|
return {
|
|
rendering[k](
|
|
parametrizer(t, t2)
|
|
)
|
|
}
|
|
end end
|
|
local rendering = setmetatable({}, meta_renderer_meta)
|
|
|
|
---@class MppRendering
|
|
local rendering_extension = {}
|
|
|
|
---Draws an x between left_top and right_bottom
|
|
---@param params RendererParams
|
|
function rendering_extension.draw_cross(params)
|
|
rendering.draw_line(params)
|
|
rendering.draw_line({
|
|
width = params.width,
|
|
color = params.color,
|
|
left_top={
|
|
params.right_bottom[1],
|
|
params.left_top[2]
|
|
},
|
|
right_bottom={
|
|
params.left_top[1],
|
|
params.right_bottom[2],
|
|
}
|
|
})
|
|
end
|
|
|
|
function rendering_extension.draw_rectangle_dashed(params)
|
|
rendering.draw_line(params, {
|
|
from={params.left_top[1], params.left_top[2]},
|
|
to={params.right_bottom[1], params.left_top[2]},
|
|
dash_offset = 0.0,
|
|
})
|
|
rendering.draw_line(params, {
|
|
from={params.left_top[1], params.right_bottom[2]},
|
|
to={params.right_bottom[1], params.right_bottom[2]},
|
|
dash_offset = 0.5,
|
|
})
|
|
rendering.draw_line(params, {
|
|
from={params.right_bottom[1], params.left_top[2]},
|
|
to={params.right_bottom[1], params.right_bottom[2]},
|
|
dash_offset = 0.0,
|
|
})
|
|
rendering.draw_line(params, {
|
|
from={params.left_top[1], params.left_top[2]},
|
|
to={params.left_top[1], params.right_bottom[2]},
|
|
dash_offset = 0.5,
|
|
})
|
|
end
|
|
|
|
local meta = {}
|
|
function meta:__index(k)
|
|
return function(t, t2)
|
|
if rendering_extension[k] then
|
|
rendering_extension[k](parametrizer(t, t2))
|
|
else
|
|
rendering[k](parametrizer(t, t2))
|
|
end
|
|
end
|
|
end
|
|
|
|
return setmetatable({}, meta)
|
|
end
|
|
|
|
function render_util.draw_clear_rendering(player_data, event)
|
|
rendering.clear("mining-patch-planner")
|
|
end
|
|
|
|
---Draws the properties of a mining drill
|
|
---@param player_data PlayerData
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
function render_util.draw_drill_struct(player_data, event)
|
|
|
|
local renderer = render_util.renderer(event)
|
|
|
|
local fx1, fy1 = event.area.left_top.x, event.area.left_top.y
|
|
fx1, fy1 = floor(fx1), floor(fy1)
|
|
local x, y = fx1 + 0.5, fy1 + 0.5
|
|
local fx2, fy2 = event.area.right_bottom.x, event.area.right_bottom.y
|
|
fx2, fy2 = ceil(fx2), ceil(fy2)
|
|
|
|
--renderer.draw_cross{x=fx1, y=fy1, w=fx2-fx1, h=fy2-fy1}
|
|
--renderer.draw_cross{x=fx1, y=fy1, w=2}
|
|
|
|
local drill = mpp_util.miner_struct(player_data.choices.miner_choice)
|
|
|
|
renderer.draw_circle{
|
|
x = fx1 + drill.drop_pos.x,
|
|
y = fy1 + drill.drop_pos.y,
|
|
c = {0, 1, 0},
|
|
r = 0.2,
|
|
}
|
|
|
|
-- drop pos
|
|
renderer.draw_cross{
|
|
x = fx1 + 0.5 + drill.out_x,
|
|
y = fy1 + 0.5 + drill.out_y,
|
|
r = 0.3,
|
|
}
|
|
|
|
for _, pos in pairs(drill.output_rotated) do
|
|
renderer.draw_cross{
|
|
x = fx1 + 0.5 + pos[1],
|
|
y = fy1 + 0.5 + pos[2],
|
|
r = 0.15,
|
|
width = 3,
|
|
c={0, 0, 0, .5},
|
|
}
|
|
end
|
|
|
|
renderer.draw_line{
|
|
from={x + drill.x, y},
|
|
to={x + drill.x, y + 2},
|
|
width = 2, color={0.5, 0.5, 0.5}
|
|
}
|
|
renderer.draw_line{
|
|
from={x + drill.x, y},
|
|
to={x + drill.x-.5, y + .65},
|
|
width = 2, color={0.5, 0.5, 0.5}
|
|
}
|
|
renderer.draw_line{
|
|
from={x + drill.x, y},
|
|
to={x + drill.x+.5, y + .65},
|
|
width = 2, color={0.5, 0.5, 0.5}
|
|
}
|
|
|
|
|
|
-- drill origin
|
|
renderer.draw_circle{
|
|
x = fx1 + 0.5,
|
|
y = fy1 + 0.5,
|
|
width = 2,
|
|
r = 0.4,
|
|
}
|
|
|
|
renderer.draw_text{
|
|
target={fx1 + .5, fy1 + .5},
|
|
text = "(0, 0)",
|
|
alignment = "center",
|
|
vertical_alignment="middle",
|
|
scale = 0.6,
|
|
}
|
|
|
|
-- negative extent - cyan
|
|
renderer.draw_cross{
|
|
x = fx1 +.5 + drill.extent_negative,
|
|
y = fy1 +.5 + drill.extent_negative,
|
|
r = 0.25,
|
|
c = {0, 0.8, 0.8},
|
|
}
|
|
|
|
-- positive extent - purple
|
|
renderer.draw_cross{
|
|
x = fx1 +.5 + drill.extent_positive,
|
|
y = fy1 +.5 + drill.extent_positive,
|
|
r = 0.25,
|
|
c = {1, 0, 1},
|
|
}
|
|
|
|
renderer.draw_rectangle{
|
|
x=fx1,
|
|
y=fy1,
|
|
w=drill.size,
|
|
h=drill.size,
|
|
width=3,
|
|
gap_length=0.5,
|
|
dash_length=0.5,
|
|
}
|
|
|
|
renderer.draw_rectangle_dashed{
|
|
x=fx1 + drill.extent_negative,
|
|
y=fy1 + drill.extent_negative,
|
|
w=drill.area,
|
|
h=drill.area,
|
|
c={0.5, 0.5, 0.5},
|
|
width=5,
|
|
gap_length=0.5,
|
|
dash_length=0.5,
|
|
}
|
|
|
|
if drill.supports_fluids then
|
|
-- pipe connections
|
|
renderer.draw_line{
|
|
width=4, color = {0, .7, 1},
|
|
from={fx1-.3, y+drill.pipe_left-.5},
|
|
to={fx1-.3, y+drill.pipe_left+.5},
|
|
}
|
|
renderer.draw_line{
|
|
width=4, color = {.7, .7, 0},
|
|
from={fx1+drill.size+.3, y+drill.pipe_left-.5},
|
|
to={fx1+drill.size+.3, y+drill.pipe_left+.5},
|
|
}
|
|
end
|
|
|
|
renderer.draw_text{
|
|
target={fx1 + drill.extent_negative, fy1 + drill.extent_negative-1.5},
|
|
text = string.format("skip_outer: %s", drill.skip_outer),
|
|
alignment = "left",
|
|
vertical_alignment="middle",
|
|
}
|
|
|
|
renderer.draw_circle{x = fx1, y = fy1, r = 0.1}
|
|
--renderer.draw_circle{ x = fx2, y = fy2, r = 0.15, color={1, 0, 0} }
|
|
end
|
|
|
|
---Preview the pole coverage
|
|
---@param player_data PlayerData
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
function render_util.draw_pole_layout(player_data, event)
|
|
rendering.clear("mining-patch-planner")
|
|
|
|
local renderer = render_util.renderer(event)
|
|
|
|
local fx1, fy1 = event.area.left_top.x, event.area.left_top.y
|
|
fx1, fy1 = floor(fx1), floor(fy1)
|
|
|
|
--renderer.draw_cross{x=fx1, y=fy1, w=fx2-fx1, h=fy2-fy1}
|
|
--renderer.draw_cross{x=fx1, y=fy1, w=2}
|
|
|
|
local drill = mpp_util.miner_struct(player_data.choices.miner_choice)
|
|
local pole = mpp_util.pole_struct(player_data.choices.pole_choice)
|
|
|
|
local function draw_lane(x, y, count)
|
|
for i = 0, count-1 do
|
|
renderer.draw_rectangle{
|
|
x = x + drill.size * i + 0.15 , y = y+.15,
|
|
w = drill.size-.3, h=1-.3,
|
|
color = i % 2 == 0 and {143/255, 86/255, 59/255} or {223/255, 113/255, 38/255},
|
|
width=2,
|
|
}
|
|
end
|
|
|
|
---@diagnostic disable-next-line: param-type-mismatch
|
|
local coverage = mpp_util.calculate_pole_coverage(player_data.choices, count, 1)
|
|
|
|
renderer.draw_circle{
|
|
x=x+.5, y=y-0.5, radius = .25, color={0.7, 0.7, 0.7},
|
|
}
|
|
for i = coverage.pole_start, coverage.full_miner_width, coverage.pole_step do
|
|
renderer.draw_circle{
|
|
x = x + i + .5,
|
|
y = y - .5,
|
|
radius = 0.3, width=2,
|
|
color = {0, 1, 1},
|
|
}
|
|
renderer.draw_line{
|
|
x = x + i +.5 - pole.supply_width / 2+.2,
|
|
y = y - .2,
|
|
h = 0,
|
|
w = pole.supply_width-.4,
|
|
color = {0, 1, 1},
|
|
width = 2,
|
|
}
|
|
renderer.draw_line{
|
|
x = x + i +.5 - pole.supply_width / 2 + .2,
|
|
y = y - .7,
|
|
h = .5,
|
|
w = 0,
|
|
color = {0, 1, 1},
|
|
width = 2,
|
|
}
|
|
renderer.draw_line{
|
|
x = x + i +.5 + pole.supply_width / 2 - .2,
|
|
y = y - .7,
|
|
h = .5,
|
|
w = 0,
|
|
color = {0, 1, 1},
|
|
width = 2,
|
|
}
|
|
end
|
|
end
|
|
|
|
for i = 1, 10 do
|
|
draw_lane(fx1, fy1+(i-1)*3, i)
|
|
end
|
|
|
|
end
|
|
|
|
---Preview the pole coverage
|
|
---@param player_data PlayerData
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
function render_util.draw_pole_layout_compact(player_data, event)
|
|
rendering.clear("mining-patch-planner")
|
|
|
|
local renderer = render_util.renderer(event)
|
|
|
|
local fx1, fy1 = event.area.left_top.x, event.area.left_top.y
|
|
fx1, fy1 = floor(fx1), floor(fy1)
|
|
|
|
--renderer.draw_cross{x=fx1, y=fy1, w=fx2-fx1, h=fy2-fy1}
|
|
--renderer.draw_cross{x=fx1, y=fy1, w=2}
|
|
|
|
local drill = mpp_util.miner_struct(player_data.choices.miner_choice)
|
|
local pole = mpp_util.pole_struct(player_data.choices.pole_choice)
|
|
|
|
local function draw_lane(x, y, count)
|
|
for i = 0, count-1 do
|
|
renderer.draw_rectangle{
|
|
x = x + drill.size * i + 0.15 , y = y+.15,
|
|
w = drill.size-.3, h=1-.3,
|
|
color = i % 2 == 0 and {143/255, 86/255, 59/255} or {223/255, 113/255, 38/255},
|
|
width=2,
|
|
}
|
|
end
|
|
|
|
---@diagnostic disable-next-line: param-type-mismatch
|
|
local coverage = mpp_util.calculate_pole_spacing(player_data.choices, count, 1)
|
|
|
|
renderer.draw_circle{
|
|
x=x+.5, y=y-0.5, radius = .25, color={0.7, 0.7, 0.7},
|
|
}
|
|
for i = coverage.pole_start, coverage.full_miner_width, coverage.pole_step do
|
|
renderer.draw_circle{
|
|
x = x + i + .5,
|
|
y = y - .5,
|
|
radius = 0.3, width=2,
|
|
color = {0, 1, 1},
|
|
}
|
|
renderer.draw_line{
|
|
x = x + i +.5 - pole.supply_width / 2+.2,
|
|
y = y - .2,
|
|
h = 0,
|
|
w = pole.supply_width-.4,
|
|
color = {0, 1, 1},
|
|
width = 2,
|
|
}
|
|
renderer.draw_line{
|
|
x = x + i +.5 - pole.supply_width / 2 + .2,
|
|
y = y - .7,
|
|
h = .5,
|
|
w = 0,
|
|
color = {0, 1, 1},
|
|
width = 2,
|
|
}
|
|
renderer.draw_line{
|
|
x = x + i +.5 + pole.supply_width / 2 - .2,
|
|
y = y - .7,
|
|
h = .5,
|
|
w = 0,
|
|
color = {0, 1, 1},
|
|
width = 2,
|
|
}
|
|
end
|
|
end
|
|
|
|
for i = 1, 10 do
|
|
draw_lane(fx1, fy1+(i-1)*3, i)
|
|
end
|
|
|
|
end
|
|
|
|
---Displays the labels of built things on the grid
|
|
---@param player_data PlayerData
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
function render_util.draw_built_things(player_data, event)
|
|
rendering.clear("mining-patch-planner")
|
|
|
|
local renderer = render_util.renderer(event)
|
|
|
|
local state = player_data.last_state
|
|
|
|
if not state then return end
|
|
|
|
local C = state.coords
|
|
local G = state.grid
|
|
|
|
for _, row in pairs(G) do
|
|
for _, tile in pairs(row) do
|
|
---@cast tile GridTile
|
|
local thing = tile.built_on
|
|
if thing then
|
|
-- renderer.draw_circle{
|
|
-- x = C.gx + tile.x, y = C.gy + tile.y,
|
|
-- w = 1,
|
|
-- color = {0, 0.5, 0, 0.1},
|
|
-- r = 0.5,
|
|
-- }
|
|
renderer.draw_rectangle{
|
|
x = C.ix1 + tile.x -.9, y = C.iy1 + tile.y -.9,
|
|
w = .8,
|
|
color = {0, 0.2, 0, 0.1},
|
|
}
|
|
renderer.draw_text{
|
|
x = C.gx + tile.x, y = C.gy + tile.y - .3,
|
|
alignment = "center",
|
|
vertical_alignment = "top",
|
|
--vertical_alignment = tile.x % 2 == 1 and "top" or "bottom",
|
|
text = thing,
|
|
scale = 0.6,
|
|
}
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
---@param player_data PlayerData
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
function render_util.draw_drill_convolution(player_data, event)
|
|
rendering.clear("mining-patch-planner")
|
|
|
|
local renderer = render_util.renderer(event)
|
|
|
|
local fx1, fy1 = event.area.left_top.x, event.area.left_top.y
|
|
fx1, fy1 = floor(fx1), floor(fy1)
|
|
|
|
local state = player_data.last_state
|
|
if not state then return end
|
|
|
|
local C = state.coords
|
|
local grid = state.grid
|
|
|
|
for _, row in pairs(grid) do
|
|
for _, tile in pairs(row) do
|
|
---@cast tile GridTile
|
|
--local c1, c2 = tile.neighbor_counts[m_size], tile.neighbor_counts[m_area]
|
|
local c1, c2 = tile.neighbors_inner, tile.neighbors_outer
|
|
if c1 == 0 and c2 == 0 then goto continue end
|
|
|
|
rendering.draw_circle{
|
|
surface = state.surface, filled=false, color = {0.3, 0.3, 1},
|
|
width=1, radius = 0.5,
|
|
target={C.gx + tile.x, C.gy + tile.y},
|
|
}
|
|
local stagger = (.5 - (tile.x % 2)) * .25
|
|
local col = c1 == 0 and {0.3, 0.3, 0.3} or {0.6, 0.6, 0.6}
|
|
rendering.draw_text{
|
|
surface = state.surface, filled = false, color = col,
|
|
target={C.gx + tile.x, C.gy + tile.y + stagger},
|
|
text = string.format("%i,%i", c1, c2),
|
|
alignment = "center",
|
|
vertical_alignment="middle",
|
|
}
|
|
|
|
::continue::
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
|
|
---@param player_data PlayerData
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
function render_util.draw_power_grid(player_data, event)
|
|
local renderer = render_util.renderer(event)
|
|
|
|
local fx1, fy1 = event.area.left_top.x, event.area.left_top.y
|
|
fx1, fy1 = floor(fx1), floor(fy1)
|
|
|
|
local state = player_data.last_state
|
|
if not state then return end
|
|
---@cast state SimpleState
|
|
|
|
local C = state.coords
|
|
local grid = state.grid
|
|
|
|
local connectivity = state.power_connectivity
|
|
if not connectivity then
|
|
game.print("No connectivity exists")
|
|
return
|
|
end
|
|
local rendered = {}
|
|
|
|
for set_id, set in pairs(connectivity) do
|
|
local set_color = color.hue_sequence(set_id)
|
|
if set_id == 0 then set_color = {1, 1, 1} end
|
|
for pole, _ in pairs(set) do
|
|
---@cast pole GridPole
|
|
-- if rendered[pole] then goto continue end
|
|
-- rendered[pole] = true
|
|
local pole_color = set_color
|
|
-- if not pole.backtracked and not pole.has_consumers then
|
|
-- pole_color = {0, 0, 0}
|
|
-- end
|
|
|
|
renderer.draw_circle{
|
|
surface = state.surface,
|
|
filled = not pole.backtracked,
|
|
color = pole_color,
|
|
width = 5,
|
|
target = {C.gx + pole.grid_x, C.gy + pole.grid_y},
|
|
radius = 0.65,
|
|
}
|
|
renderer.draw_text{
|
|
surface = state.surface,
|
|
target={C.gx + pole.grid_x, C.gy + pole.grid_y},
|
|
text = set_id,
|
|
alignment = "center",
|
|
vertical_alignment="middle",
|
|
scale = 2,
|
|
}
|
|
renderer.draw_text{
|
|
surface = state.surface,
|
|
target={C.gx + pole.grid_x, C.gy + pole.grid_y-1.25},
|
|
text = ("%i,%i"):format(pole.ix, pole.iy),
|
|
alignment = "center",
|
|
vertical_alignment="middle",
|
|
scale = 2,
|
|
}
|
|
::continue::
|
|
end
|
|
end --]]
|
|
|
|
end
|
|
|
|
---@param player_data PlayerData
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
function render_util.draw_centricity(player_data, event)
|
|
local renderer = render_util.renderer(event)
|
|
|
|
local fx1, fy1 = event.area.left_top.x, event.area.left_top.y
|
|
fx1, fy1 = floor(fx1), floor(fy1)
|
|
|
|
local state = player_data.last_state
|
|
if not state then return end
|
|
|
|
local C = state.coords
|
|
local grid = state.grid
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
---@param player_data PlayerData
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
function render_util.draw_blueprint_data(player_data, event)
|
|
local renderer = render_util.renderer(event)
|
|
|
|
local fx1, fy1 = event.area.left_top.x, event.area.left_top.y
|
|
fx1, fy1 = floor(fx1), floor(fy1)
|
|
local x, y = fx1 + 0.5, fy1 + 0.5
|
|
|
|
local id = player_data.choices.blueprint_choice and player_data.choices.blueprint_choice.item_number
|
|
if not id then return end
|
|
local bp = player_data.blueprints.cache[id]
|
|
if not bp then return end
|
|
|
|
renderer.draw_line{x = fx1, y = fy1-1, w = 0, h = 2, width = 7, color={0, 0, 0}}
|
|
renderer.draw_line{x = fx1-1, y = fy1, w = 2, h = 0, width = 7, color={0, 0, 0}}
|
|
|
|
renderer.draw_rectangle{
|
|
x = fx1,
|
|
y = fy1,
|
|
w = bp.w,
|
|
h = bp.h,
|
|
}
|
|
|
|
for _, ent in pairs(bp.entities) do
|
|
local struct = mpp_util.entity_struct(ent.name)
|
|
local clr = {1, 1, 1}
|
|
if ent.capstone_x and ent.capstone_y then
|
|
clr = {0, 1, 1}
|
|
elseif ent.capstone_x then
|
|
clr = {0, 1, 0}
|
|
elseif ent.capstone_y then
|
|
clr = {0, 0, 1}
|
|
end
|
|
renderer.draw_circle{
|
|
x = fx1 + ent.position.x,
|
|
y = fy1 + ent.position.y,
|
|
r = struct.size / 2,
|
|
color = clr,
|
|
}
|
|
end
|
|
|
|
end
|
|
|
|
---@param player_data PlayerData
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
function render_util.draw_deconstruct_preview(player_data, event)
|
|
local renderer = render_util.renderer(event)
|
|
|
|
local fx1, fy1 = event.area.left_top.x, event.area.left_top.y
|
|
fx1, fy1 = floor(fx1), floor(fy1)
|
|
|
|
local state = player_data.last_state
|
|
if not state then return end
|
|
|
|
local c = state.coords
|
|
local grid = state.grid
|
|
|
|
local layout = algorithm.layouts[state.layout_choice]
|
|
if not layout._get_deconstruction_objects then return end
|
|
local objects = layout:_get_deconstruction_objects(state)
|
|
|
|
local DIR = state.direction_choice
|
|
|
|
for _, t in pairs(objects) do
|
|
for _, object in ipairs(t) do
|
|
---@cast object GhostSpecification
|
|
local extent_w = object.extent_w or object.radius or 0.5
|
|
local extent_h = object.extent_h or extent_w
|
|
|
|
local x1, y1 = object.grid_x-extent_w, object.grid_y-extent_h
|
|
local x2, y2 = object.grid_x+extent_w, object.grid_y+extent_h
|
|
|
|
x1, y1 = mpp_util.revert_ex(c.gx, c.gy, DIR, x1, y1, c.tw, c.th)
|
|
x2, y2 = mpp_util.revert_ex(c.gx, c.gy, DIR, x2, y2, c.tw, c.th)
|
|
|
|
rendering.draw_rectangle{
|
|
surface=state.surface,
|
|
players={state.player},
|
|
filled=false,
|
|
width=3,
|
|
color={1, 0, 0},
|
|
left_top={x1+.1,y1+.1},
|
|
right_bottom={x2-.1,y2-.1},
|
|
}
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
---@param player_data PlayerData
|
|
---@param event EventData.on_player_reverse_selected_area
|
|
function render_util.draw_can_place_entity(player_data, event)
|
|
local renderer = render_util.renderer(event)
|
|
|
|
local fx1, fy1 = event.area.left_top.x, event.area.left_top.y
|
|
fx1, fy1 = floor(fx1), floor(fy1)
|
|
local x, y = fx1 + 0.5, fy1 + 0.5
|
|
|
|
local id = player_data.choices.blueprint_choice and player_data.choices.blueprint_choice.item_number
|
|
if not id then return end
|
|
local bp = player_data.blueprints.cache[id]
|
|
if not bp then return end
|
|
|
|
renderer.draw_line{x = fx1, y = fy1-1, w = 0, h = 1, width = 7, color={0.3, 0.3, 0.3}}
|
|
renderer.draw_line{x = fx1-1, y = fy1, w = 1, h = 0, width = 7, color={0.3, 0.3, 0.3}}
|
|
|
|
local build_check_type = defines.build_check_type
|
|
local can_forced = {
|
|
[{false, false}] = 0,
|
|
[{true, false}] = 1,
|
|
[{false, true}] = 2,
|
|
[{true, true}] = 3,
|
|
}
|
|
|
|
for check_type, i1 in pairs(build_check_type) do
|
|
|
|
for forced_ghost, i2 in pairs(can_forced) do
|
|
|
|
local forced, ghost = forced_ghost[1], forced_ghost[2]
|
|
|
|
local nx = x + (bp.w + 3) * i1
|
|
local ny = y + (bp.h + 3) * i2
|
|
|
|
renderer.draw_rectangle{
|
|
x = nx-.5,
|
|
y = ny-.5,
|
|
w = bp.w,
|
|
h = bp.h,
|
|
color = {0.2, 0.2, .7},
|
|
}
|
|
|
|
-- renderer.draw_text{
|
|
-- x = nx+(bp.w-1)/2, y = ny-.5,
|
|
-- text = ("%i,%i"):format(i1, i2),
|
|
-- alignment = "center",
|
|
-- vertical_alignment="bottom",
|
|
-- }
|
|
|
|
renderer.draw_text{
|
|
x = nx+(bp.w-1)/2, y = ny-1.5,
|
|
text = ("%s"):format(check_type),
|
|
alignment = "center",
|
|
vertical_alignment="bottom",
|
|
}
|
|
renderer.draw_text{
|
|
x = nx+(bp.w-1)/2, y = ny-1,
|
|
text = ("forced: %s"):format(forced),
|
|
alignment = "center",
|
|
vertical_alignment="bottom",
|
|
}
|
|
renderer.draw_text{
|
|
x = nx+(bp.w-1)/2, y = ny-.5,
|
|
text = ("ghost: %s"):format(ghost),
|
|
alignment = "center",
|
|
vertical_alignment="bottom",
|
|
}
|
|
|
|
for _, ent in pairs(bp.entities) do
|
|
local ex = nx + ent.position.x - .5
|
|
local ey = ny + ent.position.y - .5
|
|
local t = {
|
|
name = ent.name,
|
|
position = {ex, ey},
|
|
direction = ent.direction,
|
|
build_check_type = defines.build_check_type[check_type],
|
|
force = game.get_player(event.player_index).force,
|
|
forced = forced,
|
|
}
|
|
if ghost then
|
|
t.name, t.inner_name = "entity-ghost", t.name
|
|
end
|
|
|
|
local can_place = event.surface.can_place_entity(t)
|
|
|
|
renderer.draw_circle{x = ex, y = ey, r = 0.5, width = 3,
|
|
color = can_place and {0.1, .9, .1} or {0.9, .1, .1},
|
|
}
|
|
|
|
if can_place then
|
|
if not ghost then
|
|
t.name, t.inner_name = "entity-ghost", t.name
|
|
end
|
|
event.surface.create_entity(t)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
return render_util
|