; ------------------------------------------------------------------------
; HeavyThing x86_64 assembly language library and showcase programs
; Copyright © 2015-2018 2 Ton Digital
; Homepage: https://2ton.com.au/
; Author: Jeff Marrison <jeff@2ton.com.au>
;
; This file is part of the HeavyThing library.
;
; HeavyThing is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License, or
; (at your option) any later version.
;
; HeavyThing 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.
;
; You should have received a copy of the GNU General Public License along
; with the HeavyThing library. If not, see <http://www.gnu.org/licenses/>.
; ------------------------------------------------------------------------
; tuieffects.asm: a simple TUI effects demonstration
;
; first things first, include the library defaults, and the
; library main include:
include '../../ht_defaults.inc'
include '../../ht.inc'
; for the purposes of our demonstration, limit the number of iterations:
demo_iterations = 10
; Our HeavyThing's TUI effects can't be run with no valid size, so we can't
; initialise any effects until we get our first proper resize event. As a result
; we need a descendent virtual method table from our base tui_background to
; work from, and the only override we are grabbing here is for the sizechanged
; event so that we can get things underway.
; so, we literally copy tui_background.inc's vtable, and then change its
; sizechanged handler to our own:
dalign
demo_vtable:
dq tui_object$cleanup, tui_background$clone, tui_background$draw, tui_object$redraw, tui_object$updatedisplaylist, demo_sizechanged
dq tui_object$timer, tui_object$layoutchanged, tui_object$move, tui_object$setfocus, tui_object$gotfocus, tui_object$lostfocus
dq tui_object$keyevent, tui_object$domodal, tui_object$endmodal, tui_object$exit, tui_object$calcbounds, tui_object$calcchildbounds
dq tui_object$appendchild, tui_object$appendbastard, tui_object$prependchild, tui_object$contains, tui_object$getchildindex
dq tui_object$removechild, tui_object$removebastard, tui_object$removeallchildren, tui_object$removeallbastards
dq tui_object$getobjectsunderpoint, tui_object$flatten, tui_object$firekeyevent, tui_object$ontab, tui_object$onshifttab
dq tui_object$setcursor, tui_object$showcursor, tui_object$hidecursor, tui_object$click, tui_object$clicked
; for our descended tui_background object, we need to hangon to some state
; variables:
demo_panel_ofs = tui_background_size
demo_iterations_ofs = tui_background_size + 8
demo_size = tui_background_size + 16
; and then define our sizechanged handler:
; called with a single argument in rdi, the tui_background object
falign
demo_sizechanged:
prolog demo_sizechanged
; set our object's iteration count to the beginning:
mov qword [rdi+demo_iterations_ofs], demo_iterations
; make sure we let tui_background's (which was tui_object's) sizechange run
; noting this is not a virtual method call (or we'd be calling ourself)
push rdi
call tui_object$sizechanged
; we need to reuse the effect launcher, so we set another global entry point:
calign
demo_reentry:
; create our tui_panel object (which is the "target" tui_object that we'll apply effects to)
mov edi, 35
mov esi, 8
mov rdx, .title
ansi_colors ecx, 'lightgray', 'blue'
ansi_colors r8d, 'yellow', 'blue'
call tui_panel$new_ii
; save our tui_panel pointer in our base demo object:
mov rdi, [rsp]
mov [rdi+demo_panel_ofs], rax
; pick one of our random addition effects
call rng$u32
mov ecx, 5
xor edx, edx
mov r10d, eax
div ecx
mov eax, edx
shr r10d, 8
and r10d, 1 ; r10d == possibly used direction
pop rdi
mov rsi, [rdi+demo_panel_ofs]
jmp qword [rax*8+.dispatch]
dalign
.dispatch:
dq .hslider, .vslider, .sprinkler, .materialise, .fountain
calign
.hslider:
; horizontal slide in effect
mov edx, r10d
mov rcx, ineffect_complete
mov r8, rdi
call tui_effect$hslidein
epilog
calign
.vslider:
; vertical slide in effect
mov edx, r10d
mov rcx, ineffect_complete
mov r8, rdi
call tui_effect$vslidein
epilog
calign
.sprinkler:
; "sprinkle" in effect
mov rdx, ineffect_complete
mov rcx, rdi
call tui_effect$sprinkle
epilog
calign
.materialise:
; materialise effect
mov rdx, ineffect_complete
mov rcx, rdi
call tui_effect$materialize ; haha to my consistency re: AU/UK/USA spellings, hahah
epilog
calign
.fountain:
; fountain effect, quite interesting this one with a large enough terminal, haha
mov rdx, ineffect_complete
mov rcx, rdi
call tui_effect$fountain
epilog
cleartext .title, '2 Ton Digital'
; this function gets called when the aforementioned "in" effect is completed
; so now we have to do the "out" effect
; single argument in rdi == our original demo toplevel object
falign
ineffect_complete:
prolog ineffect_complete
push rdi
call rng$u32
pop rdi
mov ecx, 5
xor edx, edx
mov r10d, eax
div ecx
mov eax, edx
shr r10d, 8
and r10d, 1 ; r10d == possibly used direction
mov rsi, [rdi+demo_panel_ofs]
jmp qword [rax*8+.dispatch]
dalign
.dispatch:
dq .hslider, .vslider, .vaporise, .gunshot, .crumble
calign
.hslider:
; horizontal slide out effect
mov edx, r10d
mov rcx, outeffect_complete
mov r8, rdi
call tui_effect$hslideout
epilog
calign
.vslider:
; vertical slide out effect
mov edx, r10d
mov rcx, outeffect_complete
mov r8, rdi
call tui_effect$vslideout
epilog
calign
.gunshot:
; very interesting (especially with large terminal size) gunshot out effect
mov edx, 1
mov rcx, outeffect_complete
mov r8, rdi
call tui_effect$gunshotout
epilog
calign
.crumble:
; "crumble" out effect
mov rdx, outeffect_complete
mov rcx, rdi
call tui_effect$crumble
epilog
calign
.vaporise:
; vaporise effect
mov rdx, outeffect_complete
mov rcx, rdi
call tui_effect$vaporize ; haha to my consistency re: AU/UK/USA spellings, hahah
epilog
; this function gets called when the aforementioned "out" effect is completed
; single argument in rdi == our original demo toplevel object
falign
outeffect_complete:
prolog outeffect_complete
; rdi is our demo background object, its panel object is now destroyed
sub dword [rdi+demo_iterations_ofs], 1
jz .alldone
; otherwise, fire up a new in transition effect, reusing the first one we did
push rdi
jmp demo_reentry
calign
.alldone:
; all we want to do is drop back out cleanly:
mov rdx, [rdi]
xor esi, esi
call qword [rdx+tui_vexit]
epilog ; not reached
public _start
_start:
; every HeavyThing program needs to start with a call to initialise it
call ht$init
; the terminal object needs a tui_object descendent as its main/only child
; so, we create our demo object to be a background descendent. Since tui_background
; is normally always descended, it does not have its own "new" functions, so
; we'll create it and initialise it manually here:
mov edi, demo_size
call heap$alloc
mov rbx, rax ; hangon to our pointer
mov qword [rax], demo_vtable ; set its virtual method table pointer
mov rdi, rax
movq xmm0, [_math_onehundred] ; 100% wide
movq xmm1, [_math_onehundred] ; 100% high
mov esi, '.' ; fill character
mov edx, 0x00ef ; attributes (though we could use the ansi_colors macro as well)
call tui_background$init_dd
; create our tui_terminal object with our created tui_background
; noting that tui_terminal automatically adds itself to the epoll layer
mov rdi, rbx
call tui_terminal$new
; all thats left is to turn control over to the epoll layer
call epoll$run
; epoll$run does not come back.
; include the global data segment:
include '../../ht_data.inc'