from copy import deepcopy
import numpy as np
from PySide6.QtCore import QPoint, QLineF, QRect
from RWS.Modify import HistoryElement
from RWS.Loaders import Effect
from RWS.Utils import draw_line
[docs]
def copy_effect(effect):
return deepcopy(effect) # i should come up with better solution at sometime
[docs]
class EffectBrush(HistoryElement):
[docs]
def __init__(self, history, index, start: QPoint, size: int, remove: bool, ultra: bool):
super().__init__(history)
self.changes = {}
self.start = start
self.size = size
self.remove = remove
self.ultra = ultra # kill
self.effect = history.level.manager.effects.find_effect(self.history.level.l_effects[index]["nm"])
self.index = index
self.lastpos = start
self.paintapoint(start)
self.redraw()
[docs]
def redraw(self):
self.history.level.manager.basemod.effecteditor.elayer.redraw()
[docs]
def add_move(self, position):
points = []
draw_line(self.lastpos, position, lambda p: points.append(p))
points.pop(0)
for point in points:
self.paintapoint(point)
self.lastpos = position
self.redraw()
[docs]
def paintapoint(self, point):
strength = 10 + (90 if self.ultra else 0)
if self.effect.ultrablack:
strength = 10000
rect = QRect(point - QPoint(self.size, self.size), point + QPoint(self.size, self.size))
for xp in range(rect.x(), rect.topRight().x()):
for yp in range(rect.y(), rect.bottomLeft().y()):
newpoint = QPoint(xp, yp)
if not self.history.level.inside(newpoint):
continue
cellval = int(self.history.level.l_effects[self.index, xp, yp])
val = cellval
dist = self.size - QLineF(newpoint, point).length()
if dist > 0:
val = round(min(max(val + strength * dist * (-1 if self.remove else 1), 0), 100), 4)
if val == cellval:
continue
if self.changes.get(newpoint):
self.changes[newpoint] = [self.changes[newpoint][0], val]
else:
self.changes[newpoint] = [cellval, val]
self.history.level.l_effects[self.index, xp, yp] = val
self.history.level.manager.basemod.effecteditor.elayer.draw_pixel(newpoint, True)
[docs]
def undo_changes(self):
for point, v in self.changes.items():
before, _ = v
self.history.level.l_effects[self.index, point.x(), point.y()] = before
self.history.level.manager.basemod.effecteditor.elayer.draw_pixel(point, True)
self.redraw()
[docs]
def redo_changes(self):
for point, v in self.changes.items():
_, after = v
self.history.level.l_effects[self.index, point.x(), point.y()] = after
self.history.level.manager.basemod.effecteditor.elayer.draw_pixel(point, True)
self.redraw()
[docs]
class EffectAdd(HistoryElement):
[docs]
def __init__(self, history, effect: Effect):
super().__init__(history)
self.effect = effect
self.add_effect()
[docs]
def add_effect(self):
self.level.l_effects.append(self.effect.todict(self.level.level_size_qsize))
self.basemod.effectui.add_effects()
self.basemod.effecteditor.effectindex.update_value(len(self.level.l_effects) - 1)
[docs]
def undo_changes(self):
self.level.l_effects.pop()
self.basemod.effectui.add_effects()
[docs]
def redo_changes(self):
self.add_effect()
[docs]
class EffectRemove(HistoryElement):
[docs]
def __init__(self, history, index):
super().__init__(history)
self.index = index
self.savedeffect = self.history.level.l_effects.pop(index)
self.remove_effect()
[docs]
def remove_effect(self):
self.basemod.effectui.add_effects()
self.basemod.effecteditor.effectindex.update_value(max(0, self.index - 1))
[docs]
def undo_changes(self):
self.history.level.l_effects.insert(self.index, self.savedeffect)
self.basemod.effectui.add_effects()
self.basemod.effecteditor.effectindex.update_value(max(0, self.index))
[docs]
def redo_changes(self):
self.history.level.l_effects.pop(self.index)
self.remove_effect()
[docs]
class EffectOptionChange(HistoryElement):
[docs]
def __init__(self, history, index, option, value):
super().__init__(history)
self.prevvalue = history.level.l_effects[index]["options"][option][2]
self.index = index
self.option = option
self.value = value
self.redo_changes()
[docs]
def undo_changes(self):
self.level.l_effects[self.index]["options"][self.option][2] = self.prevvalue
self.basemod.effectui.effect_settings()
[docs]
def redo_changes(self):
self.level.l_effects[self.index]["options"][self.option][2] = self.value
self.basemod.effectui.effect_settings()
[docs]
class EffectMove(HistoryElement):
[docs]
def __init__(self, history, index, dir):
super().__init__(history)
self.index = index
self.newindex = index + dir
self.redo_changes()
[docs]
def redo_changes(self):
self.level.l_effects.insert(self.newindex, self.level.l_effects.pop(self.index))
self.basemod.effectui.add_effects()
self.basemod.effecteditor.effectindex.update_value(self.newindex)
[docs]
def undo_changes(self):
self.level.l_effects.insert(self.index, self.level.l_effects.pop(self.newindex))
self.basemod.effectui.add_effects()
self.basemod.effecteditor.effectindex.update_value(self.index)
[docs]
class EffectDuplicate(HistoryElement):
[docs]
def __init__(self, history, index):
super().__init__(history)
self.index = index
self.duplicate = deepcopy(self.level.l_effects[index])
self.redo_changes()
[docs]
def redo_changes(self):
self.level.l_effects.insert(self.index+1, self.duplicate)
self.basemod.effectui.add_effects()
self.basemod.effecteditor.effectindex.update_value(self.index+1)
[docs]
def undo_changes(self):
self.level.l_effects.pop(self.index+1)
self.basemod.effectui.add_effects()
self.basemod.effecteditor.effectindex.update_value(self.index)
[docs]
class LevelResizedEffects(HistoryElement):
[docs]
def __init__(self, history, newrect):
super().__init__(history)
self.newrect = newrect
self.preveffects = []
self.redo_changes()
[docs]
def undo_changes(self):
for i, v in enumerate(self.level.l_effects.effects):
v["mtrx"] = np.copy(self.preveffects[i])
[docs]
def redo_changes(self):
for i, v in enumerate(self.level.l_effects.effects):
newshape = np.zeros((self.newrect.width(), self.newrect.height()), np.float16)
self.preveffects.append(np.copy(v["mtrx"]))
with np.nditer(newshape, flags=['multi_index'], op_flags=['writeonly']) as it:
for x in it:
if it.multi_index[0] < -self.newrect.x() or it.multi_index[1] < -self.newrect.y():
x[...] = 0
continue
newpoints = [it.multi_index[0] + self.newrect.x(), it.multi_index[1] + self.newrect.y()]
if newpoints[0] >= v["mtrx"].shape[0] or newpoints[1] >= v["mtrx"].shape[1]:
x[...] = 0
continue
x[...] = v["mtrx"][newpoints[0], newpoints[1]]
v["mtrx"] = newshape