From 20868d6b4405bca2e7cd7c6d640dce74c4c9bb73 Mon Sep 17 00:00:00 2001 From: DarkPhoenix Date: Sun, 29 Sep 2019 23:41:45 +0300 Subject: [PATCH] Add ability to change projection range of fits --- eos/db/saveddata/fit.py | 1 + eos/effects.py | 5 +- gui/builtinContextMenus/__init__.py | 1 + .../itemProjectionRange.py | 128 ++++++++++++++++++ gui/builtinViewColumns/projectionRange.py | 9 +- gui/fitCommands/__init__.py | 1 + .../projectedFit/changeProjectionRange.py | 60 ++++++++ .../gui/projectedFit/changeRange.py | 40 ++++++ 8 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 gui/builtinContextMenus/itemProjectionRange.py create mode 100644 gui/fitCommands/calc/projectedFit/changeProjectionRange.py create mode 100644 gui/fitCommands/gui/projectedFit/changeRange.py diff --git a/eos/db/saveddata/fit.py b/eos/db/saveddata/fit.py index 32a7be52c..c105516b2 100644 --- a/eos/db/saveddata/fit.py +++ b/eos/db/saveddata/fit.py @@ -84,6 +84,7 @@ commandFits_table = Table("commandFits", saveddata_meta, class ProjectedFit: + def __init__(self, sourceID, source_fit, amount=1, active=True): self.sourceID = sourceID self.source_fit = source_fit diff --git a/eos/effects.py b/eos/effects.py index fbb9ecf38..65cf00538 100644 --- a/eos/effects.py +++ b/eos/effects.py @@ -204,7 +204,7 @@ class Effect39(BaseEffect): @staticmethod def handler(fit, module, context, projectionRange, **kwargs): - if 'projected' in context and module.maxRange >= (projectionRange or 0): + if 'projected' in context and module.getModifiedItemAttr('maxRange', 0) >= (projectionRange or 0): fit.ship.increaseItemAttr('warpScrambleStatus', module.getModifiedItemAttr('warpScrambleStrength'), **kwargs) @@ -23368,7 +23368,8 @@ class Effect5934(BaseEffect): def handler(fit, module, context, projectionRange, **kwargs): if 'projected' not in context: return - + if module.getModifiedItemAttr('maxRange', 0) < (projectionRange or 0): + return fit.ship.increaseItemAttr('warpScrambleStatus', module.getModifiedItemAttr('warpScrambleStrength')) fit.modules.filteredItemIncrease( lambda mod: mod.item.requiresSkill('High Speed Maneuvering') or mod.item.requiresSkill('Micro Jump Drive Operation'), diff --git a/gui/builtinContextMenus/__init__.py b/gui/builtinContextMenus/__init__.py index bda64884b..0750f7075 100644 --- a/gui/builtinContextMenus/__init__.py +++ b/gui/builtinContextMenus/__init__.py @@ -22,6 +22,7 @@ from gui.builtinContextMenus import shipJump # Generic item manipulations from gui.builtinContextMenus import itemRemove from gui.builtinContextMenus import itemAmountChange +from gui.builtinContextMenus import itemProjectionRange from gui.builtinContextMenus import droneSplitStack from gui.builtinContextMenus import itemVariationChange from gui.builtinContextMenus import moduleMutations diff --git a/gui/builtinContextMenus/itemProjectionRange.py b/gui/builtinContextMenus/itemProjectionRange.py new file mode 100644 index 000000000..7110069d9 --- /dev/null +++ b/gui/builtinContextMenus/itemProjectionRange.py @@ -0,0 +1,128 @@ +import re + +# noinspection PyPackageRequirements +import wx + +import gui.fitCommands as cmd +import gui.mainFrame +from eos.saveddata.drone import Drone +from eos.saveddata.fighter import Fighter +from eos.saveddata.fit import Fit as es_Fit +from eos.saveddata.module import Module +from gui.contextMenu import ContextMenuSingle +from service.fit import Fit + + +class ChangeItemProjectionRange(ContextMenuSingle): + + def __init__(self): + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + + def display(self, callingWindow, srcContext, mainItem): + if srcContext not in ('projectedFit', 'projectedModule', 'projectedDrone', 'projectedFighter'): + return False + if mainItem is None: + return False + return True + + def getText(self, callingWindow, itmContext, mainItem): + return 'Change {} Range'.format(itmContext) + + def activate(self, callingWindow, fullContext, mainItem, i): + fitID = self.mainFrame.getActiveFit() + srcContext = fullContext[0] + if isinstance(mainItem, es_Fit): + try: + value = mainItem.getProjectionInfo(fitID).projectionRange + except AttributeError: + return + else: + value = mainItem.projectionRange + if value is not None: + value /= 1000 + with RangeChanger(self.mainFrame, value) as dlg: + if dlg.ShowModal() == wx.ID_OK: + sFit = Fit.getInstance() + fit = sFit.getFit(fitID) + cleanInput = re.sub(r'[^0-9.]', '', dlg.input.GetLineText(0).strip()) + if cleanInput: + try: + cleanInputFloat = float(cleanInput) + except ValueError: + return + newRange = cleanInputFloat * 1000 + else: + newRange = None + + if isinstance(mainItem, es_Fit): + self.mainFrame.command.Submit(cmd.GuiChangeProjectedFitRangeCommand( + fitID=fitID, projectedFitID=mainItem.ID, projectionRange=newRange)) + elif isinstance(mainItem, Module): + if mainItem in fit.projectedModules: + position = fit.projectedModules.index(mainItem) + pass + elif isinstance(mainItem, Drone): + pass + elif isinstance(mainItem, Fighter): + if mainItem in fit.projectedFighters: + position = fit.projectedFighters.index(mainItem) + pass + + +ChangeItemProjectionRange.register() + + +class RangeChanger(wx.Dialog): + + def __init__(self, parent, value): + super().__init__(parent, title='Change Projection Range', style=wx.DEFAULT_DIALOG_STYLE) + self.SetMinSize((346, 156)) + + bSizer1 = wx.BoxSizer(wx.VERTICAL) + + bSizer2 = wx.BoxSizer(wx.VERTICAL) + text = wx.StaticText(self, wx.ID_ANY, 'New Range, km:') + bSizer2.Add(text, 0) + + bSizer1.Add(bSizer2, 0, wx.ALL, 10) + + self.input = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER) + if value is None: + value = '' + else: + if value == int(value): + value = int(value) + value = str(value) + self.input.SetValue(value) + self.input.SelectAll() + + bSizer1.Add(self.input, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 15) + + bSizer3 = wx.BoxSizer(wx.VERTICAL) + bSizer3.Add(wx.StaticLine(self, wx.ID_ANY), 0, wx.BOTTOM | wx.EXPAND, 15) + + bSizer3.Add(self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND) + bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10) + + self.input.SetFocus() + self.input.Bind(wx.EVT_CHAR, self.onChar) + self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter) + self.SetSizer(bSizer1) + self.CenterOnParent() + self.Fit() + + def processEnter(self, evt): + self.EndModal(wx.ID_OK) + + # checks to make sure it's valid number + @staticmethod + def onChar(event): + key = event.GetKeyCode() + + acceptable_characters = '1234567890.' + acceptable_keycode = [3, 22, 13, 8, 127] # modifiers like delete, copy, paste + if key in acceptable_keycode or key >= 255 or (key < 255 and chr(key) in acceptable_characters): + event.Skip() + return + else: + return False diff --git a/gui/builtinViewColumns/projectionRange.py b/gui/builtinViewColumns/projectionRange.py index db7765946..4a08fecb6 100644 --- a/gui/builtinViewColumns/projectionRange.py +++ b/gui/builtinViewColumns/projectionRange.py @@ -23,6 +23,7 @@ import wx from logbook import Logger import gui.mainFrame +from eos.saveddata.fit import Fit from gui.bitmap_loader import BitmapLoader from gui.utils.numberFormatter import formatAmount from gui.viewColumn import ViewColumn @@ -41,10 +42,14 @@ class ProjectionRangeColumn(ViewColumn): self.imageId = fittingView.imageList.GetImageIndex(1391, "icons") self.bitmap = BitmapLoader.getBitmap(1391, "icons") self.mask = wx.LIST_MASK_IMAGE - self.projectedView = isinstance(fittingView, gui.builtinAdditionPanes.projectedView.ProjectedView) def getText(self, stuff): - projRange = getattr(stuff, 'projectionRange', None) + if isinstance(stuff, Fit): + fitID = self.mainFrame.getActiveFit() + info = stuff.getProjectionInfo(fitID) + projRange = info.projectionRange + else: + projRange = getattr(stuff, 'projectionRange', None) if projRange is None: return '' return formatAmount(projRange, 3, 0, 3, unitName='m') diff --git a/gui/fitCommands/__init__.py b/gui/fitCommands/__init__.py index 2bf839a22..ebdd31667 100644 --- a/gui/fitCommands/__init__.py +++ b/gui/fitCommands/__init__.py @@ -66,6 +66,7 @@ from .gui.projectedFighter.changeAmount import GuiChangeProjectedFighterAmountCo from .gui.projectedFighter.changeMetas import GuiChangeProjectedFighterMetasCommand from .gui.projectedFit.add import GuiAddProjectedFitsCommand from .gui.projectedFit.changeAmount import GuiChangeProjectedFitAmountCommand +from .gui.projectedFit.changeRange import GuiChangeProjectedFitRangeCommand from .gui.projectedModule.add import GuiAddProjectedModuleCommand from .gui.projectedModule.changeCharges import GuiChangeProjectedModuleChargesCommand from .gui.projectedModule.changeMetas import GuiChangeProjectedModuleMetasCommand diff --git a/gui/fitCommands/calc/projectedFit/changeProjectionRange.py b/gui/fitCommands/calc/projectedFit/changeProjectionRange.py new file mode 100644 index 000000000..aae50c7c8 --- /dev/null +++ b/gui/fitCommands/calc/projectedFit/changeProjectionRange.py @@ -0,0 +1,60 @@ +import wx +from logbook import Logger + +from gui.fitCommands.helpers import restoreCheckedStates +from service.fit import Fit + + +pyfalog = Logger(__name__) + + +class CalcChangeProjectedFitProjectionRangeCommand(wx.Command): + + def __init__(self, fitID, projectedFitID, projectionRange): + wx.Command.__init__(self, True, 'Change Projected Fit Projection Range') + self.fitID = fitID + self.projectedFitID = projectedFitID + self.projectionRange = projectionRange + self.savedProjectionRange = None + self.savedStateCheckChanges = None + + def Do(self): + pyfalog.debug('Doing change of projected fit {} range to {} for fit {}'.format(self.projectedFitID, self.projectionRange, self.fitID)) + sFit = Fit.getInstance() + fit = sFit.getFit(self.fitID) + projectedFit = sFit.getFit(self.projectedFitID, projected=True) + # Projected fit could have been deleted if we are redoing + if projectedFit is None: + pyfalog.debug('Projected fit is not available') + return False + projectionInfo = projectedFit.getProjectionInfo(self.fitID) + if projectionInfo is None: + pyfalog.warning('Fit projection info is not available') + return False + self.savedProjectionRange = projectionInfo.projectionRange + if self.projectionRange == self.savedProjectionRange: + return False + projectionInfo.projectionRange = self.projectionRange + + sFit.recalc(fit) + self.savedStateCheckChanges = sFit.checkStates(fit, None) + return True + + def Undo(self): + pyfalog.debug('Undoing change of projected fit {} range to {} for fit {}'.format(self.projectedFitID, self.projectionRange, self.fitID)) + cmd = CalcChangeProjectedFitProjectionRangeCommand( + fitID=self.fitID, + projectedFitID=self.projectedFitID, + projectionRange=self.savedProjectionRange) + result = cmd.Do() + restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges) + return result + + @property + def needsGuiRecalc(self): + if self.savedStateCheckChanges is None: + return True + for container in self.savedStateCheckChanges: + if len(container) > 0: + return True + return False diff --git a/gui/fitCommands/gui/projectedFit/changeRange.py b/gui/fitCommands/gui/projectedFit/changeRange.py new file mode 100644 index 000000000..bb3549118 --- /dev/null +++ b/gui/fitCommands/gui/projectedFit/changeRange.py @@ -0,0 +1,40 @@ +import wx + +import eos.db +import gui.mainFrame +from gui import globalEvents as GE +from gui.fitCommands.calc.projectedFit.changeProjectionRange import CalcChangeProjectedFitProjectionRangeCommand +from gui.fitCommands.helpers import InternalCommandHistory +from service.fit import Fit + + +class GuiChangeProjectedFitRangeCommand(wx.Command): + + def __init__(self, fitID, projectedFitID, projectionRange): + wx.Command.__init__(self, True, 'Change Projected Fit Projection Range') + self.internalHistory = InternalCommandHistory() + self.fitID = fitID + self.projectedFitID = projectedFitID + self.projectionRange = projectionRange + + def Do(self): + cmd = CalcChangeProjectedFitProjectionRangeCommand(fitID=self.fitID, projectedFitID=self.projectedFitID, projectionRange=self.projectionRange) + success = self.internalHistory.submit(cmd) + sFit = Fit.getInstance() + if cmd.needsGuiRecalc: + eos.db.flush() + sFit.recalc(self.fitID) + sFit.fill(self.fitID) + eos.db.commit() + wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,))) + return success + + def Undo(self): + success = self.internalHistory.undoAll() + eos.db.flush() + sFit = Fit.getInstance() + sFit.recalc(self.fitID) + sFit.fill(self.fitID) + eos.db.commit() + wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,))) + return success