fortunes_foundation/cursor.lua
Nyeogmi 0912e90510 Change undo behavior
- Undo while holding a card drops it
- Undo can be redone
2024-02-13 19:09:35 -08:00

149 lines
3.7 KiB
Lua

acceptance_state={
not_grabbed=0,
would_accept=1,
would_not_accept=2,
no_move=3
}
cursor=klass()
function cursor:init(board)
self.ruleset=board.ruleset
self.board=board
self.hover_x=self.ruleset.n_slots\2
self.hover_y=1
self.saved_hover_x_y=nil
self.grabbed=nil
end
function cursor:acceptance_state()
local hover=self:hover_slot()
if self.grabbed then
if hover==self.grabbed then
return acceptance_state.no_move
end
local source=self.board.slots[self.grabbed]
local target=self.board.slots[self:hover_slot()]
local card=source:peek()
if target:would_accept(card) then
return acceptance_state.would_accept,source,target
else
return acceptance_state.would_not_accept
end
else
if (self.board.slots[hover]:peek()) return acceptance_state.not_grabbed
return acceptance_state.would_not_accept
end
end
function cursor:save_hover()
self.saved_hover_x_y={self.hover_x,self.hover_y}
end
function cursor:restore_hover()
self.wants_to_restore_hover=true
end
function cursor:actually_restore_hover()
if (not self.saved_hover_x_y) return
self.wants_to_restore_hover=false
-- try restoring hover x
local old_hover_x,old_hover_y=self.hover_x,self.hover_y
self.hover_x,self.hover_y=unpack(self.saved_hover_x_y)
-- try very hard to be in a valid spot
for i in all{
function() self.hover_x,self.hover_y=old_hover_x,old_hover_y end,
function() self:move_x(-1) end,
function() self:move_y(1) end,
function() self:move_x(-1) end,
function() self:move_y(-1) end
} do
if (self:acceptance_state()!=acceptance_state.would_not_accept) return
i()
end
end
function cursor:toggle_grab()
local acc,src,tar=self:acceptance_state()
local slot=self:hover_slot()
if acc==acceptance_state.not_grabbed then
if (not self.board.watcher:intercept("grab",slot)) sounds:dire() return
if (self.board.slots[slot]:peek()) self.grabbed=slot
self:save_hover()
sounds:menu()
elseif acc==acceptance_state.would_accept then
if (not self.board.watcher:intercept("drop",slot)) sounds:dire() return
self.board:pre_move(src:peek())
local card=src:pop()
tar:add(card)
self.grabbed=nil
self.board:on_move(card)
self:restore_hover()
sounds:menu()
elseif acc==acceptance_state.no_move or acc==acceptance_state.would_not_accept then
self:drop_grab()
else
assert(false,"invalid acceptance state")
end
end
function cursor:drop_grab()
if (not self.board.watcher:intercept("cancel")) sounds:dire() return
self.grabbed=nil
self:restore_hover()
sounds:menu()
end
function cursor:update()
if (self.wants_to_restore_hover) self:actually_restore_hover()
end
function cursor:move_x(dx)
if (self.hover_y==0) return
if (dx==0) return
local orig_x=self.hover_x
while true do
self.hover_x+=dx
self.hover_x%=self.ruleset.n_slots
if (self.hover_x==orig_x) return
if (self:acceptance_state()!=acceptance_state.would_not_accept) return true
end
return
end
function cursor:move_y(dy)
local old_y=self.hover_y
if (self.hover_y==0 and dy==1) self.hover_y=1
if (self.hover_y==1 and dy==-1) self.hover_y=0
if (self:acceptance_state()==acceptance_state.would_not_accept) if (not self:move_x(-1)) self.hover_y=old_y
end
function cursor:hover_slot()
if (self.hover_y==0) return self.ruleset.n_slots+1
return self.hover_x+1
end
function cursor:grabbed_card()
if self.grabbed then
local slot=self.board.slots[self.grabbed]
return slot:peek()
end
return nil
end
function cursor:draw_at(l,i)
local card=self:grabbed_card()
local acc=self:acceptance_state()
if card then
i+=1
local x,y=l:place_card(i)
local card_fg=self.ruleset.deck:draw_card(x,y,card,{rotate=l.rotated})
local fg=card_fg
draw_layout_hint(l,i,9,false)
else
local filled=false
if (i<1) i=1 filled=true
draw_layout_hint(l,i,12,filled)
end
end