1local std = stead 2local type = std.type 3local instead = std.ref '@instead' 4 5-- luacheck: read globals instead_theme_var 6-- luacheck: read globals instead_theme_name 7-- luacheck: read globals instead_ticks 8-- luacheck: read globals instead_font_load 9-- luacheck: read globals instead_font_free 10-- luacheck: read globals instead_font_scaled_size 11-- luacheck: read globals instead_sprite_alpha 12-- luacheck: read globals instead_sprite_dup 13-- luacheck: read globals instead_sprite_scale 14-- luacheck: read globals instead_sprite_rotate 15-- luacheck: read globals instead_sprite_text 16-- luacheck: read globals instead_sprite_text_size 17-- luacheck: read globals instead_sprite_draw 18-- luacheck: read globals instead_sprite_copy 19-- luacheck: read globals instead_sprite_compose 20-- luacheck: read globals instead_sprite_fill 21-- luacheck: read globals instead_sprite_pixel 22-- luacheck: read globals instead_sprite_load 23-- luacheck: read globals instead_sprite_free 24-- luacheck: read globals instead_sprite_size 25-- luacheck: read globals instead_sprites_free 26-- luacheck: read globals instead_sprite_colorkey 27-- luacheck: read globals instead_sprite_pixels 28-- luacheck: read globals instead_mouse_pos 29-- luacheck: read globals instead_mouse_show 30-- luacheck: read globals instead_mouse_filter 31-- luacheck: read globals instead_finger_pos 32-- luacheck: read globals instead_noise1 33-- luacheck: read globals instead_noise2 34-- luacheck: read globals instead_noise3 35-- luacheck: read globals instead_noise4 36-- luacheck: read globals instead_render_callback 37-- luacheck: read globals instead_direct 38-- luacheck: read globals instead_busy 39-- luacheck: read globals instead_sprite_pixels 40-- luacheck: read globals instead_screen_size 41-- luacheck: read globals instead_screen_dpi 42 43-- theme 44instead.theme_var = instead_theme_var 45instead.theme_name = instead_theme_name 46instead.screen_size = instead_screen_size 47instead.screen_dpi = instead_screen_dpi 48 49local theme = std.obj { 50 nam = '@theme'; 51 vars = {}; 52 reset_vars = {}; 53 { 54 win = { gfx = {}}; 55 inv = { gfx = {}}; 56 menu = { gfx = {}}; 57 gfx = {}; 58 snd = {}; 59 scr = {}; 60 }; 61} 62 63function theme.restore(name) 64 if type(name) ~= 'string' then 65 std.err("Wrong parameter to theme.restore", 2) 66 end 67 local v = theme.vars[name] 68 if not v then 69 return 70 end 71 instead.theme_var(name, v); 72end 73 74function theme.set(name, val) 75 if type(name) ~= 'string' or val == nil then 76 std.err("Wrong parameter to theme.set", 2) 77 end 78 if not theme.reset_vars[name] then 79 theme.reset_vars[name] = instead.theme_var(name) 80 end 81 instead.theme_var(name, std.tostr(val)); 82 theme.vars[name] = std.tostr(val); 83end 84 85function theme.reset(name) 86 if type(name) ~= 'string' then 87 std.err("Wrong parameter to theme.reset", 2) 88 end 89 local v = theme.reset_vars[name] 90 if not v then 91 return 92 end 93 instead.theme_var(name, v); 94 theme.vars[name] = nil 95 theme.reset_vars[name] = nil 96end 97 98function theme.name(...) 99 return instead.theme_name(...); 100end 101 102function theme.get(...) 103 return instead.theme_var(...); 104end 105 106function theme.scr.w() 107 return tonumber(theme.get 'scr.w') 108end 109 110function theme.scr.h() 111 return tonumber(theme.get 'scr.h') 112end 113 114function theme.win.reset() 115 std.for_all(theme.reset, "win.x", "win.y", "win.w", "win.h", 116 "win.col.fg", "win.col.link", "win.col.alink", 117 "win.fnt.name", "win.fnt.size", "win.fnt.height"); 118end 119 120function theme.win.geom(x, y, w, h) 121 theme.set("win.x", x); 122 theme.set("win.y", y); 123 theme.set("win.w", w); 124 theme.set("win.h", h); 125end 126 127 128function theme.win.color(fg, link, alink) 129 theme.set("win.col.fg", fg); 130 theme.set("win.col.link", link); 131 theme.set("win.col.alink", alink); 132end 133 134function theme.win.font(name, size, height) 135 theme.set("win.fnt.name", name); 136 theme.set("win.fnt.size", size); 137 theme.set("win.fnt.height", height); 138end 139 140function theme.win.gfx.reset() 141 std.for_all(theme.reset, "win.gfx.up", "win.up.x", "win.up.y"); 142 std.for_all(theme.reset, "win.gfx.down", "win.down.x", "win.down.y"); 143end 144 145function theme.win.gfx.up(pic, x, y) 146 theme.set("win.gfx.up", pic); 147 theme.set("win.up.x", x); 148 theme.set("win.up.y", y); 149end 150 151function theme.win.gfx.down(pic, x, y) 152 theme.set("win.gfx.down", pic); 153 theme.set("win.down.x", x); 154 theme.set("win.down.y", y); 155end 156 157function theme.inv.reset() 158 std.for_all(theme.reset, "inv.x", "inv.y", "inv.w", "inv.h", 159 "inv.col.fg", "inv.col.link", "inv.col.alink", 160 "inv.fnt.name", "inv.fnt.size", "inv.fnt.height", 161 "inv.mode"); 162end 163 164function theme.inv.geom(x, y, w, h) 165 theme.set("inv.x", x); 166 theme.set("inv.y", y); 167 theme.set("inv.w", w); 168 theme.set("inv.h", h); 169end 170 171function theme.inv.color(fg, link, alink) 172 theme.set("inv.col.fg", fg); 173 theme.set("inv.col.link", link); 174 theme.set("inv.col.alink", alink); 175end 176 177function theme.inv.font(name, size, height) 178 theme.set("inv.fnt.name", name); 179 theme.set("inv.fnt.size", size); 180 theme.set("inv.fnt.height", height); 181end 182 183function theme.inv.mode(mode) 184 theme.set("inv.mode", mode); 185end 186 187function theme.inv.gfx.reset() 188 std.for_all(theme.reset, "inv.gfx.up", "inv.up.x", "inv.up.y"); 189 std.for_all(theme.reset, "inv.gfx.down", "inv.down.x", "inv.down.y"); 190end 191 192function theme.inv.gfx.up(pic, x, y) 193 theme.set("inv.gfx.up", pic); 194 theme.set("inv.up.x", x); 195 theme.set("inv.up.y", y); 196end 197 198function theme.inv.gfx.down(pic, x, y) 199 theme.set("inv.gfx.down", pic); 200 theme.set("inv.down.x", x); 201 theme.set("inv.down.y", y); 202end 203 204function theme.menu.reset() 205 std.for_all(theme.reset, "menu.bw", 206 "menu.col.fg", "menu.col.bg", "menu.col.alpha", 207 "menu.col.link", "menu.col.alink", 208 "menu.fnt.name", "menu.fnt.size", "menu.fnt.height"); 209end 210 211function theme.menu.bw(w) 212 theme.set("menu.bw", w) 213end 214 215function theme.menu.color(fg, bg, alpha, link, alink) 216 theme.set("menu.col.fg", fg); 217 theme.set("menu.col.bg", bg); 218 theme.set("menu.col.alpha", alpha); 219 theme.set("menu.col.link", link); 220 theme.set("menu.col.alink", alink); 221end 222 223function theme.menu.font(name, size, height) 224 theme.set("menu.fnt.name", name); 225 theme.set("menu.fnt.size", size); 226 theme.set("menu.fnt.height", height); 227end 228 229function theme.menu.gfx.reset() 230 std.for_all(theme.reset, "menu.gfx.button", "menu.button.x", "menu.button.y"); 231end 232 233function theme.menu.gfx.button(b, x, y) 234 theme.set("menu.gfx.button", b); 235 theme.set("menu.button.x", x); 236 theme.set("menu.button.y", y); 237end; 238 239function theme.gfx.reset() 240 std.for_all(theme.reset, "scr.gfx.cursor.normal", "scr.gfx.cursor.use", 241 "scr.gfx.cursor.x", "scr.gfx.cursor.y", 242 "scr.gfx.mode", "scr.gfx.pad", 243 "scr.gfx.bg"); 244end 245 246function theme.gfx.cursor(norm, use, x, y) 247 theme.set("scr.gfx.cursor.normal", norm); 248 theme.set("scr.gfx.cursor.use", use); 249 theme.set("scr.gfx.cursor.x", x); 250 theme.set("scr.gfx.cursor.y", y); 251end 252 253function theme.gfx.mode(mode) 254 theme.set("scr.gfx.mode", mode); 255end 256 257function theme.gfx.pad(pad) 258 theme.set("scr.gfx.pad", pad); 259end 260 261function theme.gfx.bg(bg) 262 theme.set("scr.gfx.bg", bg); 263end 264 265function theme.snd.reset() 266 theme.reset("snd.click"); 267end 268 269function theme.snd.click(w) 270 theme.set("snd.click", w); 271end 272 273-- sprites 274instead.ticks = instead_ticks 275instead.font_load = instead_font_load 276instead.font_free = instead_font_free 277instead.font_scaled_size = instead_font_scaled_size 278instead.sprite_alpha = instead_sprite_alpha 279instead.sprite_dup = instead_sprite_dup 280instead.sprite_scale = instead_sprite_scale 281instead.sprite_rotate = instead_sprite_rotate 282instead.sprite_text = instead_sprite_text 283instead.sprite_text_size = instead_sprite_text_size 284instead.sprite_draw = instead_sprite_draw 285instead.sprite_copy = instead_sprite_copy 286instead.sprite_compose = instead_sprite_compose 287instead.sprite_fill = instead_sprite_fill 288instead.sprite_pixel = instead_sprite_pixel 289instead.sprite_load = instead_sprite_load 290instead.sprite_free = instead_sprite_free 291instead.sprite_size = instead_sprite_size 292instead.sprites_free = instead_sprites_free 293instead.sprite_colorkey = instead_sprite_colorkey 294instead.sprite_pixels = instead_sprite_pixels 295 296instead.mouse_pos = instead_mouse_pos 297instead.mouse_show = instead_mouse_show 298instead.mouse_filter = instead_mouse_filter 299 300instead.finger_pos = instead_finger_pos 301 302instead.noise1 = instead_noise1 303instead.noise2 = instead_noise2 304instead.noise3 = instead_noise3 305instead.noise4 = instead_noise4 306 307instead.render_callback = instead_render_callback 308 309instead.direct = instead_direct 310 311std.busy = instead_busy 312 313local spr = { 314 __gc = function(s) 315 instead.sprite_free(s.spr) 316 end; 317 __tostring = function(s) 318 return s.spr 319 end; 320} 321 322spr.__index = spr 323 324local fnt = { 325 __gc = function(s) 326 instead.font_free(s.fnt) 327 end; 328 __tostring = function(s) 329 return s.fnt 330 end; 331} 332 333fnt.__index = fnt 334 335local spr_get = function(s) 336 if type(s) == 'string' then 337 return s 338 end 339 return std.tostr(s) 340end 341 342function fnt:new(nam) 343 if type(nam) ~= 'string' then 344 std.err("Wrong argument to fnt:new(): "..std.tostr(nam), 2) 345 end 346 local o = { 347 fnt = nam; 348 __save = function() end; 349 } 350 std.setmt(o, self) 351 return std.proxy(o) 352end 353 354function fnt:text(text, col, style, ...) 355 return spr:new(instead.sprite_text(self.fnt, text, col, style, ...)) 356end 357 358function fnt:size(...) 359 return instead.sprite_text_size(self.fnt, ...); 360end 361 362function fnt:height(...) 363 local _, h = self:size(...) 364 return h 365end 366 367function spr:new(nam) 368 if type(nam) ~= 'string' then 369 std.err("Wrong argument to spr:new(): "..std.tostr(nam), 2) 370 end 371 local o = { 372 spr = nam; 373 __save = function() end; 374 } 375 std.setmt(o, self) 376 return std.proxy(o) 377end; 378 379function spr:alpha(alpha, ...) 380 return spr:new(instead.sprite_alpha(self.spr, alpha, ...)); 381end 382 383function spr:colorkey(color, ...) 384 instead.sprite_colorkey(self.spr, color, ...); 385 return self 386end 387 388function spr:dup(...) 389 return spr:new(instead.sprite_dup(self.spr, ...)); 390end 391 392function spr:scale(xs, ys, smooth, ...) 393 if smooth == nil then 394 smooth = true -- default is on 395 end 396 return spr:new(instead.sprite_scale(self.spr, xs, ys, smooth,...)); 397end 398 399function spr:rotate(angle, smooth, ...) 400 if smooth == nil then 401 smooth = true -- default is on 402 end 403 return spr:new(instead.sprite_rotate(self.spr, angle, smooth, ...)); 404end 405 406function spr:size() 407 return instead.sprite_size(self.spr); 408end 409 410function spr:draw(fx, fy, fw, fh, d, x, y, alpha) 411 if d == nil and x == nil and y == nil then 412 d, x, y, alpha = fx, fy, fw, fh 413 fx, fy, fw, fh = 0, 0, -1, -1 414 end 415 instead.sprite_draw(self.spr, fx, fy, fw, fh, spr_get(d), x, y, alpha); 416 return d 417end 418 419function spr:copy(fx, fy, fw, fh, d, x, y) 420 if d == nil and x == nil and y == nil then 421 d, x, y = fx, fy, fw 422 fx, fy, fw, fh = 0, 0, -1, -1 423 end 424 instead.sprite_copy(self.spr, fx, fy, fw, fh, spr_get(d), x, y); 425 return d 426end 427 428function spr:compose(fx, fy, fw, fh, d, x, y) 429 if d == nil and x == nil and y == nil then 430 d, x, y = fx, fy, fw 431 fx, fy, fw, fh = 0, 0, -1, -1 432 end 433 instead.sprite_compose(self.spr, fx, fy, fw, fh, spr_get(d), x, y); 434 return d 435end 436 437function spr:fill(x, y, w, h, col) 438 if h == nil and col == nil then 439 instead.sprite_fill(self.spr, 0, 0, -1, -1, x); 440 return self 441 end 442 instead.sprite_fill(self.spr, x, y, w, h, col); 443 return self 444end 445 446function spr:pixel(x, y, col, alpha) 447 if not col then 448 return instead.sprite_pixel(self.spr, x, y, col, alpha) 449 end 450 instead.sprite_pixel(self.spr, x, y, col, alpha) 451 return self 452end 453 454local screen = spr:new 'screen' 455 456local sprite = { 457 nam = '@sprite'; 458} 459 460function sprite.new(w, h, ...) 461 if std.tonum(w) and std.tonum(h) then 462 local t = 'blank:'..std.tostr(std.math.floor(w))..'x'..std.tostr(std.math.floor(h)) 463 return spr:new(instead.sprite_load(t)) 464 end 465 local sp = instead.sprite_load(w, h, ...) 466 if not sp then 467 std.err("Can not load sprite: "..std.tostr(w), 2); 468 end 469 return spr:new(sp) 470end 471 472function sprite.fnt(name, sz, ...) 473 if not std.tonum(sz) then 474 std.err("No font size specified in sprite:fnt().", 2) 475 end 476 local fn = instead.font_load(name, sz, ...) 477 if not fn then 478 std.err("Can not load font: "..std.tostr(name), 2); 479 end 480 return fnt:new(fn) 481end 482 483function sprite.scr() 484 return screen 485end 486 487function sprite.direct(v) 488 return instead.direct(v) 489end 490 491function sprite.font_scaled_size(size) 492 return instead.font_scaled_size(size); 493end 494 495local render_cb = nil 496function sprite.render_callback(fn) 497 local old = render_cb 498 render_cb = fn 499 instead.render_callback(render_cb) 500 return old 501end 502 503std.obj(sprite) 504 505instead.sprite_pixels = instead_sprite_pixels 506 507local pfnt = { 508} 509 510pfnt.__index = pfnt 511std.setmt(pfnt, fnt) 512 513local pxl = { 514} 515 516pxl.__index = pxl 517 518function pxl:dup() 519 local w, h, s = self:size() 520 local p = instead.sprite_pixels(w, h, s) 521 if p then 522 self:copy(p) 523 end 524 return self:new(p) 525end 526 527function pxl:sprite(...) 528 return sprite.new(self, false, ...) 529end 530 531function pxl:tosprite(...) 532 return sprite.new(self, true, ...) 533end 534 535function pxl:draw_spr(fx, fy, fw, fh, d, x, y, alpha) 536 if d == nil and x == nil and y == nil then 537 instead.sprite_draw(self, 0, 0, -1, -1, spr_get(fx), fy, fw, fh); 538 return fx 539 end 540 instead.sprite_draw(self, fx, fy, fw, fh, spr_get(d), x, y, alpha); 541 return d 542end 543 544function pxl:copy_spr(fx, fy, fw, fh, d, x, y, alpha) 545 if d == nil and x == nil and y == nil then 546 instead.sprite_copy(self, 0, 0, -1, -1, spr_get(fx), fy, fw, fh); 547 return fx 548 end 549 instead.sprite_copy(self, fx, fy, fw, fh, spr_get(d), x, y, alpha); 550 return d 551end 552 553function pxl:compose_spr(fx, fy, fw, fh, d, x, y, alpha) 554 if d == nil and x == nil and y == nil then 555 instead.sprite_compose(self, 0, 0, -1, -1, spr_get(fx), fy, fw, fh); 556 return fx 557 end 558 instead.sprite_compose(self, fx, fy, fw, fh, spr_get(d), x, y, alpha); 559 return d 560end 561 562function pxl:scale(...) 563 return pxl:new(self:new_scaled(...)) 564end 565 566function pxl:rotate(...) 567 return pxl:new(self:new_rotated(...)) 568end 569 570local function poly(self, fn, t, ...) 571 if type(t) ~= 'table' then 572 std.err("Wrong argument to :poly()", 3) 573 end 574 if #t < 4 then 575 return 576 end 577 local n = #t 578 for i = 1, n, 2 do 579 if i == n - 1 then 580 fn(self, t[i], t[i+1], t[1], t[2], ...); 581 else 582 fn(self, t[i], t[i+1], t[i+2], t[i+3], ...); 583 end 584 end 585end 586 587function pxl:poly(t, ...) 588 poly(self, self.line, t, ...) 589end 590 591function pxl:polyAA(t, ...) 592 poly(self, self.lineAA, t, ...) 593end 594 595function pxl:new(p) 596 if type(p) ~= 'userdata' then 597 return 598 end 599 local t = getmetatable(p).__index 600 setmetatable(t, self) 601 return p 602end 603 604function pfnt:new(nam) 605 return fnt.new(self, nam) 606end 607 608function pfnt:text(text, col, style, ...) 609 local s = self 610 return pxl:new(instead.sprite_pixels(instead.sprite_text(s.fnt, text, col, style, ...))) 611end 612 613local pixels = { 614 nam = '@pixels'; 615} 616 617function pixels.fnt(name, sz, ...) 618 if not std.tonum(sz) then 619 std.err("No font size specified.", 2) 620 end 621 return pfnt:new(instead.font_load(name, -sz, ...)) 622end 623 624function pixels.new(...) 625 return pxl:new(instead.sprite_pixels(...)) 626end 627 628std.obj (pixels) 629 630local rnd_seed = 1980 + 1978 631 632stead.mod_init(function() 633 rnd_seed = (std.os.time(stead.os.date("*t")) + rnd_seed + instead.ticks()) 634 std.rnd_seed(rnd_seed) 635end) 636 637stead.mod_done(function() 638 sprite.render_callback() -- stop render 639-- instead.sprites_free(); 640end) 641