Working undo

This commit is contained in:
Luke Hubmayer-Werner 2020-05-22 22:19:27 +09:30
parent 1c622da928
commit 3251e2f03b
1 changed files with 83 additions and 48 deletions

View File

@ -235,7 +235,7 @@ func _input(event: InputEvent) -> void:
sel_col = int(gridpos.x)
drag_action = DragAction.DRAW_COLOR
drag_color = posmod(cell_colors.get_cell(sel_row, sel_col) + (1 if event.button_index==BUTTON_LEFT else -1), N_COLORS)
cell_colors.set_cell(sel_row, sel_col, drag_color)
set_cell_color(sel_row, sel_col, drag_color)
elif event is InputEventMouseMotion and event.button_mask:
if drag_action == DragAction.TEST_LINE:
@ -268,99 +268,134 @@ func _input(event: InputEvent) -> void:
sel_row = int(gridpos.y)
sel_col = int(gridpos.x)
set_cell_color(sel_row, sel_col, drag_color)
elif event is InputEventKey and event.pressed:
match event.scancode:
KEY_Z:
undo()
var undo_stack = []
class UndoAction:
var action_type
var cell_row
var cell_col
var cell_row: int
var cell_col: int
var activated: bool
func _init(action, row, col) -> void:
action_type = action
cell_row = row
cell_col = col
activated = false
class UndoActionCorner extends UndoAction:
func _init(action, row, col).(action, row, col) -> void:
pass
var corner_marks
var corner_mark
var set: bool # False = clear
func _init(row, col, corner_mark, set, corner_marks).(corner_mark, row, col) -> void:
self.corner_marks = corner_marks
self.corner_mark = corner_mark
self.set = set
func _to_string() -> String:
match action_type:
UndoActions.SET_L_RIGHT:
return '+L %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row]
UndoActions.CLEAR_L_RIGHT:
return '-L %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row]
UndoActions.SET_X_RIGHT:
return '+X %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row]
UndoActions.CLEAR_X_RIGHT:
return '-X %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row]
UndoActions.SET_L_DOWN:
return '+L %s%d:%s'%[Common.num2alpha(cell_col-1), cell_row, Common.num2alpha(cell_col)]
UndoActions.CLEAR_L_DOWN:
return '-L %s%d:%s'%[Common.num2alpha(cell_col-1), cell_row, Common.num2alpha(cell_col)]
UndoActions.SET_X_DOWN:
return '+X %s%d:%s'%[Common.num2alpha(cell_col-1), cell_row, Common.num2alpha(cell_col)]
UndoActions.CLEAR_X_DOWN:
return '-X %s%d:%s'%[Common.num2alpha(cell_col-1), cell_row, Common.num2alpha(cell_col)]
var prefix = '+' if set else '-'
match corner_mark:
CornerMark.L_RIGHT:
return prefix+'L %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row]
CornerMark.X_RIGHT:
return prefix+'X %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row]
CornerMark.L_DOWN:
return prefix+'L %s%d:%s'%[Common.num2alpha(cell_col-1), cell_row, Common.num2alpha(cell_col)]
CornerMark.X_DOWN:
return prefix+'X %s%d:%s'%[Common.num2alpha(cell_col-1), cell_row, Common.num2alpha(cell_col)]
_:
return 'unk %d %s%d'%[action_type, Common.num2alpha(cell_col), cell_row]
return 'unk %s%d %s%d'%[prefix, corner_mark, Common.num2alpha(cell_col), cell_row]
func activate() -> void:
activated = true
if set:
corner_marks.set_flag(cell_row, cell_col, corner_mark)
else:
corner_marks.clear_flag(cell_row, cell_col, corner_mark)
func undo() -> void:
activated = false
if set:
corner_marks.clear_flag(cell_row, cell_col, corner_mark)
else:
corner_marks.set_flag(cell_row, cell_col, corner_mark)
class UndoActionCell extends UndoAction:
var set_state
var prev_state
func _init(action, row, col, set_state, prev_state).(action, row, col) -> void:
var old_state
var cell_colors
func _init(action, row, col, set_state, cell_colors).(action, row, col) -> void:
self.set_state = set_state
self.prev_state = prev_state
self.old_state = set_state
self.cell_colors = cell_colors
func _to_string() -> String:
match action_type:
UndoActions.SET_COLOR:
return 'C%d->%d %s%d'%[set_state, prev_state, Common.num2alpha(cell_col), cell_row]
return 'C%d<-%d %s%d'%[set_state, old_state, Common.num2alpha(cell_col), cell_row]
_:
return 'unk %d %s%d'%[action_type, Common.num2alpha(cell_col), cell_row]
func set_cell_color(row, col, new_color):
var old_color = cell_colors.get_cell(row, col)
if old_color != new_color:
cell_colors.set_cell(row, col, new_color)
undo_stack.append(UndoActionCell.new(UndoActions.SET_COLOR, row, col, new_color, old_color))
func activate() -> void:
assert(not activated)
activated = true
match action_type:
UndoActions.SET_COLOR:
old_state = cell_colors.get_cell(cell_row, cell_col)
cell_colors.set_cell(cell_row, cell_col, set_state)
func undo() -> void:
assert(activated)
activated = false
match action_type:
UndoActions.SET_COLOR:
cell_colors.set_cell(cell_row, cell_col, old_state)
func do_action(action):
action.activate()
undo_stack.append(action)
func undo():
if !undo_stack.empty():
var action = undo_stack.pop_back()
action.undo()
func set_cell_color(row, col, new_color):
if new_color != cell_colors.get_cell(row, col):
do_action(UndoActionCell.new(UndoActions.SET_COLOR, row, col, new_color, cell_colors))
# TODO: Refactor all this nonsense a bit more
func set_line_right(row, col):
if !corner_marks.get_flag(row, col, CornerMark.L_RIGHT) and !corner_marks.get_flag(row, col, CornerMark.X_RIGHT):
corner_marks.set_flag(row, col, CornerMark.L_RIGHT)
undo_stack.append(UndoActionCorner.new(UndoActions.SET_L_RIGHT, row, col))
do_action(UndoActionCorner.new(row, col, CornerMark.L_RIGHT, true, corner_marks))
func set_line_down(row, col):
if !corner_marks.get_flag(row, col, CornerMark.L_DOWN) and !corner_marks.get_flag(row, col, CornerMark.X_DOWN):
corner_marks.set_flag(row, col, CornerMark.L_DOWN)
undo_stack.append(UndoActionCorner.new(UndoActions.SET_L_DOWN, row, col))
do_action(UndoActionCorner.new(row, col, CornerMark.L_DOWN, true, corner_marks))
func clear_line_right(row, col):
if corner_marks.get_flag(row, col, CornerMark.L_RIGHT):
corner_marks.clear_flag(row, col, CornerMark.L_RIGHT)
undo_stack.append(UndoActionCorner.new(UndoActions.CLEAR_L_RIGHT, row, col))
do_action(UndoActionCorner.new(row, col, CornerMark.L_RIGHT, false, corner_marks))
func clear_line_down(row, col):
if corner_marks.get_flag(row, col, CornerMark.L_DOWN):
corner_marks.clear_flag(row, col, CornerMark.L_DOWN)
undo_stack.append(UndoActionCorner.new(UndoActions.CLEAR_L_DOWN, row, col))
do_action(UndoActionCorner.new(row, col, CornerMark.L_DOWN, false, corner_marks))
func set_x_right(row, col):
if !corner_marks.get_flag(row, col, CornerMark.L_RIGHT) and !corner_marks.get_flag(row, col, CornerMark.X_RIGHT):
corner_marks.set_flag(row, col, CornerMark.X_RIGHT)
undo_stack.append(UndoActionCorner.new(UndoActions.SET_X_RIGHT, row, col))
do_action(UndoActionCorner.new(row, col, CornerMark.X_RIGHT, true, corner_marks))
func set_x_down(row, col):
if !corner_marks.get_flag(row, col, CornerMark.L_DOWN) and !corner_marks.get_flag(row, col, CornerMark.X_DOWN):
corner_marks.set_flag(row, col, CornerMark.X_DOWN)
undo_stack.append(UndoActionCorner.new(UndoActions.SET_X_DOWN, row, col))
do_action(UndoActionCorner.new(row, col, CornerMark.X_DOWN, true, corner_marks))
func clear_x_right(row, col):
if corner_marks.get_flag(row, col, CornerMark.X_RIGHT):
corner_marks.clear_flag(row, col, CornerMark.X_RIGHT)
undo_stack.append(UndoActionCorner.new(UndoActions.CLEAR_X_RIGHT, row, col))
do_action(UndoActionCorner.new(row, col, CornerMark.X_RIGHT, false, corner_marks))
func clear_x_down(row, col):
if corner_marks.get_flag(row, col, CornerMark.X_DOWN):
corner_marks.clear_flag(row, col, CornerMark.X_DOWN)
undo_stack.append(UndoActionCorner.new(UndoActions.CLEAR_X_DOWN, row, col))
do_action(UndoActionCorner.new(row, col, CornerMark.X_DOWN, false, corner_marks))