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) sel_col = int(gridpos.x)
drag_action = DragAction.DRAW_COLOR 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) 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: elif event is InputEventMouseMotion and event.button_mask:
if drag_action == DragAction.TEST_LINE: if drag_action == DragAction.TEST_LINE:
@ -268,99 +268,134 @@ func _input(event: InputEvent) -> void:
sel_row = int(gridpos.y) sel_row = int(gridpos.y)
sel_col = int(gridpos.x) sel_col = int(gridpos.x)
set_cell_color(sel_row, sel_col, drag_color) 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 = [] var undo_stack = []
class UndoAction: class UndoAction:
var action_type var action_type
var cell_row var cell_row: int
var cell_col var cell_col: int
var activated: bool
func _init(action, row, col) -> void: func _init(action, row, col) -> void:
action_type = action action_type = action
cell_row = row cell_row = row
cell_col = col cell_col = col
activated = false
class UndoActionCorner extends UndoAction: class UndoActionCorner extends UndoAction:
func _init(action, row, col).(action, row, col) -> void: var corner_marks
pass 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: func _to_string() -> String:
match action_type: var prefix = '+' if set else '-'
UndoActions.SET_L_RIGHT: match corner_mark:
return '+L %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row] CornerMark.L_RIGHT:
UndoActions.CLEAR_L_RIGHT: return prefix+'L %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row]
return '-L %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row] CornerMark.X_RIGHT:
UndoActions.SET_X_RIGHT: return prefix+'X %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row]
return '+X %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row] CornerMark.L_DOWN:
UndoActions.CLEAR_X_RIGHT: return prefix+'L %s%d:%s'%[Common.num2alpha(cell_col-1), cell_row, Common.num2alpha(cell_col)]
return '-X %s%d:%d'%[Common.num2alpha(cell_col), cell_row-1, cell_row] CornerMark.X_DOWN:
UndoActions.SET_L_DOWN: return prefix+'X %s%d:%s'%[Common.num2alpha(cell_col-1), cell_row, Common.num2alpha(cell_col)]
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)]
_: _:
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: class UndoActionCell extends UndoAction:
var set_state var set_state
var prev_state var old_state
func _init(action, row, col, set_state, prev_state).(action, row, col) -> void: var cell_colors
func _init(action, row, col, set_state, cell_colors).(action, row, col) -> void:
self.set_state = set_state self.set_state = set_state
self.prev_state = prev_state self.old_state = set_state
self.cell_colors = cell_colors
func _to_string() -> String: func _to_string() -> String:
match action_type: match action_type:
UndoActions.SET_COLOR: 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] return 'unk %d %s%d'%[action_type, Common.num2alpha(cell_col), cell_row]
func set_cell_color(row, col, new_color): func activate() -> void:
var old_color = cell_colors.get_cell(row, col) assert(not activated)
if old_color != new_color: activated = true
cell_colors.set_cell(row, col, new_color) match action_type:
undo_stack.append(UndoActionCell.new(UndoActions.SET_COLOR, row, col, new_color, old_color)) 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): 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): 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) do_action(UndoActionCorner.new(row, col, CornerMark.L_RIGHT, true, corner_marks))
undo_stack.append(UndoActionCorner.new(UndoActions.SET_L_RIGHT, row, col))
func set_line_down(row, col): 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): 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) do_action(UndoActionCorner.new(row, col, CornerMark.L_DOWN, true, corner_marks))
undo_stack.append(UndoActionCorner.new(UndoActions.SET_L_DOWN, row, col))
func clear_line_right(row, col): func clear_line_right(row, col):
if corner_marks.get_flag(row, col, CornerMark.L_RIGHT): if corner_marks.get_flag(row, col, CornerMark.L_RIGHT):
corner_marks.clear_flag(row, col, CornerMark.L_RIGHT) do_action(UndoActionCorner.new(row, col, CornerMark.L_RIGHT, false, corner_marks))
undo_stack.append(UndoActionCorner.new(UndoActions.CLEAR_L_RIGHT, row, col))
func clear_line_down(row, col): func clear_line_down(row, col):
if corner_marks.get_flag(row, col, CornerMark.L_DOWN): if corner_marks.get_flag(row, col, CornerMark.L_DOWN):
corner_marks.clear_flag(row, col, CornerMark.L_DOWN) do_action(UndoActionCorner.new(row, col, CornerMark.L_DOWN, false, corner_marks))
undo_stack.append(UndoActionCorner.new(UndoActions.CLEAR_L_DOWN, row, col))
func set_x_right(row, col): 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): 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) do_action(UndoActionCorner.new(row, col, CornerMark.X_RIGHT, true, corner_marks))
undo_stack.append(UndoActionCorner.new(UndoActions.SET_X_RIGHT, row, col))
func set_x_down(row, col): 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): 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) do_action(UndoActionCorner.new(row, col, CornerMark.X_DOWN, true, corner_marks))
undo_stack.append(UndoActionCorner.new(UndoActions.SET_X_DOWN, row, col))
func clear_x_right(row, col): func clear_x_right(row, col):
if corner_marks.get_flag(row, col, CornerMark.X_RIGHT): if corner_marks.get_flag(row, col, CornerMark.X_RIGHT):
corner_marks.clear_flag(row, col, CornerMark.X_RIGHT) do_action(UndoActionCorner.new(row, col, CornerMark.X_RIGHT, false, corner_marks))
undo_stack.append(UndoActionCorner.new(UndoActions.CLEAR_X_RIGHT, row, col))
func clear_x_down(row, col): func clear_x_down(row, col):
if corner_marks.get_flag(row, col, CornerMark.X_DOWN): if corner_marks.get_flag(row, col, CornerMark.X_DOWN):
corner_marks.clear_flag(row, col, CornerMark.X_DOWN) do_action(UndoActionCorner.new(row, col, CornerMark.X_DOWN, false, corner_marks))
undo_stack.append(UndoActionCorner.new(UndoActions.CLEAR_X_DOWN, row, col))