1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2024-12-14 10:13:13 +02:00
RedMew/features/cutscene/rendering.lua
2019-07-07 20:51:25 +02:00

342 lines
11 KiB
Lua

local RS = require 'map_gen.shared.redmew_surface'
local Debug = require 'utils.debug'
local Rendering = require 'utils.rendering'
local Vertices = require 'resources.vertices'
local insert = table.insert
local toggle_debug = false --Set to true if you wish to get spammed with debug messages from the rendering module (Requires _DEBUG = true)
local function debug_print(message, trace_levels)
if toggle_debug then
Debug.print(message, trace_levels)
end
end
local Public = {}
--At zoom level 1 a tile is 32x32 pixels
--tile size is calculated by 32 * zoom level.
local function text_height_in_tiles(scale, zoom)
-- Default (count-font) at scale 10 is 125 pixels for lower letters and 109 for capital letters
-- At scale 5 this is 64 or very close to half of the size at scale 10 (62.5)
-- Therefore size hsa been determined to be (12.5 * scale) + 1
local size = (12.5 * scale) + 1
local pixel_per_tile = zoom * 32
return size / pixel_per_tile, size
end
local function calculate_percentages(settings, player_resolution)
local original_resolution = settings.original_resolution
return {
height = player_resolution.height / original_resolution.height,
width = player_resolution.width / original_resolution.width,
tile = (settings.original_zoom * 32) / (settings.player_zoom * 32)
}
end
local function text_scale(percentage, scale)
return scale * (percentage.height + percentage.width) * 0.5
end
local function fit_to_screen(percentage, coordinates)
if not coordinates.fitted then
local height = percentage.height
local width = percentage.width
local tile = percentage.tile
for _, pos in pairs(coordinates) do
if type(pos) == 'number' then
coordinates.x = coordinates.x * width
coordinates.y = coordinates.y * height
break
else
pos.x = pos.x * width
pos.y = pos.y * height
end
end
for _, pos in pairs(coordinates) do
if type(pos) == 'number' then
coordinates.x = coordinates.x * tile
coordinates.y = coordinates.y * tile
break
else
pos.x = pos.x * tile
pos.y = pos.y * tile
end
end
coordinates.fitted = true
end
return coordinates
end
local function fit_to_screen_edges(settings, player_resolution, coordinates)
if not coordinates.fitted then
local tile = settings.original_zoom * 32
local player_tile = settings.player_zoom * 32
local display_scale = player_resolution.scale or 1
local player_height = (player_resolution.height / player_tile) * 0.5
local player_width = (player_resolution.width / player_tile) * 0.5
for _, pos in pairs(coordinates) do
if type(pos) == 'number' then
coordinates.y = -player_height + (((coordinates.y * tile) / player_tile) * display_scale)
coordinates.x = -player_width + (((coordinates.x * tile) / player_tile) * display_scale)
break
else
pos.y = -player_height + (((pos.y * tile) / player_tile) * display_scale)
pos.x = -player_width + (((pos.x * tile) / player_tile) * display_scale)
end
end
coordinates.fitted = true
end
return coordinates
end
local function create_background_params(params)
local background_params = params.background
if background_params then
for k, v in pairs(params) do
if k ~= 'background' then
if not background_params[k] then
background_params[k] = v
end
end
end
else
background_params = params
end
return background_params
end
local function text_background(settings, offset, player, percentages, size, number_text, params)
local margin = 0.01 / params.scale
local left_top = fit_to_screen(percentages, {x = -40, y = 0})
local right_bottom = fit_to_screen(percentages, {x = 40, y = 0})
left_top.y = -size * margin * 0.875
right_bottom.y = size * (1.5 + (margin * 1.125)) * number_text
local background_params = create_background_params(params)
return Public.draw_rectangle(settings, offset, left_top, right_bottom, player, background_params)
end
function Public.draw_text(settings, offset, text, player, params, draw_background, fit_to_edge)
local ids = {}
local player_resolution = player.display_resolution
player_resolution.scale = player.display_scale
local percentages = calculate_percentages(settings, player_resolution)
local scale = params.scale
if draw_background ~= -1 then
scale = text_scale(percentages, scale)
local size = text_height_in_tiles(scale, settings.player_zoom)
if fit_to_edge then
offset = fit_to_screen_edges(settings, player_resolution, offset)
else
offset = fit_to_screen(percentages, offset)
end
offset.y = offset.y - size * 0.5
end
local size = text_height_in_tiles(scale, settings.player_zoom)
if draw_background == true then
insert(ids, text_background(settings, offset, player, percentages, size, 1, params, fit_to_edge))
end
local target = {x = player.position.x + offset.x, y = player.position.y + offset.y}
local color = params.color
color = color and color or {r = 255, g = 255, b = 255}
local font = params.font
local surface = params.surface
surface = surface or RS.get_surface()
local ttl = params.time_to_live
ttl = ttl and ttl or -1
local forces = params.forces
local players = params.players
players = players or {}
table.insert(players, player)
local visible = params.visible
visible = visible or true
local dog = params.draw_on_ground
dog = dog or false
local orientation = params.orientation
orientation = orientation or 0
local alignment = params.alignment
alignment = alignment or 'center'
--local swz = params.scale_with_zoom
local swz = true
local oiam = params.only_in_alt_mode
oiam = oiam or false
local rendering_params = {
text = {'', text},
color = color,
target = target,
scale_with_zoom = swz,
surface = surface,
time_to_live = ttl,
alignment = alignment,
players = players,
scale = scale,
forces = forces,
visible = visible,
draw_on_ground = dog,
only_in_alt_mode = oiam,
orientation = orientation,
font = font
}
debug_print(rendering_params)
insert(ids, rendering.draw_text(rendering_params))
return ids
end
function Public.draw_multi_line_text(settings, offset, texts, player, params, draw_background, fit_to_edge)
local ids = {}
local player_resolution = player.display_resolution
player_resolution.scale = player.display_scale
local percentages = calculate_percentages(settings, player_resolution)
local scale = params.scale
scale = text_scale(percentages, scale)
local size = text_height_in_tiles(scale, settings.player_zoom)
if fit_to_edge then
offset = fit_to_screen_edges(settings, player_resolution, offset)
else
offset = fit_to_screen(percentages, offset)
end
offset.y = offset.y - size * 0.5
if draw_background then
insert(ids, text_background(settings, offset, player, percentages, size, #texts, params, fit_to_edge))
draw_background = -1
end
for i = 1, #texts do
insert(ids, Public.draw_text(settings, offset, texts[i], player, params, draw_background, fit_to_edge)[1])
offset.y = offset.y + (size * 1.5)
end
return ids
end
function Public.draw_rectangle(settings, offset, left_top, right_bottom, player, params, fit_to_edge)
local player_resolution = player.display_resolution
player_resolution.scale = player.display_scale
local percentages = calculate_percentages(settings, player_resolution)
if fit_to_edge then
offset = fit_to_screen_edges(settings, player_resolution, offset)
left_top = fit_to_screen_edges(settings, player_resolution, left_top)
right_bottom = fit_to_screen_edges(settings, player_resolution, right_bottom)
else
offset = fit_to_screen(percentages, offset)
left_top = fit_to_screen(percentages, left_top)
right_bottom = fit_to_screen(percentages, right_bottom)
end
local target_left = {x = player.position.x + left_top.x + offset.x, y = player.position.y + left_top.y + offset.y}
local target_right = {x = player.position.x + right_bottom.x + offset.x, y = player.position.y + right_bottom.y + offset.y}
local color = params.color
color = color and color or {}
local width = params.width
width = width and width or 0
local filled = params.filled
filled = filled and filled or true
local surface = params.surface
surface = surface or RS.get_surface()
local ttl = params.time_to_live
ttl = ttl and ttl or -1
local forces = params.forces
local players = params.players
players = players or {}
table.insert(players, player)
local visible = params.visible
visible = visible or true
local dog = params.draw_on_ground
dog = dog or false
local oiam = params.only_in_alt_mode
oiam = oiam or false
local rendering_params = {
color = color,
width = width,
filled = filled,
left_top = target_left,
right_bottom = target_right,
surface = surface,
time_to_live = ttl,
forces = forces,
players = players,
visible = visible,
draw_on_ground = dog,
only_in_alt_mode = oiam
}
debug_print(rendering_params)
return rendering.draw_rectangle(rendering_params)
end
local blackout_settings = {original_resolution = {height = 1440, width = 2560}, original_zoom = 1, player_zoom = 1}
function Public.blackout(player, zoom, ttl, color)
local left_top = {x = -40, y = -22.5}
local right_bottom = {x = 40, y = 22.5}
blackout_settings.player_zoom = zoom
return Public.draw_rectangle(blackout_settings, {x = 0, y = 0}, left_top, right_bottom, player, {color = color, time_to_live = ttl})
end
function Public.draw_arrow(settings, offset, player, params, fit_to_edge)
local player_resolution = player.display_resolution
player_resolution.scale = player.display_scale
local percentages = calculate_percentages(settings, player_resolution)
if fit_to_edge then
offset = fit_to_screen_edges(settings, player_resolution, offset)
else
offset = fit_to_screen(percentages, offset)
end
local vertices = Rendering.scale(Vertices.arrow, percentages.tile, percentages.tile)
vertices = Rendering.rotate(vertices, params.rotation)
vertices = Rendering.translate(vertices, offset.x, offset.y)
local color = params.color or {1, 1, 1, 1}
params.color = color
local players = params.players
players = players or {}
table.insert(players, player)
params.players = players
params.surface = RS.get_surface()
--Debug.print(vertices)
return Rendering.draw_polygon(vertices, params)
end
return Public