-
Notifications
You must be signed in to change notification settings - Fork 232
Fix: quickfort UI freeze on large blueprints and strip undocumented ghost-features #1597
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -129,7 +129,7 @@ function BlueprintDialog:init() | |
| }, | ||
| widgets.HotkeyLabel{ | ||
| frame={b=0, l=15}, | ||
| key='SELECT_ALL', -- TODO: change to SEC_SELECT once 51.01 is stable | ||
| key='SEC_SELECT', | ||
| label='Delete selected blueprint', | ||
| on_activate=self:callback('delete_blueprint'), | ||
| enabled=function() | ||
|
|
@@ -545,35 +545,8 @@ function Quickfort:on_transform_change(val) | |
| self.dirty = true | ||
| end | ||
|
|
||
| local origin, test_point = {x=0, y=0}, {x=1, y=-2} | ||
| local minimal_sequence = { | ||
| ['x=1, y=-2'] = {}, | ||
| ['x=2, y=-1'] = {'cw', 'flipv'}, | ||
| ['x=2, y=1'] = {'cw'}, | ||
| ['x=1, y=2'] = {'flipv'}, | ||
| ['x=-1, y=2'] = {'cw', 'cw'}, | ||
| ['x=-2, y=1'] = {'ccw', 'flipv'}, | ||
| ['x=-2, y=-1'] = {'ccw'}, | ||
| ['x=-1, y=-2'] = {'fliph'} | ||
| } | ||
|
|
||
| -- reduces the list of transformations to a minimal sequence | ||
| local function reduce_transform(elements) | ||
| local pos = test_point | ||
| for _,elem in ipairs(elements) do | ||
| pos = quickfort_transform.make_transform_fn_from_name(elem)(pos, origin) | ||
| end | ||
| local ret = quickfort_transform.resolve_vector(pos, minimal_sequence) | ||
| if #ret == #elements then | ||
| -- if we're not making the sequence any shorter, prefer the existing set | ||
| return elements | ||
| end | ||
| return copyall(ret) | ||
| end | ||
|
|
||
| function Quickfort:on_transform(val) | ||
| table.insert(transformations, val) | ||
| transformations = reduce_transform(transformations) | ||
| self:updateLayout() | ||
|
Comment on lines
547
to
550
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see any reason to remove this code. without it, the UI Label would grow without bound as the user applies multiple transformations. this code is beneficial, and it only runs when the user applies a transformation, so it doesn't impact the performance per the stated intent of the PR. |
||
| self.dirty = true | ||
| end | ||
|
|
@@ -683,26 +656,61 @@ function Quickfort:onRenderFrame(dc, rect) | |
|
|
||
| -- if the (non-locked) cursor has moved since last preview processing or any | ||
| -- settings have changed, regenerate the preview | ||
| local cursor = dfhack.gui.getMousePos() or self.saved_cursor | ||
| if self.dirty or not same_xyz(self.saved_cursor, cursor) then | ||
| if not self.cursor_locked then | ||
| self.saved_cursor = cursor | ||
| local mouse_pos = dfhack.gui.getMousePos() or self.saved_cursor | ||
| local draw_cursor = self.cursor_locked and self.saved_cursor or mouse_pos | ||
|
|
||
| if not self.cursor_locked and not same_xyz(self.saved_cursor, mouse_pos) then | ||
| self.target_cursor = mouse_pos | ||
| self.dirty = true | ||
| end | ||
|
|
||
| if self.dirty then | ||
| local now = os.clock() | ||
| -- wait at least 0.05s (50ms) between heavy recalculations | ||
| if not self.last_refresh_time or (now - self.last_refresh_time > 0.05) then | ||
|
Comment on lines
+668
to
+670
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I'd prefer this be based on frames instead of wall clock. ticks are of course not relevant, because ZScreen. |
||
| if self.target_cursor then | ||
| self.saved_cursor = self.target_cursor | ||
| self.target_cursor = nil | ||
| end | ||
| self:refresh_preview() | ||
| -- record time AFTER the heavy computation to guarantee breathing room for the engine | ||
| self.last_refresh_time = os.clock() | ||
| self.dirty = false | ||
| end | ||
| self:refresh_preview() | ||
| self.dirty = false | ||
| end | ||
|
|
||
| local tiles = self.saved_preview.tiles | ||
| if not tiles[cursor.z] then return end | ||
| local src_z = self.saved_cursor.z + (mouse_pos.z - draw_cursor.z) | ||
| if not tiles[src_z] then return end | ||
|
|
||
| local dx = draw_cursor.x - self.saved_cursor.x | ||
| local dy = draw_cursor.y - self.saved_cursor.y | ||
| local dz = draw_cursor.z - self.saved_cursor.z | ||
|
|
||
| local bounds = self.saved_preview.bounds[src_z] | ||
| if not bounds then return end | ||
|
|
||
| local shifted_bounds = { | ||
| x1 = bounds.x1 + dx, | ||
| x2 = bounds.x2 + dx, | ||
| y1 = bounds.y1 + dy, | ||
| y2 = bounds.y2 + dy | ||
| } | ||
|
|
||
| local function get_overlay_pen(pos) | ||
| if same_xyz(pos, self.saved_cursor) then return CURSOR_PEN end | ||
| local preview_tile = quickfort_preview.get_preview_tile(tiles, pos) | ||
| if same_xyz(pos, draw_cursor) then return CURSOR_PEN end | ||
|
|
||
| local old_pos = { | ||
| x = pos.x - dx, | ||
| y = pos.y - dy, | ||
| z = pos.z - dz | ||
| } | ||
| local preview_tile = quickfort_preview.get_preview_tile(tiles, old_pos) | ||
| if preview_tile == nil then return end | ||
| return preview_tile and GOOD_PEN or BAD_PEN | ||
| end | ||
|
|
||
| guidm.renderMapOverlay(get_overlay_pen, self.saved_preview.bounds[cursor.z]) | ||
| guidm.renderMapOverlay(get_overlay_pen, shifted_bounds) | ||
| end | ||
|
|
||
| function Quickfort:onInput(keys) | ||
|
|
@@ -713,6 +721,10 @@ function Quickfort:onInput(keys) | |
| if keys._MOUSE_L and not self:getMouseFramePos() then | ||
| local pos = dfhack.gui.getMousePos() | ||
| if pos then | ||
| if not self.cursor_locked then | ||
| self.saved_cursor = pos | ||
| self.target_cursor = nil | ||
| end | ||
| self:commit() | ||
| return true | ||
| end | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -93,9 +93,9 @@ setmetatable(action_switch, {__index=function() return do_help end}) | |
|
|
||
| local args = {...} | ||
| local action = table.remove(args, 1) or 'help' | ||
| args.commands = argparse.stringList(action) | ||
| args.commands = {action} | ||
|
|
||
| local action_fn = action_switch[args.commands[1]] | ||
| local action_fn = action_switch[action] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the issue this purports to fix is real, although I don't know if it's severe enough to warrant a fix. this proposed fix is wrong; it removes a documented capability for no good reason. quickfort is designed to accept multiple comma-separated commands. this proposed fix removes that capability. I recommend against merging this particular change. Edit: the fact that this capability is intentional and documented speaks against the title of this PR. "strip undocumented ghost-features". no. |
||
|
|
||
| if (action == 'run' or action == 'orders' or action == 'undo') and | ||
| not dfhack.isMapLoaded() then | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
has this been tested? can you explain what key sequence or mouse button presses this would change?
it's not enough to blithely say, oh yeah, we're way past 51.01 so let's just perform the TODO while we're in here.
SEC_SELECTshowed up as a keybinding/mousebinding between 50.15 and 51.02. what is it? isSELECT_ALLdeprecated now? what is being changed here?should this be merged? I'm honestly not sure. I don't think it would hurt, but I don't know that there's a reason to do it.