Files
libretro/bios/Bungie/Marathon/Plugins/Basic M1 HUD/Basic HUD M1.lua
T
Abdessamad Derraz bb19a6d5cf feat: profile what RetroBat and RetroPie run
100 emulator names the two platforms run had no profile, so their packs carried nothing for them. Each was read from the platform's own launcher or scriptmodule: the same program as an existing profile takes the name in cores:, a different build gets its own profile read from that version, a launcher or self-contained game goes to remove_cores, and the rest are new profiles written from their source or shipped binary. The files they need that the collection lacked are collected from the upstream distributions. Bungie and splitwolf trees are read by path and stay out of dedup.
2026-10-20 06:14:10 +02:00

957 lines
28 KiB
Lua

-- Basic M1 HUD (C) 2024 by Gregory Smith, based on the default Marathon HUD
-- Copyright (C) 2011 and beyond by Jeremiah Morris
-- and the "Aleph One" developers.
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- This license is contained in the file "COPYING",
-- which is included with this source code; it is available online at
-- http://www.gnu.org/licenses/gpl.html
Triggers = {}
function Triggers.draw()
if TexturePalette.draw() then return end
if Player.motion_sensor.active then
local r = rects["motion sensor"]
local sidelen = globals.motion_sensor_side_length
clip_motion_sensor(r.x, r.y, sidelen, sidelen)
imgs["motion sensor virgin mount"]:draw(r.x, r.y)
for i = 1,#Player.motion_sensor.blips do
local blip = Player.motion_sensor.blips[i - 1]
local img = imgs["motion sensor " .. blip.type.mnemonic .. " " .. blip.intensity]
local mult = (blip.distance/globals.motion_sensor_range) * (sidelen/2)
local rad = math.rad(blip.direction)
local xoff = r.x + (sidelen / 2) + (math.cos(rad) * mult)
local yoff = r.y + (sidelen / 2) + (math.sin(rad) * mult)
img:draw(xoff - (img.width / 2), yoff - (img.height / 2))
end
unclip_motion_sensor()
end
-- inventory
if true then
local r = rects["inventory"]
local f = int_fonts["interface"]
local rowh = f.line_height
local sec = Player.inventory_sections.current
local x = rects["inventory"].x
local y = rects["inventory"].y
local w = Screen.width - x
local h = Screen.height - y
Screen.fill_rect(x - adj(2), y - adj(2), w + adj(2), h + adj(2), InterfaceColors["inventory background"])
-- header
Screen.fill_rect(r.x, r.y, r.width, rowh, InterfaceColors["inventory header background"]);
draw_text_trunc(f, sec.name, r.x + globals.text_inset, r.y, r.width - globals.text_inset, InterfaceColors["inventory text"])
-- content
Screen.fill_rect(r.x, r.y + rowh, r.width, r.height - rowh, InterfaceColors["inventory background"])
if sec.type == InventorySections["network statistics"] then
network_stats_draw()
else
inventory_items_draw()
end
end
-- weapons
if true then
local r = rects["weapon display"]
Screen.fill_rect(r.x, r.y, r.width, r.height, InterfaceColors["inventory background"])
local wep = Player.weapons.desired
if wep then
-- weapon shapes
local shpinfo = wep_shapes[wep.type]
if shpinfo.unusable then
weapon_shape_draw(shpinfo.single)
if Player.items[wep.type.mnemonic].count > 1 then
weapon_shape_draw(shpinfo.multiple)
else
weapon_shape_draw(shpinfo.unusable)
end
elseif shpinfo.multiple then
if Player.items[wep.type.mnemonic].count > 1 then
weapon_shape_draw(shpinfo.multiple)
else
weapon_shape_draw(shpinfo.single)
end
else
weapon_shape_draw(shpinfo.single)
end
-- name
weapon_name_draw(wep.name, wep_nrects[wep.type], true)
-- ammo
if wep.primary then
if wep.primary.bullet_display then
weapon_bullet_draw(wep.primary)
elseif wep.primary.energy_display then
weapon_energy_draw(wep.primary)
end
end
if wep.secondary then
if wep.secondary.bullet_display then
weapon_bullet_draw(wep.secondary)
elseif wep.secondary.energy_display then
weapon_energy_draw(wep.secondary)
end
end
end
end
-- health
local nrg = globals.player_maximum_suit_energy
if Player.energy > 2*nrg then
draw_bar(rects["shield"], (Player.energy - 2*nrg) / nrg,
imgs["triple energy bar top"],
imgs["triple energy bar"],
imgs["double energy bar"])
elseif Player.energy > nrg then
draw_bar(rects["shield"], (Player.energy - nrg) / nrg,
imgs["double energy bar top"],
imgs["double energy bar"],
imgs["energy bar"])
else
draw_bar(rects["shield"], math.max(Player.energy, 0) / nrg,
imgs["energy bar top"],
imgs["energy bar"],
imgs["empty energy bar"])
end
-- oxygen
draw_bar(rects["oxygen"], Player.oxygen / globals.player_maximum_suit_oxygen,
imgs["oxygen bar top"],
imgs["oxygen bar"],
imgs["empty energy bar"])
-- player name
if #Game.players > 1 then
-- local r = rects["player name"]
local x = rects["inventory"].x
local h = int_fonts["player name"].line_height
local y = rects["inventory"].y - h
local w = Screen.width - x
draw_text_center(int_fonts["player name"],
Player.name,
x + 1, y - adj(4) + 1, w,
{ 0, 0, 0, 1})
draw_text_center(int_fonts["player name"],
Player.name,
x, y - adj(4), w,
InterfaceColors[Player.color.mnemonic .. " player"])
end
end
function Triggers.resize()
if TexturePalette.resize() then return end
local ww = Screen.width
local wh = Screen.height
-- calculate HUD area
hud_rect = {}
local hudsize = Screen.hud_size_preference
hud_rect.width = 640
if hudsize == SizePreferences["double"] then
if ww >= 2560 then
hud_rect.width = 1280
end
elseif hudsize == SizePreferences["largest"] then
hud_rect.width = ww / 2
end
hud_rect.height = hud_rect.width * 3 / 4
-- hud_rect.x = math.floor((ww - hud_rect.width) / 2)
-- hud_rect.y = math.floor((wh - hud_rect.height) / 2)
hud_rect.x = ww - hud_rect.width
hud_rect.y = wh - hud_rect.height
hud_rect.scale = hud_rect.width / 640
hud_rect.x = hud_rect.x + hud_rect.width - adj(InterfaceRects["inventory"].width) - adj(InterfaceRects["inventory"].x) - adj(InterfaceRects["weapon display"].width)
hud_rect.y = hud_rect.y + hud_rect.height - adj(InterfaceRects["inventory"].y) - adj(InterfaceRects["inventory"].height)
-- calculate terminal area
local termsize = Screen.term_size_preference
local termrect = InterfaceRects["terminal screen"]
Screen.term_rect.width = 640
if termsize == SizePreferences["double"] then
if (wh - adj(InterfaceRects["motion sensor"].height) * 2) >= 640 and ww >= 1280 then
Screen.term_rect.width = 1280
end
elseif termsize == SizePreferences["largest"] then
Screen.term_rect.width = math.min(ww, math.max(640, 2 * (wh - adj(InterfaceRects["motion sensor"].height) * 2)))
end
Screen.term_rect.height = Screen.term_rect.width / 2
Screen.term_rect.x = math.floor((ww - Screen.term_rect.width) / 2)
Screen.term_rect.y = math.floor((wh - Screen.term_rect.height) / 2)
-- calculate world-view area
Screen.world_rect.width = ww
Screen.world_rect.height = wh
Screen.world_rect.x = 0
Screen.world_rect.y = 0
-- calculate map area
Screen.map_rect.width = ww
Screen.map_rect.height = wh
Screen.map_rect.x = 0
Screen.map_rect.y = 0
unclip()
-- recalculate screen fonts
for k, v in pairs(int_fonts) do
v.scale = hud_rect.scale
end
-- recalculate interface rectangles
rects = {}
for r in InterfaceRects() do
rects[r.mnemonic] = adj_rect(r)
end
rects["motion sensor"].x = 0
rects["motion sensor"].y = wh - rects["motion sensor"].height
rects["shield"].x = rects["motion sensor"].x + rects["motion sensor"].width + adj(4)
rects["shield"].y = wh - rects["shield"].height
rects["oxygen"].x = rects["shield"].x + rects["shield"].width + adj(4)
rects["oxygen"].y = wh - rects["oxygen"].height
Screen.text_margins.bottom = rects["motion sensor"].height + adj(4)
-- scale images
for k, v in pairs(imgs) do
v:rescale(adj(v.unscaled_width), adj(v.unscaled_height))
end
-- scale weapon shapes
for k, v in pairs(wep_shapes) do
for kk, vv in pairs(v) do
if vv.shp then
vv.shp:rescale(adj(vv.shp.unscaled_width), adj(vv.shp.unscaled_height))
end
vv.x = adj_x(vv.orig_x)
vv.y = adj_y(vv.orig_y)
end
end
-- scale bullet shapes
for k, v in pairs(ammo_shapes) do
v:rescale(adj(v.unscaled_width), adj(v.unscaled_height))
end
-- recalculate weapon name rects
wep_nrects = {}
for wt in WeaponTypes() do
wep_nrects[wt] = adj_rect(Player.weapons[wt].name_rect)
end
-- recalculate globals
globals = {
message_area_x_offset = adj(-9),
message_area_y_offset = adj(-5),
text_inset = adj(2),
name_offset = adj(23),
top_of_bar_width = adj(4),
motion_sensor_side_length = adj(123),
network_compass_36 = adj(36),
network_compass_61 = adj(61),
player_maximum_suit_energy = 150,
player_maximum_suit_oxygen = 6*30*60,
motion_sensor_range = 8,
used_mic = false
}
end
function Triggers.init()
if not (WeaponTypes["fist"] == nil) then WeaponTypes["fist"].mnemonic = "knife" end
int_fonts = {}
for ftype in InterfaceFonts() do
int_fonts[ftype.mnemonic] = Fonts.new{ interface = ftype }
end
imgs = {}
imgs["motion sensor mask"] = Images.new { path = "resources/motion_sensor_mask.png" }
imgs["interface panel"] = Images.new{ resource = 128 }
for idx, name in ipairs({
"",
"empty energy bar",
"",
"energy bar",
"oxygen bar",
"energy bar top",
"oxygen bar top",
"blinker off",
"blinker on",
"",
"microphone off",
"respawn off",
"microphone on",
"respawn on",
"", "", "", "", "", "", "",
"motion sensor mount",
"motion sensor virgin mount",
"motion sensor alien 0",
"motion sensor alien 1",
"motion sensor alien 2",
"motion sensor alien 3",
"motion sensor alien 4",
"motion sensor alien 5",
"motion sensor friend 0",
"motion sensor friend 1",
"motion sensor friend 2",
"motion sensor friend 3",
"motion sensor friend 4",
"motion sensor friend 5",
"", "", "", "", "", "", "", "", "", "", "",
"motion sensor hostile player 0",
"motion sensor hostile player 1",
"motion sensor hostile player 2",
"motion sensor hostile player 3",
"motion sensor hostile player 4",
"motion sensor hostile player 5",
"", "",
"double energy bar",
"triple energy bar",
"double energy bar top",
"triple energy bar top" }) do
if name ~= "" then
imgs[name] = Shapes.new{ collection = 0, texture_index = idx - 1, type = TextureTypes["interface"] }
end
end
wep_shapes = {}
ammo_shapes = {}
for wt in WeaponTypes() do
local wep = Player.weapons[wt]
wep_shapes[wt] = {}
if wep.shape then
local s = wep.shape
wep_shapes[wt].single = {
shp = Shapes.new{ collection = 0, type = TextureTypes["interface"],
texture_index = s.texture_index },
orig_x = s.x,
orig_y = s.y }
end
if wep.multiple_shape then
local s = wep.multiple_shape
wep_shapes[wt].multiple = {
shp = Shapes.new{ collection = 0, type = TextureTypes["interface"],
texture_index = s.texture_index },
orig_x = s.x,
orig_y = s.y }
end
if wep.multiple_unusable_shape then
local s = wep.multiple_unusable_shape
wep_shapes[wt].unusable = {
shp = Shapes.new{ collection = 0, type = TextureTypes["interface"],
texture_index = s.texture_index },
orig_x = s.x,
orig_y = s.y }
end
if wep.primary and wep.primary.bullet_display then
local disp = wep.primary.bullet_display
if not ammo_shapes[disp.texture_index] then
ammo_shapes[disp.texture_index] = Shapes.new{ collection = 0, type = TextureTypes["interface"], texture_index = disp.texture_index }
end
if not ammo_shapes[disp.empty_texture_index] then
ammo_shapes[disp.empty_texture_index] = Shapes.new{ collection = 0, type = TextureTypes["interface"], texture_index = disp.empty_texture_index }
end
end
if wep.secondary and wep.secondary.bullet_display then
local disp = wep.secondary.bullet_display
if disp.texture_index then
if not ammo_shapes[disp.texture_index] then
ammo_shapes[disp.texture_index] = Shapes.new{ collection = 0, type = TextureTypes["interface"], texture_index = disp.texture_index }
end
end
if disp.empty_texture_index then
if not ammo_shapes[disp.empty_texture_index] then
ammo_shapes[disp.empty_texture_index] = Shapes.new{ collection = 0, type = TextureTypes["interface"], texture_index = disp.empty_texture_index }
end
end
end
end
Triggers.resize()
end
function adj(len)
return len * hud_rect.scale
end
function adj_x(x)
return hud_rect.x + adj(x)
end
function adj_y(y)
return hud_rect.y + adj(y)
end
function adj_rect(r)
return { x = adj_x(r.x),
y = adj_y(r.y),
width = adj(r.width),
height = adj(r.height) }
end
function draw_bar(r, frac, cap, full, empty)
empty.crop_rect.height = empty.height
empty.crop_rect.y = 0
empty:draw(r.x, r.y)
local height = r.height * frac
local caph = globals.top_of_bar_width
if height > 2 * caph then
cap.crop_rect.height = caph
cap:draw(r.x, r.y + r.height - height)
full.crop_rect.height = height - caph
full.crop_rect.y = r.height - height + caph
full:draw(r.x, r.y + r.height - full.crop_rect.height)
else
cap.crop_rect.height = height/2
cap:draw(r.x, r.y + r.height - height)
full.crop_rect.height = height/2
full.crop_rect.y = full.height - full.crop_rect.height
full:draw(r.x, r.y + r.height - full.crop_rect.height)
end
end
function trunc_text(font, text, w)
local tw, th = font:measure_text(text)
while tw > w do
text = string.sub(text, 1, -2)
tw, th = font:measure_text(text)
end
return text, tw
end
function draw_text_trunc(font, text, x, y, w, color)
local tt, tw = trunc_text(font, text, w)
font:draw_text(tt, x, y, color)
end
function draw_text_center(font, text, x, y, w, color)
local tt, tw = trunc_text(font, text, w)
font:draw_text(tt, x + sfloor((w - tw)/2), y, color)
end
function draw_text_right(font, text, x, y, color)
local tw, th = font:measure_text(text)
font:draw_text(text, x - tw, y, color)
end
function clip(x, y, w, h)
local rect = Screen.clip_rect
rect.x = x
rect.y = y
rect.width = w
rect.height = h
end
function cliprect(r)
local rect = Screen.clip_rect
rect.x = r.x
rect.y = r.y
rect.width = r.width
rect.height = r.height
end
function unclip()
local rect = Screen.clip_rect
rect.x = 0
rect.y = 0
rect.width = Screen.width
rect.height = Screen.height
end
function clip_motion_sensor(x, y, w, h)
if Screen.renderer == "software" then
clip(x, y, w, h)
else
unclip()
Screen.clear_mask()
Screen.masking_mode = MaskingModes["drawing"]
imgs["motion sensor mask"]:draw(x, y)
Screen.masking_mode = MaskingModes["enabled"]
end
end
function unclip_motion_sensor()
if Screen.renderer == "software" then
unclip()
else
Screen.masking_mode = MaskingModes["disabled"]
end
end
function sfloor(num)
return num - (num % hud_rect.scale)
end
function format_time(ticks)
local secs = math.floor(ticks / 30)
return string.format("%d:%02d", math.floor(secs / 60), secs % 60)
end
function player_ranking_text(gametype, ranking)
if gametype == "kill monsters" or
gametype == "capture the flag" or
gametype == "rugby" or
gametype == "most points" then
return string.format("%d", ranking)
elseif gametype == "least points" then
return string.format("%d", -ranking)
elseif gametype == "cooperative play" then
return string.format("%d%%", ranking)
elseif gametype == "most time" or
gametype == "least time" or
gametype == "king of the hill" or
gametype == "kill the man with the ball" or
gametype == "defense" or
gametype == "tag" then
return format_time(math.abs(ranking))
end
return nil
end
function sorted_players()
local sort_tbl = {}
for i = 1,#Game.players do
table.insert(sort_tbl, { rank = Game.players[i - 1].ranking, idx = i - 1 })
end
local sortfunc = function(a, b)
if a.rank ~= b.rank then return a.rank > b.rank end
return a.idx < b.idx
end
table.sort(sort_tbl, sortfunc)
local splayers = {}
for i = 1,#sort_tbl do
table.insert(splayers, Game.players[sort_tbl[i].idx])
end
return splayers
end
function inventory_item_draw(item, y)
local r = rects["inventory"]
local clr = InterfaceColors["inventory text"]
if not item.valid then clr = InterfaceColors["invalid weapon"] end
local iname = item.plural
if item.count == 1 then iname = item.singular end
draw_text_trunc(
int_fonts["interface"],
iname,
r.x + globals.name_offset + globals.text_inset,
y,
r.width - globals.name_offset - globals.text_inset,
clr)
draw_text_trunc(
int_fonts["interface item count"],
string.format("%3d", item.count),
r.x + globals.text_inset,
y,
globals.name_offset + globals.text_inset,
clr)
end
function inventory_items_draw()
local r = rects["inventory"]
local rowh = int_fonts["interface"].line_height
local maxrows = r.height / rowh
local currow = 1
local section = Player.inventory_sections.current.type
for itype in ItemTypes() do
if currow < maxrows and itype ~= ItemTypes["knife"] then
local item = Player.items[itype]
if item.inventory_section == section and item.count > 0 then
inventory_item_draw(item, r.y + (currow * rowh))
currow = currow + 1
end
end
end
end
function inventory_right_draw(text, currow)
local r = rects["inventory"]
local f = int_fonts["interface"]
draw_text_right(f, text, r.x + r.width - globals.text_inset, r.y + (currow * f.line_height), InterfaceColors["inventory text"])
end
function inventory_right_draw(text, currow)
local r = rects["inventory"]
local f = int_fonts["interface"]
draw_text_right(f, text, r.x + r.width - globals.text_inset, r.y + (currow * f.line_height), InterfaceColors["inventory text"])
end
function network_stats_draw()
local r = { xl = rects["inventory"].x + globals.text_inset,
xr = rects["inventory"].x + rects["inventory"].width - globals.text_inset,
y = rects["inventory"].y,
width = rects["inventory"].width - (2*globals.text_inset) }
local f = int_fonts["interface"]
local rowh = f.line_height
-- time/score display in header
if Game.time_remaining and Game.time_remaining <= 30*60*999 then
draw_text_right(f, format_time(Game.time_remaining),
r.xr, r.y, InterfaceColors["inventory text"])
elseif Game.kill_limit then
local lim = Game.kill_limit
local gt = Game.type.mnemonic
if gt == "kill monsters" or
gt == "cooperative play" or
gt == "king of the hill" or
gt == "kill the man with the ball" or
gt == "tag" then
local leastleft = nil
for p = 1,#Game.players do
local thisleft = lim - Game.players[p - 1].kills
if (not leastleft) or thisleft < leastleft then
leastleft = thisleft
end
end
draw_text_right(f, string.format("%d", leastleft),
r.xr, r.y, InterfaceColors["inventory text"])
end
end
-- player listing
for idx, p in ipairs(sorted_players()) do
r.y = r.y + rowh
local clr = InterfaceColors[p.color.mnemonic .. " player"]
draw_text_trunc(f, p.name, r.xl, r.y, r.width, clr)
draw_text_right(f, player_ranking_text(Game.type, p.ranking),
r.xr, r.y, clr)
end
end
function weapon_name_draw(txt, nr, vertical)
local f = int_fonts["weapon name"]
local fh = f.line_height
local w, h = f:measure_text(txt)
local draw_single = function(singleline, vert)
local y = nr.y
if vert then
if fh > nr.height then
y = nr.y - fh + adj(2)
else
local off = nr.height - fh
y = nr.y + nr.height - fh - sfloor(off/2) - adj(1)
end
else
if fh > nr.height then
y = nr.y + nr.height - fh
else
y = nr.y
end
end
draw_text_center(f, singleline, nr.x, y, nr.width, InterfaceColors["inventory text"])
end
-- will we fit on one line?
if w <= nr.width then
draw_single(txt, vertical)
return
end
-- no more words?
local spos, epos = string.find(txt, " ")
if not spos then
draw_single(txt, vertical)
return
end
-- if we get here, we need to split
local lineend = spos
w, h = f:measure_text(string.sub(txt, 1, spos - 1))
while w < nr.width do
spos, epos = string.find(txt, " ", lineend + 1)
if not spos then
w = nr.width
else
w, h = f:measure_text(string.sub(txt, 1, spos - 1))
if w < nr.width then lineend = spos end
end
end
draw_single(string.sub(txt, 1, lineend - 1), false)
weapon_name_draw(string.sub(txt, lineend + 1, -1), { x = nr.x, width = nr.width, y = nr.y + f.line_height, height = nr.height - f.line_height }, false)
end
function weapon_shape_draw(shpinfo)
if shpinfo and shpinfo.shp then
shpinfo.shp:draw(shpinfo.x, shpinfo.y)
end
end
function weapon_bullet_draw(trigger)
local disp = trigger.bullet_display
local rounds = trigger.rounds
if rounds < 0 then rounds = 0 end
local max = disp.across * disp.down
if rounds > max then rounds = max end
local dr = adj_rect(disp)
local full = ammo_shapes[disp.texture_index]
if not full then return end
local empty = ammo_shapes[disp.empty_texture_index]
if not empty then return end
local row = 0
full.crop_rect.x = 0
full.crop_rect.width = full.width
while row < math.floor(rounds / disp.across) do
full:draw(dr.x, dr.y)
dr.y = dr.y + dr.height
row = row + 1
end
local partial = rounds % disp.across
if partial > 0 then
full.crop_rect.width = partial * dr.width
empty.crop_rect.width = (disp.across - partial) * dr.width
if disp.right_to_left then
full.crop_rect.x = 0
full:draw(dr.x, dr.y)
empty.crop_rect.x = full.crop_rect.width
empty:draw(dr.x + empty.crop_rect.x, dr.y)
else
empty.crop_rect.x = 0
empty:draw(dr.x, dr.y)
full.crop_rect.x = empty.crop_rect.width
full:draw(dr.x + full.crop_rect.x, dr.y)
end
dr.y = dr.y + dr.height
end
row = 0
empty.crop_rect.x = 0
empty.crop_rect.width = empty.width
while row < math.floor((max - rounds) / disp.across) do
empty:draw(dr.x, dr.y)
dr.y = dr.y + dr.height
row = row + 1
end
end
function weapon_energy_draw(trigger)
local disp = trigger.energy_display
local rounds = trigger.rounds
if rounds < 0 then return end
if rounds > disp.maximum then rounds = disp.maximum end
local dr = adj_rect(disp)
Screen.fill_rect(dr.x, dr.y, dr.width, dr.height, disp.color)
dr.x = dr.x + adj(1)
dr.y = dr.y + adj(1)
dr.width = dr.width - adj(2)
dr.height = dr.height - adj(2)
local fill_height = sfloor((rounds * dr.height) / disp.maximum)
Screen.fill_rect(dr.x, dr.y, dr.width, dr.height - fill_height, disp.empty_color)
end
-- BEGIN texture palette utility
--
-- Use: in Triggers.draw: "if TexturePalette.draw() then return end"
-- in Triggers.resize: "if TexturePalette.resize() then return end"
TexturePalette = {}
TexturePalette.active = false
function TexturePalette.check_active()
local old_active = TexturePalette.active
local new_active = false
if Player.texture_palette.size > 0 then new_active = true end
TexturePalette.active = new_active
if old_active and not new_active then
Screen.crosshairs.lua_hud = TexturePalette.saved_crosshairs_lua_hud
Triggers.resize()
elseif new_active and not old_active then
TexturePalette.palette_cache = {}
TexturePalette.saved_crosshairs_lua_hud = Screen.crosshairs.lua_hud
Screen.crosshairs.lua_hud = false
TexturePalette.resize()
end
return TexturePalette.active
end
function TexturePalette.get_shape(slot)
local key = string.format("%d %d", slot.collection, slot.texture_index)
local shp = TexturePalette.palette_cache[key]
if not shp then
shp = Shapes.new{collection = slot.collection, texture_index = slot.texture_index, type = slot.type}
TexturePalette.palette_cache[key] = shp
end
return shp
end
function TexturePalette.draw_shape(slot, x, y, size)
local shp = TexturePalette.get_shape(slot)
if not shp then return end
if shp.width > shp.height then
shp:rescale(size, shp.unscaled_height * size / shp.unscaled_width)
shp:draw(x, y + (size - shp.height)/2)
else
shp:rescale(shp.unscaled_width * size / shp.unscaled_height, size)
shp:draw(x + (size - shp.width)/2, y)
end
end
function TexturePalette.draw(hr)
if not TexturePalette.check_active() then return false end
local hr = TexturePalette.hud_rect
local tcount = Player.texture_palette.size
local size
if tcount <= 5 then size = 128
elseif tcount <= 16 then size = 80
elseif tcount <= 36 then size = 53
elseif tcount <= 64 then size = 40
elseif tcount <= 100 then size = 32
elseif tcount <= 144 then size = 26
else size = 20
end
size = size * hr.scale
local rows = math.floor(hr.height/size)
local cols = math.floor(hr.width/size)
local x_offset = hr.x + (hr.width - cols * size)/2
local y_offset = hr.y + (hr.height - rows * size)/2
for i = 0,tcount - 1 do
TexturePalette.draw_shape(
Player.texture_palette.slots[i],
(i % cols) * size + x_offset + hr.scale/2,
math.floor(i / cols) * size + y_offset + hr.scale/2,
size - hr.scale)
end
if Player.texture_palette.highlight then
local i = Player.texture_palette.highlight
Screen.frame_rect(
(i % cols) * size + x_offset,
math.floor(i / cols) * size + y_offset,
size, size,
InterfaceColors["inventory text"],
hr.scale)
end
return true
end
function TexturePalette.resize()
if not TexturePalette.check_active() then return false end
local ww = Screen.width
local wh = Screen.height
-- calculate HUD area
TexturePalette.hud_rect = {}
local hudsize = Screen.hud_size_preference
TexturePalette.hud_rect.width = 640
if hudsize == SizePreferences["double"] then
if wh >= 960 and ww >= 1280 then
TexturePalette.hud_rect.width = 1280
end
elseif hudsize == SizePreferences["largest"] then
TexturePalette.hud_rect.width = math.min(ww, math.max(640, (4 * wh) / 3));
end
TexturePalette.hud_rect.height = TexturePalette.hud_rect.width / 4
TexturePalette.hud_rect.x = math.floor((ww - TexturePalette.hud_rect.width) / 2)
TexturePalette.hud_rect.y = math.floor(wh - TexturePalette.hud_rect.height)
TexturePalette.hud_rect.scale = TexturePalette.hud_rect.width / 640
-- remove HUD height from rest of calculations
wh = TexturePalette.hud_rect.y
-- calculate terminal area
local termsize = Screen.term_size_preference
Screen.term_rect.width = 640
if termsize == SizePreferences["double"] then
if wh >= 640 and ww >= 1280 then
Screen.term_rect.width = 1280
end
elseif termsize == SizePreferences["largest"] then
Screen.term_rect.width = math.min(ww, math.max(640, 2 * wh))
end
Screen.term_rect.height = Screen.term_rect.width / 2
Screen.term_rect.x = math.floor((ww - Screen.term_rect.width) / 2)
Screen.term_rect.y = math.floor((wh - Screen.term_rect.height) / 2)
-- calculate world-view area
Screen.world_rect.width = math.min(ww, math.max(640, 2 * wh))
Screen.world_rect.height = Screen.world_rect.width / 2
Screen.world_rect.x = math.floor((ww - Screen.world_rect.width) / 2)
Screen.world_rect.y = math.floor((wh - Screen.world_rect.height) / 2)
-- calculate map area
if Screen.map_overlay_active then
-- overlay just matches world-view
Screen.map_rect.width = Screen.world_rect.width
Screen.map_rect.height = Screen.world_rect.height
Screen.map_rect.x = Screen.world_rect.x
Screen.map_rect.y = Screen.world_rect.y
else
Screen.map_rect.width = ww
Screen.map_rect.height = wh
Screen.map_rect.x = 0
Screen.map_rect.y = 0
end
Screen.clip_rect.width = Screen.width
Screen.clip_rect.height = Screen.height
Screen.clip_rect.x = 0
Screen.clip_rect.y = 0
return true
end
-- END texture palette utility