Open emk opened 1 week ago
OK, some notes from the API:
Signals. If we look up .signals
on a circuit network like this:
/c helpers.write_file('quality-signals.json', serpent.block(game.surfaces[5].find_entities_filtered{name='hud-combinator'}[1].get_circuit_network(2).signals))
...we get an array of signals in ItemIDAndQualityIDPair
format:
{
count = 707,
signal = {
name = "quality-module-3"
}
},
{
count = 384,
signal = {
name = "quality-module-3",
quality = "uncommon"
}
},
{
count = 63,
signal = {
name = "quality-module-3",
quality = "rare"
}
},
If quality
is omitted, that means it's common
.
Filters. If I'm reading the docs right, these should look something like:
{
name = "quality-module-3',
quality = 'uncommon',
comparator = '≥'
}
But name
is optional, so we may get filters like:
{
quality = 'uncommon',
comparator = '≥'
}
Or we may see filters like:
{
name = "quality-module-3',
}
Presumably, if we make sure that we recognize these values when returned from the API, and we pass them to the right API calls, we should be able to get most things working pretty quickly.
Other things we may need to do. We might also need to:
comparator
and quality
, if present. This is implemented by filter_signal
in hud-gui.lua
, and it should be easy to fix.storage.filters
in combinator.lua
, I believe. This would probably need to change from a list of strings to a list of filter tables, as seen above. There's already migration.lua
with support for migrating data.sprite-button
. The existing code uses sprite-button
with sprite = 'signal_type/signal_name
, but there's no documented way to pass quality. But quality doesn't seem to be 100% documented, either, so it might be worth looking at other mods.Huh, the really hard part about all of this seems to be rendering the signal images with both a number and a quality?
LuaGuiElement is currently used to display each signal, using type = "sprite-button"
. This can display the sprite and a number, but not a quality. Or you could do this:
table[table_name].add {
type = "choose-elem-button",
elem_type = "signal",
signal = { type = signal_type, name = signal_name, quality = "uncommon" },
-- sprite = const.SIGNAL_TYPE_MAP[signal_type] .. "/" .. signal_name,
-- quality = "uncommon",
number = signal.count,
style = network_styles[i],
tooltip = signal_name_map[signal_type][signal_name].localised_name
}
...but that displays the quality and ignores number
.
Using Control-F6 on the combinator windows shows that they have some nice C++ widgets for displaying signals, but they're not exported to Lua. Similarly, the logistics buttons in the inventory screen, and the filter button in the splitter UI seem to be using options that aren't available to Lua.
So displaying filters and signals actually seems like the hardest part of this.
I still haven't found a way to get signal.signal.quality
an signal.count
onto the same icon. The best I have found is this:
local signal_quality = signal.signal.quality or "common"
...
table[table_name].add {
type = "label",
caption = "[item=" .. signal_name .. ",quality=" .. signal_quality .. "] " .. signal.count,
tooltip = signal_name_map[signal_type][signal_name].localised_name
}
...which gives us:
(Well, that first quality indicator is wrong, but that was a bug in my code.)
This is going to have horizontal alignment issues as the numbers change, and it doesn't match the standard C++ UI widgets that Factorio uses internally:
But so far, labels are the best way I've found to display signals with both quantities and counts from Lua.
How do people feel about some version of the Lua UI with counts next to icons?
Pinging @hgschmie for his input
I transferred most of the maintaining of this mod to @hgschmie since I quit Factorio but would love to see this mod live on.
About the counts next to icons, is this a missing mod feature in the API for these types of icons? Are there maybe other mods that have solved this issue from which you can steal the solution?
Ideally, this feature would be implemented without breaking existing functionality or have it be an optional experimental feature that can be enabled in the settings.
Either way, this sounds like a great addition! And my compliments for your detailed and extensive write-up!
About the counts next to icons, is this a missing mod feature in the API for these types of icons? Are there maybe other mods that have solved this issue from which you can steal the solution?
I spent several hours last night digging through modding APIs, the Factorio data
directory, other mods' source code, etc. I also tried lots of experiments with LuaGuiElement
, looking for undocumented features. I used the built-in GUI inspector to see how Factorio did it, and discovered that in every case, they were using C++ GUI elements that aren't available in Lua.
I have not been able to find any way to get both quality and count displayed as a single icon, like the game's C++ code does. If it's there, it's exceptionally well hidden.
The problem seems to be that quality is implemented about 25% in C++ and 75% in an optional Lua mod. The UI bits are all in the engine itself, and very few of them seem to be exported to Lua. I imagine this will get fixed in several months. But for now, I can't do any better than you see above—quality on the icon, and a count next to it.
Ideally, this feature would be implemented without breaking existing functionality or have it be an optional experimental feature that can be enabled in the settings.
Obviously, we shouldn't break anyone's setup or save game, ever.
But at the same time, not displaying quality, or only optionally displaying quality, feels like it's simply a bug? "Uncommon iron plate" is a completely different signal than "Iron plate". Essentially, quality levels create completely new items that can't be used in place of common items. So the signals are completely distinct. If they're present, we should always display them with quality information.
Complex filters. On another note, it doesn't look like the complex filters used in splitters, things like "iron plates of quality uncommon or better" are actually available to the Lua API. at all. So it's probably better to omit these kinds of complex filters for now, and wait for API support.
So my proposed feature list is now:
OK, here's a basic prototype! This is the best-looking UI that I can figure out how to create with the current modding API:
And here are the code changes I made. They're really simple. (Unfold to view.)
No data migration is necessary; the existing filter code actually saves and loads quality information correctly.
I could submit this as a PR, if people are happy with this! But if someone wants to try to find better UI options, I am very much open to suggestions!
Looks good! Please make a PR and add a setting option with "Enable experimental item quality display" or something better you can think off, and then I'm happy to merge
(Looking at this in game some more, I think we may also need to change the table to have fewer columns when displaying things like this.)
There is a setting to change columns(rows):
Ah, excellent!
In addition to changing the width there, we would want to adjust the calculation:
width = (max_columns_allowed * (36 + 4)) + 40
...to use 52 instead of 36, to account for the wider grid cells.
Doing that, then manually adjusting Max HUD items per row to 4, and using format_number
to format the numbers, we get this:
This seems to be pretty reasonable, if we want to properly display quality signals using the current mod APIs. I'm not sure if we can do much better without changes to Factorio itself.
I'll send a PR this weekend, which will give me to time figure out how to add a preference for switching between the old-style and the new-style signal displays.
Great! Thanks for all the effort!
I did some work on CircuitHUD today (did you notice that you could not build it on a space station?). I will look at the PR and merge the changes into a new PR for 2.2.0.
I think the discrepancy between the icons available in lua and the C++ code is a bug / issue; I will see if I can get someone from Wube to fix this.
I will probably push 2.1.0 out and then make these changes a 2.1.1 or a 2.2.0
[@JasonLandbridge That every push to master is a new release is good and bad. Can we make that github action manually triggerable (but only by owner/collaborators on the repo)?
[@JasonLandbridge That every push to master is a new release is good and bad. Can we make that github action manually triggerable (but only by owner/collaborators on the repo)?
Done! Can you check if you can run the action?
I have posted https://forums.factorio.com/viewtopic.php?f=28&t=122689 about the "sprite button with quality and number". Usually the Wube folks are pretty responsive in that forum. Worst case, we get "nah, won't do that", in that case we can still merge this PR.
about the quality icons. You can actually get pretty close with sprite-button:
The five chests represent a chest each with a different quality. If you hover over them, they do show the correct element tooltip with
diff --git a/gui/hud-gui.lua b/gui/hud-gui.lua
index da57270..bdb0807 100644
--- a/gui/hud-gui.lua
+++ b/gui/hud-gui.lua
@@ -13,12 +13,12 @@ local gui_hud = {}
-- Checks if the signal is allowed to be shown based on the filters set for this HUD Combinator
-- @returns if signal is allowed to be shown
-local function filter_signal(signals, name)
+local function filter_signal(signals, signal)
if table_size(signals) == 0 then
return true
end
for _, value in pairs(signals) do
- if value.name == name then
+ if value.name == signal.signal.name and value.quality == signal.signal.quality then
return true
end
end
@@ -180,14 +180,25 @@ function gui_hud.render_signals(hud_combinator, parent_gui, max_columns, signals
end
-- Check if this signal should be shown based on filtering
- if common.short_if(should_filter, filter_signal(signals_filter, signal_name), true) then
- table[table_name].add {
+ if common.short_if(should_filter, filter_signal(signals_filter, signal), true) then
+ local button = {
type = "sprite-button",
sprite = const.SIGNAL_TYPE_MAP[signal_type] .. "/" .. signal_name,
number = signal.count,
style = network_styles[i],
- tooltip = signal_name_map[signal_type][signal_name].localised_name
+ tooltip = signal_name_map[signal_type][signal_name].localised_name,
}
+
+ if signal_type == 'item' then
+ button.elem_tooltip = {
+ type = 'item-with-quality',
+ name = signal_name,
+ quality = signal.signal.quality,
+ }
+ end
+
+ table[table_name].add(button)
+
is all that is needed for that. If we can figure out a way to actually display the icon correctly, then this would work really nicely...
If we can figure out a way to actually display the icon correctly, then this would work really nicely...
I did a lot of digging to find a way to get both the item count and the quality to display visually. As of two weeks ago, I couldn't find anything in the mod API, or in other mods. The GUI debugging tools show that icon+count+quality is displayed using non-exported C++ widgets.
Getting an upstream fix is ideal. But displaying quality is extremely useful by mid-game.
(Since people are interested, let's make this a real issue.)
How quality works. Factorio 2.0 adds an (optional) quality mechanism. If you insert "quality modules" in a machine, it will occasionally produce higher quality outputs. For example, a furnace with quality mods might produce:
The game treats these as five entirely different items. You can't make steel, for example, by mixing 4 common and 1 uncommon iron plate. You can either make common steel using 5 common iron plates, or uncommon steel using 5 uncommon iron plates. (And of course you can put quality mods in your steel furnace, for a random chance of jumping up a tier.)
Supporting quality in Circuit HUD. There are a number of things that would need to happen. Let's break these down into categories. First, the essentials:
Finally, there's an advanced feature possible here:
Support "advanced"/"comparison-based" quality filters, like inserters and splitters do. These filters allow saying things like "show all iron plates of at least uncommon rarity", or "show all items which are rare or better."(See discussion; the Lua API seems to be missing what we need.)I think Cricuit HUD would be a ridiculously useful tool for monitoring high-quality production lines, which involve large numbers of similar items and feedback loops.
If I have time this weekend, I'll look at the mod API and see if I can start roughing out a PR. But if anyone else is interested, please go ahead!