Mutators: fully functional GUI

This commit is contained in:
bi 2018-05-18 19:51:40 +03:00
parent 21f61c9360
commit f3e6e0daa4
5 changed files with 289 additions and 27 deletions

View file

@ -114,35 +114,58 @@ local function is_compatible(mutator, other_mutator)
end end
-- Creates 'compatibility' entry for the mutator, checks compatibility of given mutator with all other mutators. -- Creates 'compatibility' entry for the mutator, checks compatibility of given mutator with all other mutators.
-- 'compatibility.mostly_compatible' is 'true' when mutator is not specifically set to be incompatible with -- 'compatibility.is_mostly_compatible' is 'true' when mutator is not specifically set to be incompatible with
-- all other mutators. All the incompatible mutators will be added to 'compatibility.except'. And vice versa, -- all other mutators. All the incompatible mutators will be added to 'compatibility.except'. And vice versa,
-- if 'mostly_compatible' is 'false', all the compatible mutators will be added to 'except'. -- if 'is_mostly_compatible' is 'false', all the compatible mutators will be added to 'except'.
local function update_compatibility(mutator) local function update_compatibility(mutator)
-- Create default 'compatibility' entry -- Create default 'compatibility' entry
local config = mutator:get_config() local config = mutator:get_config()
config.compatibility = {} config.compatibility = {}
local compatibility = config.compatibility local compatibility = config.compatibility
compatibility.mostly_compatible = not config.incompatible_with_all
-- Compatibility with other mods
compatibility.is_mostly_compatible = not config.incompatible_with_all
compatibility.except = {} compatibility.except = {}
local mostly_compatible = compatibility.mostly_compatible local is_mostly_compatible = compatibility.is_mostly_compatible
local except = compatibility.except local except = compatibility.except
for _, other_mutator in ipairs(_MUTATORS) do for _, other_mutator in ipairs(_MUTATORS) do
local other_config = other_mutator:get_config() local other_config = other_mutator:get_config()
local other_mostly_compatible = other_config.compatibility.mostly_compatible local other_mostly_compatible = other_config.compatibility.is_mostly_compatible
local other_except = other_config.compatibility.except local other_except = other_config.compatibility.except
if is_compatible(mutator, other_mutator) then if is_compatible(mutator, other_mutator) then
if not mostly_compatible then except[other_mutator] = true end if not is_mostly_compatible then except[other_mutator] = true end
if not other_mostly_compatible then other_except[mutator] = true end if not other_mostly_compatible then other_except[mutator] = true end
else else
if mostly_compatible then except[other_mutator] = true end if is_mostly_compatible then except[other_mutator] = true end
if other_mostly_compatible then other_except[mutator] = true end if other_mostly_compatible then other_except[mutator] = true end
end end
end end
-- Compatibility with current difficulty (This part works only for V1. Will see what to do with V2 later.)
compatibility.compatible_difficulties = {
easy = false,
normal = false,
hard = false,
harder = false,
hardest = false,
survival_hard = false,
survival_harder = false,
survival_hardest = false,
}
local compatible_difficulties = compatibility.compatible_difficulties
local compatible_difficulties_number = 0
for _, difficulty_key in ipairs(config.difficulty_levels) do
if type(compatible_difficulties[difficulty_key]) ~= "nil" then
compatible_difficulties[difficulty_key] = true
compatible_difficulties_number = compatible_difficulties_number + 1
end
end
compatibility.compatible_difficulties_number = compatible_difficulties_number
end end
function vmf.temp_show_mutator_compatibility() function vmf.temp_show_mutator_compatibility()
@ -153,9 +176,9 @@ function vmf.temp_show_mutator_compatibility()
for _, mutator in ipairs(_MUTATORS) do for _, mutator in ipairs(_MUTATORS) do
local compatibility = mutator:get_config().compatibility local compatibility = mutator:get_config().compatibility
print(mutator:get_readable_name() .. (compatibility.mostly_compatible and "[+]" or "[-]") .. ":") print(mutator:get_readable_name() .. (compatibility.is_mostly_compatible and "[+]" or "[-]") .. ":")
local ident = compatibility.mostly_compatible and " - " or " + " local ident = compatibility.is_mostly_compatible and " - " or " + "
for other_mutator in pairs(compatibility.except) do for other_mutator in pairs(compatibility.except) do
print(ident .. other_mutator:get_readable_name()) print(ident .. other_mutator:get_readable_name())

View file

@ -1,17 +1,19 @@
local vmf = get_mod("VMF") local vmf = get_mod("VMF")
local _DEFINITIONS = dofile("scripts/mods/vmf/modules/ui/mutators/mutators_gui_definitions")
local _MUTATORS = vmf.mutators local _MUTATORS = vmf.mutators
local _SELECTED_DIFFICULTY_KEY
local _DEFINITIONS = dofile("scripts/mods/vmf/modules/ui/mutators/mutators_gui_definitions")
local _UI_SCENEGRAPH local _UI_SCENEGRAPH
local _MUTATOR_LIST_WIDGETS = {} local _MUTATOR_LIST_WIDGETS = {}
local _PARTY_BUTTON_WIDGET local _PARTY_BUTTON_WIDGET
local _OTHER_WIDGETS = {} local _OTHER_WIDGETS = {}
local _ORIGINAL_VALUES = {} local _ORIGINAL_VALUES = {} -- @TODO: get rid of it?
local _MUTATOR_LIST_IS_VISIBLE local _MUTATOR_LIST_IS_VISIBLE
local _CURRENT_PAGE_NUMBER local _CURRENT_PAGE_NUMBER
@ -88,6 +90,162 @@ local function change_map_view_look(map_view, is_vmf_look)
end end
end end
--@TODO: clean up, and probably do direct change instead of return
local function calculate_tooltip_offset (widget_content, widget_style, ui_renderer)
--local cursor_offset_bottom = widget_style.cursor_offset_bottom
if ui_renderer.input_service then
local cursor_position = UIInverseScaleVectorToResolution(ui_renderer.input_service.get(ui_renderer.input_service, "cursor"))
if cursor_position then
local text = widget_content.tooltip_text
local max_width = widget_style.max_width
local font, font_size = UIFontByResolution(widget_style)
local font_name = font[3]
local font_material = font[1]
local _, font_min, font_max = UIGetFontHeight(ui_renderer.gui, font_name, font_size)
local texts = UIRenderer.word_wrap(ui_renderer, text, font_material, font_size, max_width)
local num_texts = #texts
local full_font_height = (font_max + math.abs(font_min)) * RESOLUTION_LOOKUP.inv_scale
local tooltip_height = full_font_height * num_texts
--if((cursor_offset_bottom[2] / UIResolutionScale() + tooltip_height) > cursor_position[2]) then
local cursor_offset_top = {}
cursor_offset_top[1] = widget_style.cursor_offset_top[1]
cursor_offset_top[2] = widget_style.cursor_offset_top[2] - (tooltip_height * UIResolutionScale())
return cursor_offset_top
--else
-- return cursor_offset_bottom
--end
end
end
--return cursor_offset_bottom
end
local function offset_function_callback(ui_scenegraph_, style, content, ui_renderer)
local mutator = content.mutator
local can_be_enabled = true
local mutator_compatibility_config = mutator:get_config().compatibility
local is_mostly_compatible = mutator_compatibility_config.is_mostly_compatible
local except = mutator_compatibility_config.except
for _, other_mutator in ipairs(_MUTATORS) do
if other_mutator:is_enabled() and other_mutator ~= mutator then
can_be_enabled = can_be_enabled and (is_mostly_compatible and not except[other_mutator] or
not is_mostly_compatible and except[other_mutator])
end
end
can_be_enabled = can_be_enabled and mutator_compatibility_config.compatible_difficulties[_SELECTED_DIFFICULTY_KEY]
content.can_be_enabled = can_be_enabled
-- Enable/disable mutator
if content.highlight_hotspot.on_release then
if mutator:is_enabled() then
vmf.set_mutator_state(mutator, false, false)
elseif can_be_enabled then
vmf.set_mutator_state(mutator, true, false)
end
end
-- Tooltip
-- Yup, a boilerplate code, kinda. I made it to divide tooltip code part, and to update it only for selected mod.
if content.highlight_hotspot.is_hover then
local tooltip_text = content.description
local incompatible_mods = {}
local conflicting_mods = {}
if next(except) then
tooltip_text = tooltip_text .. "\n\n" ..
(is_mostly_compatible and "-- INCOMPATIBLE WITH [MUTATORS] --\n" or
"-- COMPATIBLE ONLY WITH [MUTATORS] --\n") --@TODO: localize
for other_mutator, _ in pairs(except) do
table.insert(incompatible_mods, " * " .. other_mutator:get_readable_name())
end
tooltip_text = tooltip_text .. table.concat(incompatible_mods, "\n")
end
local difficulties = {}
local compatible_difficulties_number = mutator_compatibility_config.compatible_difficulties_number
if compatible_difficulties_number < 8 then
tooltip_text = tooltip_text .. "\n\n" ..
(compatible_difficulties_number > 4 and "-- INCOMPATIBLE WITH [DIFFICULTIES] --\n" or
"-- COMPATIBLE ONLY WITH [DIFFICULTIES] --\n") --@TODO: localize
for difficulty_key, is_compatible in pairs(mutator_compatibility_config.compatible_difficulties) do
if compatible_difficulties_number > 4 and not is_compatible
or not (compatible_difficulties_number > 4) and is_compatible then
table.insert(difficulties, " * " .. vmf:localize(difficulty_key))
end
end
tooltip_text = tooltip_text .. table.concat(difficulties, "\n")
end
for _, other_mutator in ipairs(_MUTATORS) do
if other_mutator:is_enabled() and other_mutator ~= mutator then
if not (is_mostly_compatible and not except[other_mutator] or
not is_mostly_compatible and except[other_mutator]) then
table.insert(conflicting_mods, " * " .. other_mutator:get_readable_name() .. " (mutator)")
end
end
end
if not can_be_enabled then
--tooltip_text = tooltip_text .. "\n\n" .. "--[X]-- CONFLICTS --[X]--\n"
tooltip_text = tooltip_text .. "\n\n" .. "-- CONFLICTS --\n"
if #conflicting_mods > 0 then
tooltip_text = tooltip_text .. table.concat(conflicting_mods, "\n") .. "\n"
end
if not mutator_compatibility_config.compatible_difficulties[_SELECTED_DIFFICULTY_KEY] then
tooltip_text = tooltip_text .. " * " .. vmf:localize(_SELECTED_DIFFICULTY_KEY) .. " (difficulty)" .. "\n"
end
--tooltip_text = tooltip_text .. "--[X]--\n"
end
content.tooltip_text = tooltip_text
style.tooltip_text.cursor_offset = calculate_tooltip_offset(content, style.tooltip_text, ui_renderer)
end
-- VISUAL
local is_enabled = content.mutator:is_enabled()
style.text.text_color = content.can_be_enabled and (is_enabled and content.text_color_enabled or
content.text_color_disabled) or content.text_color_inactive
content.checkbox_texture = is_enabled and content.checkbox_checked_texture or
content.checkbox_unchecked_texture
end
local function initialize_mutators_ui(map_view) local function initialize_mutators_ui(map_view)
@ -97,8 +255,9 @@ local function initialize_mutators_ui(map_view)
-- Creating mutator list widgets and calculating total pages number -- Creating mutator list widgets and calculating total pages number
for i, mutator in ipairs(_MUTATORS) do for i, mutator in ipairs(_MUTATORS) do
local offset = ((i - 1) % 8) + 1 local offset = ((i - 1) % 8) + 1
_MUTATOR_LIST_WIDGETS[i] = UIWidget.init(_DEFINITIONS.create_mutator_widget(mutator)) _MUTATOR_LIST_WIDGETS[i] = UIWidget.init(_DEFINITIONS.create_mutator_widget(mutator, offset_function_callback))
_MUTATOR_LIST_WIDGETS[i].offset = {0, -32 * offset, 0} _MUTATOR_LIST_WIDGETS[i].offset = {0, -32 * offset, 0}
_MUTATOR_LIST_WIDGETS[i].content.mutator = mutator
end end
_CURRENT_PAGE_NUMBER = 1 _CURRENT_PAGE_NUMBER = 1
_TOTAL_PAGES_NUMBER = math.floor(#_MUTATORS / 8) + ((#_MUTATORS % 8 > 0) and 1 or 0) _TOTAL_PAGES_NUMBER = math.floor(#_MUTATORS / 8) + ((#_MUTATORS % 8 > 0) and 1 or 0)
@ -190,7 +349,12 @@ end)
vmf:hook("MapView.update", function (func, self, dt, t) vmf:hook("MapView.update", function (func, self, dt, t)
func(self, dt, t) func(self, dt, t)
if self.menu_active and _IS_MUTATORS_GUI_INITIALIZED then if self.menu_active and _IS_MUTATORS_GUI_INITIALIZED then
local difficulty_data = self.selected_level_index and self:get_difficulty_data(self.selected_level_index)
local difficulty_layout = difficulty_data and difficulty_data[self.selected_difficulty_stepper_index]
_SELECTED_DIFFICULTY_KEY = difficulty_layout and difficulty_layout.key
update_mutators_ui(self, dt) update_mutators_ui(self, dt)
end end
end) end)

View file

@ -121,7 +121,7 @@ local party_button_widget_defenition = UIWidgets.create_octagon_button(
) )
local function create_mutator_widget(mutator) local function create_mutator_widget(mutator, offset_function_callback)
return { return {
scenegraph_id = "sg_mutators_list_start", scenegraph_id = "sg_mutators_list_start",
element = { element = {
@ -129,39 +129,113 @@ local function create_mutator_widget(mutator)
-- { -- {
-- pass_type = "rect", -- pass_type = "rect",
-- style_id = "mutators_list_background", -- style_id = "mutators_list_background"
-- --texture_id = "mutators_list_background_texture_id"
-- }, -- },
{
pass_type = "hotspot",
content_id = "highlight_hotspot"
},
{
pass_type = "local_offset",
offset_function = offset_function_callback
},
{
pass_type = "texture",
style_id = "hover_texture",
texture_id = "hover_texture",
content_check_function = function (content)
return content.can_be_enabled and content.highlight_hotspot.is_hover
end
},
{ {
pass_type = "text", pass_type = "text",
style_id = "text", style_id = "text",
text_id = "text" text_id = "text"
}, },
{
pass_type = "texture",
style_id = "checkbox_style",
texture_id = "checkbox_texture"
},
{
pass_type = "tooltip_text",
text_id = "tooltip_text",
style_id = "tooltip_text",
content_check_function = function (content)
return content.highlight_hotspot.is_hover
end
},
} }
}, },
content = { content = {
mutators_list_background_texture_id = "map_view_mutators_area", mutator = nil, -- is added after creation (i can't add mutator here now, becuase UIWidget.init() clones tables)
mutator = mutator,
text = mutator:get_readable_name(), text = mutator:get_readable_name(),
--text = "bIbIbI(rus)",
description = mutator:get_description() or "No description provided.", --@TODO: localize
can_be_enabled = false,
mutators_list_background_texture_id = "map_view_mutators_area",
highlight_hotspot = {},
tooltip_text = "",
--hover_texture = "map_setting_bg_fade",
hover_texture = "playerlist_hover",
checkbox_texture = "checkbox_unchecked",
checkbox_unchecked_texture = "checkbox_unchecked", -- unsused
checkbox_checked_texture = "checkbox_checked", -- unsused
text_color_disabled = Colors.get_color_table_with_alpha("white", 255),
text_color_enabled = Colors.get_color_table_with_alpha("cheeseburger", 255),
text_color_inactive = Colors.get_color_table_with_alpha("slate_gray", 255),
}, },
style = { style = {
mutators_list_background = { -- mutators_list_background = {
--scenegraph_id = "sg_mutators_list_start", -- --scenegraph_id = "sg_mutators_list_start",
color = {math.random(255), math.random(255), math.random(255), 255}, -- size = {370, 32},
size = {370, 32} -- color = {math.random(255), math.random(255), math.random(255), 255}
}, -- },
text = { text = {
offset = {0, -2, 2}, offset = {10, -2, 2},
font_size = 24, font_size = 24,
font_type = "hell_shark", font_type = "hell_shark",
dynamic_font = true, dynamic_font = true,
text_color = Colors.get_color_table_with_alpha("white", 255) text_color = Colors.get_color_table_with_alpha("white", 255)
}, },
hover_texture = {
size = {370, 32},
offset = {0, 0, 1}
},
checkbox_style = {
size = {20, 20},
offset = {340, 6, 2},
color = {255, 255, 255, 255}
},
tooltip_text = {
font_type = "hell_shark",
font_size = 18,
horizontal_alignment = "left",
vertical_alignment = "top",
cursor_side = "right",
max_width = 425,
cursor_offset = {27, 27},
cursor_offset_bottom = {27, 27},
cursor_offset_top = {27, -27}
},
size = {370, 32},
} }
} }
end end

View file

@ -110,6 +110,7 @@ vmf.initialize_mod_state(onslaught)
local one_hit_one_kill = new_mod("one_hit_one_kill") local one_hit_one_kill = new_mod("one_hit_one_kill")
mod_data = {} mod_data = {}
mod_data.name = "One Hit One Kill" mod_data.name = "One Hit One Kill"
mod_data.description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tincidunt placerat nulla eget pharetra. Vivamus consequat tristique vestibulum. Nullam vitae feugiat arcu, non porta ante. Phasellus consequat facilisis quam quis dignissim"
mod_data.is_mutator = true mod_data.is_mutator = true
mod_data.mutator_settings = { mod_data.mutator_settings = {
--title = "One Hit One Kill", --title = "One Hit One Kill",

View file

@ -1,5 +1,5 @@
VT1 = false VT1 = true
--move vmf to local var
return { return {
init = function(object) init = function(object)