Skip to content
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

search-filter.lua #846

Closed
wants to merge 11 commits into from
Closed

search-filter.lua #846

wants to merge 11 commits into from

Conversation

unboundlopez
Copy link

@unboundlopez unboundlopez commented Sep 30, 2023

This code introduces a "Unit Search Engine" feature to Dwarf Fortress. It allows you to search for and select units within the game, simplifying the process of managing your fortress. I'm satisfied with the program's current functionality and have no plans to make further changes, the DFHack community master programmers can take over its maintenance and development. This feature can greatly enhance your Dwarf Fortress experience, making it easier to locate and interact with specific units in your fortress.

Dwarf.Fortress.2023.10.05-00.26.webm

unboundlopez and others added 6 commits September 30, 2023 14:53
Searches dwarf citizens through a widget/window.

Things to do is add ctrl + f to launch search-filter or alt + f. Well, any shortcut works as long as it's convenient.
hopefully fixed trailing white spaces
Cleared the whitespace
Search for EOL in VScode settings and click on '\n' to make LF default
@unboundlopez
Copy link
Author

pre-commit.ci autofix

pre-commit-ci bot and others added 5 commits September 30, 2023 21:23
I think I'm done. May be compatible with others.
I believe I'm done. I couldn't figure out how to add panels/tabs/buttons to the widget, but that's ok. I changed the conditions so visitors and hostile can be searched alongside citizens using the program.
Copy link
Member

@myk002 myk002 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments in this code appear to violate rule 1 for code comment best practices: https://stackoverflow.blog/2021/12/23/best-practices-for-writing-code-comments/
that is, the comments are all either misleading or duplicate the code, which makes maintenance more difficult.

as far as I can tell, the code would be clearer if all comments were removed

at a higher level, though, given the complexity of getting this right, would it be perhaps better to implement it as search functionality for the vanilla units list? then you wouldn't have to depend on hacky workarounds for unit selection, and people would benefit from search without having to open a separate DFHack window. The data structures are in df.global.game.main_interface.info.cri_unit

Comment on lines +34 to +38
local unitName = dfhack.TranslateName(dfhack.units.getVisibleName(unit))
if unitName == "" then
-- Use the race name if the unit's name field is empty
unitName = dfhack.units.getRaceName(unit)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dfhack.units.getReadableName(unit) would be a better fit here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added excessive comments because I'm not a programmer. These comments in the code are most likely wrong, and I'm open to having them all removed.

Regarding the program's functionality, it successfully realized my initial vision, which makes me satisfied. Additionally, I believe it's crucial to maintain the graphical user interface for the search filter program, as it offers an accessibility feature that I would greatly miss.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I'm not interested in any recognition/credit so if someone is interested in taking all the code and calling it their own. I'm 100% happy with that. I just want others to enjoy the ability to ctrl+f aka use a search engine.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also feel free to contact me on discord: unboundlopez

Comment on lines +16 to +27
widgets.EditField{
view_id='edit',
frame={t=1, l=1}, -- Position of the EditField view
text='', -- Initial text in the EditField view
on_change=self:callback('updateList'), -- Callback function when text in EditField changes
},
widgets.List{
view_id='list',
frame={t=3, b=0},
choices=self:getFortControlledUnits(), -- Choices in the List view are obtained from getFortControlledUnits function
on_select=self:callback('onSelect'), -- Callback function when a unit is selected from the list
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a widgets.FilteredList

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat. Idk how to properly change it on the git hub or the code. I'm ok with the code being taken over by someone else.

unitName = dfhack.units.getRaceName(unit)
end
if dfhack.units.isVisible(unit) and dfhack.units.isActive(unit) then
table.insert(fortControlledUnits, {text=unitName, search_normalized=dfhack.toSearchNormalized(unitName), id=unit.id})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set search_key instead of search_normalized, and you don't need to normalize the key yourself with toSearchNormalized. that is handled by widgets.FilteredList

Comment on lines +47 to +59
function SearchEngine:updateList()
local input = dfhack.toSearchNormalized(self.subviews.edit.text)
local fortControlledUnits = self:getFortControlledUnits()
local filtered_fortControlledUnits = {}

for _, unit in ipairs(fortControlledUnits) do
if string.find(unit.search_normalized, input) then
table.insert(filtered_fortControlledUnits, unit)
end
end

self.subviews.list:setChoices(filtered_fortControlledUnits)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be removed once you move from widgets.List to widgets.FilteredList

self.subviews.list:setChoices(filtered_fortControlledUnits)
end

function SearchEngine:onSelect(index, unit)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please fix the indentation for this function

Comment on lines +77 to +80
-- Enable mouse tracking and set the left mouse button as pressed
df.global.enabler.tracking_on = 1
df.global.enabler.mouse_lbut = 1
df.global.enabler.mouse_lbut_down = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
-- Enable mouse tracking and set the left mouse button as pressed
df.global.enabler.tracking_on = 1
df.global.enabler.mouse_lbut = 1
df.global.enabler.mouse_lbut_down = 1

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mouse button state is handled by gui.simulateInput()

df.global.enabler.mouse_lbut_down = 1

-- Simulate a left mouse click at the current mouse position
gui.simulateInput(dfhack.gui.getDFViewscreen(), '_MOUSE_R')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are you simulating a right click here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I simulate a right click there is sometimes the program clicks on a object like a object or unit that doesn't want to get off the screen. Therefore, a right click somewhere in the screen closes out that pesky character sheet of the object that doesn't want to close.

Comment on lines +87 to +90
-- Disable mouse tracking and set the left mouse button as not pressed
df.global.enabler.tracking_on = 0
df.global.enabler.mouse_lbut = 0
df.global.enabler.mouse_lbut_down = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
-- Disable mouse tracking and set the left mouse button as not pressed
df.global.enabler.tracking_on = 0
df.global.enabler.mouse_lbut = 0
df.global.enabler.mouse_lbut_down = 0

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gui.simulateInput() also handles mouse state restoration after sending input to the target screen

-- Screen creation
SearchEngineScreen = defclass(SearchEngineScreen, gui.ZScreen)
SearchEngineScreen.ATTRS = {
focus_path='SearchEngine',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

focus path should match the script name (search-filter, or whatever we decide to rename this to)

-- Simulate a left mouse click at the current mouse position
gui.simulateInput(dfhack.gui.getDFViewscreen(), '_MOUSE_R')

gui.simulateInput(dfhack.gui.getDFViewscreen(), '_MOUSE_L')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some more logic is needed here to make sure that the unit is the selected focus of the panel. if more than one "thing" is on that tile, it might be an item or a different unit that is selected. You'd need to also click on the "tab" to bring up the appropriate unit:
image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that you can't just change df.global.game.main_interface.view_sheets.active_id because that won't update the displayed text

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is upsetting having the search filter bring up multiple units/objects when they are on top of each other. However, I personally don't mind clicking on the stacked pile of dwarf's/animals/monsters as I don't know how to bring up the searched name to the forefront when this occurs.

@myk002
Copy link
Member

myk002 commented Oct 12, 2023

closing this as search functionality was integrated into the vanilla screens

@myk002 myk002 closed this Oct 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants