-- Inherited from Vdo_base_object
Vdo_dialog = Vdo_base_object:new_base()
-- Global Locals
local DIALOG_ALIGN_CENTER = 0
local DIALOG_ALIGN_LEFT = 1
local DIALOG_BOX_MIN_WIDTH = 450
local DIALOG_BOX_DEFAULT_TEXT_LINES = 11
local DIALOG_BOX_CONTENT_START_X = 9
local DIALOG_BOX_CONTENT_START_Y = 36
local DIALOG_BOX_SPINNER_SIZE = 80
local DIALOG_BOX_SPINNER_PADDING = 20
local DIALOG_BOX_CONTENT_VERTICAL_SPACING = 10
local DIALOG_BOX_CONTENT_OPTIONS_SPACING = 34
local DIALOG_BOX_CONTENT_OPTIONS_HORIZONTAL_SPACING = 20
local DIALOG_BOX_CONTENT_OPTIONS_HORIZONTAL_OFFSET = 20
local DIALOG_BOX_SCROLLBAR_WIDTH = 18 --width of scrollbar...
local DIALOG_BOX_SCROLLBAR_PADDING = 10 --spacing for scrollbar ...
local DIALOG_BOX_TEXT_MASK_PADDING = 5 --Padding for mask on text...
local DIALOG_BOX_TEXT_UNSELECTED = {R = 218/255, G = 226/255; B = 230/255}
local DIALOG_BOX_TEXT_SELECTED = {R = 0/255, G = 0/255; B = 0/255}
-- Widget types...
DIALOG_WIDGET_TYPE_OPTION = 0
DIALOG_WIDGET_TYPE_TITLE = 1
DIALOG_WIDGET_TYPE_TEXT = 2
DIALOG_WIDGET_TYPE_IMAGE = 3
DIALOG_WIDGET_TYPE_SPINNER = 4
DIALOG_ACTION_NONE = -1
DIALOG_ACTION_SELECT = 0
DIALOG_ACTION_BACK = 1
--init dialog script
function vdo_dialog_init()
end
--cleanup dialog script
function vdo_dialog_cleanup()
end
-------------------------------------------------------------------------------
-- Init Dialog VDO!
-------------------------------------------------------------------------------
function Vdo_dialog:init()
self.header = ""
self.base_content_h = vint_object_find("content", self.handle)
self.previous_content_h = -1
--Configure highlight for
self.highlight = Vdo_button_highlight:new("options_highlight", self.base_content_h)
self.highlight:show_button(CTRL_MENU_BUTTON_A)
local h = vint_object_find("spinner_obj", self.handle)
vint_set_property(h, "visible", false)
vint_set_property(h, "visible", false)
local h = vint_object_find("text_obj", self.handle)
vint_set_property(h, "visible", false)
local h = vint_object_find("options_obj", self.handle)
vint_set_property(h, "visible", false)
local h = vint_object_find("hint_bar_grp", self.handle)
vint_set_property(h, "visible", false)
self.hint_bar = Vdo_hint_bar:new("hint_bar", self.handle)
local h = vint_object_find("dialog_img", self.handle)
vint_set_property(h, "visible", false)
--Store references to shadow...
self.shadow = {}
self.shadow.nw = vint_object_find("shadow_nw", self.handle)
self.shadow.n = vint_object_find("shadow_n", self.handle)
self.shadow.ne = vint_object_find("shadow_ne", self.handle)
self.shadow.e = vint_object_find("shadow_e", self.handle)
self.shadow.se = vint_object_find("shadow_se", self.handle)
self.shadow.s = vint_object_find("shadow_s", self.handle)
self.shadow.sw = vint_object_find("shadow_sw", self.handle)
self.shadow.w = vint_object_find("shadow_w", self.handle)
--Get and store the size of the body text element...
local h = vint_object_find("body_txt", self.handle)
vint_set_property(h, "text_tag", "XXXX")
local width, height = element_get_actual_size(h)
self.text_line_height = height
self.alignment = DIALOG_ALIGN_CENTER
self.current_dialog = -1
end
--[[
Dialogs[handle] = {
base_object = -1,
header = -1,
widgets = {},
widget_count = 0,
}
]]
-------------------------------------------------------------------------------
-- Creates the dialog data....
--
-- @param dialog_data { full of data...}
-- @param do_morph bool (true or false)
-------------------------------------------------------------------------------
function Vdo_dialog:create(dialog_data, do_morph, morph_complete_cb)
if self.morph_playing == true then
self:morph_complete()
end
if do_morph == true then
--Need to clone and delete old dialog content when finished...
--our morph callback will handle any remaining cleanup..
self.previous_content_h = vint_object_clone(self.base_content_h)
--Move content behind new content...
vint_set_property(self.previous_content_h, "depth", 5000)
if morph_complete_cb ~= nil then
self.morph_complete_cb = morph_complete_cb
else
self.morph_complete_cb = nil
end
else
self.morph_complete_cb = nil
end
-- Clear out old dialog cloned objects out of our current dialog...
if self.current_dialog ~= -1 then
local clones = self.current_dialog.widget_clones
for key, val in pairs(clones) do
vint_object_destroy(val)
end
end
--hide all objects that we clone from...
local widget_h = vint_object_find("text_obj", self.base_content_h)
vint_set_property(widget_h, "visible", false)
widget_h = vint_object_find("dialog_img", self.base_content_h)
vint_set_property(widget_h, "visible", false)
widget_h = vint_object_find("spinner_obj", self.base_content_h)
vint_set_property(widget_h, "visible", false)
widget_h = vint_object_find("options_obj", self.base_content_h)
vint_set_property(widget_h, "visible", false)
widget_h = vint_object_find("hint_bar_grp", self.base_content_h)
vint_set_property(widget_h, "visible", false)
--Reset current dialog table...
self.current_dialog = {}
-- handle body...
local title_txt = ""
local options = {}
local option_count = 0
local selected_index = 0
-- Tables and variables used to keep track of cloned objects...
self.current_dialog.widgets = {}
self.current_dialog.widget_clones = {}
self.current_dialog.option_has_clone = false
self.current_dialog.text_has_clone = false
self.current_dialog.image_has_clone = false
self.current_dialog.spinner_has_clone = false
local widgets = {}
local widgets_count = 0
local widgets_width = 0
local widgets_height = DIALOG_BOX_CONTENT_START_Y --Default height for widgets, in case there are none.
--loop through widgets and unpack them into objects......
for i = 0, dialog_data.widgets_count - 1 do
local widget = dialog_data[i]
local widget_type = widget.type
local widget_h -- Handle to current widget...
local do_position_widget = true -- Should we position the widget?
local num_lines = 0
local width = 0 -- Used to position the widgets...
local height = 0 -- Used to position the widgets...
local is_waiting = widget.is_waiting or false
--process odd type widgets first...
if widget_type == DIALOG_WIDGET_TYPE_TITLE then
-- Store title to use later...
title_txt = widget.title
do_position_widget = false
elseif widget_type == DIALOG_WIDGET_TYPE_OPTION then
-- Store options to process later...
options[option_count] = {
has_second_option = widget.has_second_option,
tag_1 = widget.tag_1,
tag_2 = widget.tag_2,
option_id = widget.option_id,
disabled = widget.disabled,
}
--Set current option to be selected if we are...
if widget.selected == true then
selected_index = widget.option_id
end
option_count = option_count + 1
do_position_widget = false
elseif widget_type == DIALOG_WIDGET_TYPE_TEXT then
--Text field for dialog...
local text_tag = widget.text_tag
num_lines = widget.num_lines
if not is_waiting then
if self.current_dialog.text_has_clone == false then
widget_h = vint_object_find("text_obj", self.base_content_h)
self.current_dialog.text_has_clone = true
else
local h = vint_object_find("text_obj", self.base_content_h)
widget_h = vint_object_clone(h)
self:add_clone_to_list(widget_h)
end
local body_txt_h = vint_object_find("body_txt", widget_h)
if num_lines ~= 0 then
vint_set_property(body_txt_h, "text_tag_crc", text_tag)
else
vint_set_property(body_txt_h, "text_tag", text_tag)
end
width, height = element_get_actual_size(body_txt_h)
vint_set_property(widget_h, "visible", true)
else
widget_h = vint_object_find("hint_bar_grp")
local data = {
{CTRL_MENU_BUTTON_B, "CONTROL_CANCEL"},
}
self.hint_bar:set_hints(data)
height = self.text_line_height + 5
vint_set_property(widget_h, "visible", true)
end
elseif widget_type == DIALOG_WIDGET_TYPE_IMAGE then
--Image field for dialog...
local image_name = widget.image_name
if self.current_dialog.image_has_clone == false then
widget_h = vint_object_find("dialog_img", self.base_content_h)
self.current_dialog.image_has_clone = true
else
local h = vint_object_find("dialog_img", self.base_content_h)
widget_h = vint_object_clone(h)
self:add_clone_to_list(widget_h)
end
vint_set_property(widget_h, "visible", true)
vint_set_property(widget_h, "image", image_name)
width, height = element_get_actual_size(widget_h)
elseif widget_type == DIALOG_WIDGET_TYPE_SPINNER then
--Spinner field for dialog...
local spinner_txt = widget.spinner_txt
widget_h = vint_object_find("spinner_obj", self.base_content_h)
vint_set_property(widget_h, "visible", true)
--Set text tag of spinner...
local spinner_txt_h = vint_object_find("spinner_txt", widget_h)
local spinner_txt_width, spinner_txt_height = element_get_actual_size(spinner_txt_h)
local spinner_txt_x, spinner_txt_y = vint_get_property(spinner_txt_h, "anchor")
vint_set_property(spinner_txt_h, "text_tag", spinner_txt)
--Clone and target animation...
local spinner_anim_h = vint_object_find("spinner_anim", self.handle)
vint_set_property(spinner_anim_h, "target_handle", widget_h)
vint_set_property(spinner_anim_h, "is_paused", false)
--get width/height for box...
local spinner_gfx_h = vint_object_find("spinner_gfx_1", self.base_content_h)
width = spinner_txt_width
height = DIALOG_BOX_SPINNER_SIZE
end
if do_position_widget == true then
--store widget data for alignment later...
widgets[widgets_count] = {
h = widget_h,
type = widget_type,
width = width,
height = height,
num_lines = num_lines,
is_waiting = is_waiting,
}
widgets_count = widgets_count + 1
widgets_width = max(widgets_width, width)
end
end
widgets.widgets_count = widgets_count
--Set Title
local title_txt_obj = Vdo_base_object:new("title_txt", self.base_content_h)
title_txt_obj:set_text(title_txt)
local title_width, title_height = title_txt_obj:get_actual_size()
title_width = title_width + 6 --for padding
-- Build options...
-- Position base options
local options_h = vint_object_find("options_obj", self.base_content_h)
local option_h = vint_object_find("option", options_h)
local option_1_width
local option_2_width
local option_1_largest_width = 0
local option_1_with_second_option_largest_width = 0
local option_2_largest_width = 125 -- This is also the default width of the text box... Approximatly 8 characters...
if game_get_platform() == "PC" then
option_2_largest_width = 250 -- Double it on PC so typing directly in it isn't so jarring
end
local x = 0
local y = 0
for i = 0, option_count - 1 do
local current_option_h
local option_is_clone = false
if i == 0 then
current_option_h = option_h
x, y = vint_get_property(current_option_h, "anchor")
else
current_option_h = vint_object_clone(option_h)
y = y + DIALOG_BOX_CONTENT_OPTIONS_SPACING
option_is_clone = true
end
local option_txt_1_h = vint_object_find("option_txt_1", current_option_h)
local option_txt_2_h = vint_object_find("option_txt_2", current_option_h)
local option_2_grp_h = vint_object_find("option_2_grp", current_option_h)
vint_set_property(current_option_h, "anchor", x, y)
--force tags to nothing if no data was sent in...
if options[i].tag_1 == nil then
options[i].tag_1 = ""
end
if options[i].tag_2 == nil then
options[i].tag_2 = ""
end
--Set text tags...
vint_set_property(option_txt_1_h, "text_tag", options[i].tag_1)
vint_set_property(option_txt_2_h, "text_tag", options[i].tag_2)
--Find largest elements for alignment later...
option_1_width = element_get_actual_size(option_txt_1_h)
option_2_width = element_get_actual_size(option_txt_2_h)
option_1_largest_width = max(option_1_width, option_1_largest_width)
--Do we show the second option?
if options[i].has_second_option == true then
vint_set_property(option_2_grp_h, "visible", true)
--Now calculate the width of the largest first option with a second option...
option_1_with_second_option_largest_width = max(option_1_width, option_1_with_second_option_largest_width)
option_2_largest_width = max(option_2_width, option_2_largest_width)
else
vint_set_property(option_2_grp_h, "visible", false)
end
options[i].h = current_option_h
--Add to widget clone table if option is clone...
if option_is_clone then
self.current_dialog.widget_clones[i] = current_option_h
end
end
-- Align second options...
-- todo align right side of box to width of the shit...
for i = 0, option_count - 1 do
local current_option_h = options[i].h
local option_txt_1_h = vint_object_find("option_txt_1", current_option_h)
local option_2_grp_h = vint_object_find("option_2_grp", current_option_h)
local x, y = vint_get_property(option_txt_1_h, "anchor")
vint_set_property(option_2_grp_h, "anchor", x + option_1_with_second_option_largest_width + DIALOG_BOX_CONTENT_OPTIONS_HORIZONTAL_SPACING, y)
--Set size of option2 box, + 10 to account for padding...
local option_2_box_width = option_2_largest_width + 10
--Resize background
local box_bg_h = vint_object_find("option_box_bg", current_option_h)
local box_bg_width, box_bg_height = element_get_actual_size(box_bg_h)
element_set_actual_size(box_bg_h, option_2_box_width - 4, box_bg_height) --its the box width.. - 4 is the width of the size so we subtract it...
--Resize the north and south sides of the box...
local box_n_h = vint_object_find("option_box_n", current_option_h)
local box_s_h = vint_object_find("option_box_s", current_option_h)
local box_width, box_height = element_get_actual_size(box_n_h)
element_set_actual_size(box_n_h, option_2_box_width, box_height)
element_set_actual_size(box_s_h, option_2_box_width, box_height)
--Reposition right side of box...
local box_e_h = vint_object_find("option_box_e", current_option_h)
local box_x, box_y = vint_get_property(box_e_h, "anchor")
vint_set_property(box_e_h, "anchor", option_2_box_width, box_y)
end
local options_height
--the largest width is either the first option or the combined width of first option or second option...
local options_largest_width = max(option_1_largest_width, option_1_with_second_option_largest_width + option_2_largest_width + 5)
--calculate the total width of the options...
local options_width = x + options_largest_width + DIALOG_BOX_CONTENT_OPTIONS_HORIZONTAL_SPACING + DIALOG_BOX_CONTENT_OPTIONS_HORIZONTAL_OFFSET
-- Show options if we have them...
if option_count > 0 then
vint_set_property(options_h, "visible", true)
--Use options height...
options_height = y + DIALOG_BOX_CONTENT_OPTIONS_SPACING - 12
else
vint_set_property(options_h, "visible", true)
options_height = 0
end
--Store off option data for later...
options.option_count = option_count
self.current_dialog.options = options
--Highlight current option...
self:highlight_option(selected_index, true)
--Pre-calculate size of box...
local dialog_box_width = max(DIALOG_BOX_MIN_WIDTH, options_width)
dialog_box_width = max(widgets_width, dialog_box_width)
dialog_box_width = max(title_width, dialog_box_width)
local dialog_box_height = 0 -- This will be calculated as we place everything...
--Position widgets...
local widget_x = DIALOG_BOX_CONTENT_START_X
local widget_y = DIALOG_BOX_CONTENT_START_Y
for i = 0, widgets_count - 1 do
local widget_h = widgets[i].h
local widget_type = widgets[i].type
local width = widgets[i].width
local height = widgets[i].height
local num_lines = widgets[i].num_lines
local is_waiting = widgets[i].is_waiting
if widget_type == DIALOG_WIDGET_TYPE_TEXT then
if not is_waiting then
local body_txt_h = vint_object_find("body_txt", widget_h)
if body_txt_h ~= 0 then
local scroll_h = vint_object_find("scroll", widget_h)
local wrap_width = dialog_box_width - DIALOG_BOX_SCROLLBAR_WIDTH - DIALOG_BOX_SCROLLBAR_PADDING
vint_set_property(body_txt_h, "wrap_width", wrap_width)
vint_set_property(body_txt_h, "word_wrap", true)
--Move scrollbar to edge of text box...
local scroll_x, scroll_y = vint_get_property(scroll_h, "anchor")
local body_txt_x, body_txt_y = vint_get_property(body_txt_h, "anchor")
vint_set_property(scroll_h, "anchor", body_txt_x + wrap_width + DIALOG_BOX_SCROLLBAR_PADDING, scroll_y)
--Replace width and height values...
local text_width, text_height = element_get_actual_size(body_txt_h)
if num_lines == 0 then
num_lines = DIALOG_BOX_DEFAULT_TEXT_LINES
end
height = self.text_line_height * num_lines
--This means we don't need to scroll...
--[[ DAD - 8/17/11 - Removed the scroll bar.. keeping this here for SR4 though
if text_height <= height then
height = text_height
vint_set_property(scroll_h, "visible", false)
else
vint_set_property(scroll_h, "visible", true)
end
]]--
-- This section can be removed if the above is uncommented
if text_height <= height then
height = text_height
end
vint_set_property(scroll_h, "visible", false)
-- End section
--adjust size of mask
local mask_h = vint_object_find("mask", widget_h)
element_set_actual_size(mask_h, dialog_box_width, height + DIALOG_BOX_TEXT_MASK_PADDING)
end
else
height = self.text_line_height + 5
end
elseif widget_type == DIALOG_WIDGET_TYPE_SPINNER then
--Set text tag of spinner...
local spinner_txt_h = vint_object_find("spinner_txt", widget_h)
local wrap_width = dialog_box_width - DIALOG_BOX_SPINNER_SIZE - DIALOG_BOX_SPINNER_PADDING
vint_set_property(spinner_txt_h, "wrap_width", wrap_width)
vint_set_property(spinner_txt_h, "word_wrap", true)
---if the text is wrapping more than 3 lines we have problems and need to reposition the spinner...
local y = 0
local spinner_txt_width, spinner_txt_height = element_get_actual_size(spinner_txt_h)
local spinner_internal_grp_h = vint_object_find("spinner_internal_grp", widget_h)
if spinner_txt_height > DIALOG_BOX_SPINNER_SIZE then
y = (spinner_txt_height - DIALOG_BOX_SPINNER_SIZE) * .5
end
vint_set_property(spinner_internal_grp_h, "anchor", 0, y)
height = height + (y * 2)
end
--position widget...
vint_set_property(widget_h, "anchor", widget_x, widget_y)
--Calculate position for next widget...
widget_y = widget_y + height + DIALOG_BOX_CONTENT_VERTICAL_SPACING
--Store off widget height (last positioned object plus the height of it...
widgets_height = widget_y
end
-- Position base options
local options_h = vint_object_find("options_obj", self.base_content_h)
vint_set_property(options_h, "anchor", widget_x, widgets_height)
dialog_box_height = widgets_height - DIALOG_BOX_CONTENT_START_Y + options_height
self.current_dialog.widgets = widgets
--Change to new size...
self:morph_size(dialog_box_width, dialog_box_height, do_morph)
end
function Vdo_dialog:morph_size(width, height, do_morph)
if do_morph then
local morph_anim_h = vint_object_find("morph_anim", self.handle)
local morph_twn_h = vint_object_find("morph_twn",morph_anim_h)
local content_alpha_twn_h = vint_object_find("content_alpha_twn", morph_anim_h)
local new_content_alpha_twn_h = vint_object_find("new_content_alpha_twn", morph_anim_h)
--Use the following data to convert pixels to widths...
local fill_h = vint_object_find("fill", self.handle)
local start_width, start_height = vint_get_property(fill_h, "unscaled_size")
vint_set_property(morph_twn_h, "start_value", self.width/start_width, self.height/start_height)
vint_set_property(morph_twn_h, "end_value", width/start_width, height/start_height)
local callback_string = self:package_tween_callback("size_update")
vint_set_property(morph_twn_h, "per_frame_event", callback_string)
local callback_string = self:package_tween_callback("morph_complete")
vint_set_property(morph_twn_h, "end_event", callback_string)
--set targets for fade in and out tweens...
vint_set_property(content_alpha_twn_h, "target_handle", self.previous_content_h) --target the new content (this tween fades out)
vint_set_property(new_content_alpha_twn_h, "target_handle", self.content_h) --target the new content (this tween fades in)
lua_play_anim(morph_anim_h)
self.morph_playing = true
else
self:set_size(width, height)
end
end
function Vdo_dialog:size_update()
local fill_h = vint_object_find("fill", self.handle)
local width, height = element_get_actual_size(fill_h)
self:set_size(width, height)
end
function Vdo_dialog:set_size(width, height)
local border_h = vint_object_find("border", self.handle)
local fill_h = vint_object_find("fill", self.handle)
local dialog_clip_h = vint_object_find("dialog_clip", self.handle)
--Calculate background element sizes...
local border_width = width + 10
local border_height = height + 38
local clip_width = width + 1
local clip_height = height + 33
--[[
relative sizes...
fill: 420, 217
border: 430, 255
dialog_clip: 420, 250
]]
--Adjust background elements...
element_set_actual_size(fill_h, width, height)
element_set_actual_size(border_h, border_width, border_height)
element_set_actual_size(dialog_clip_h, clip_width, clip_height)
self:set_shadow(width, height)
--Set highlight width on option bar...
self.highlight:set_width(width)
--Align box to screen...
local box_h = vint_object_find("dialog_grp", self.handle)
if self.alignment == DIALOG_ALIGN_CENTER then
--get parent scale... of object.(this isn't standard... but handles us if we are scaled by a parent document...
local scale_x, scale_y
if vint_is_std_res() then
scale_x = 0.667
scale_y = 0.667
vint_set_property(self.handle, "scale", scale_x, scale_y)
else
scale_x = 1.0
scale_y = 1.0
vint_set_property(self.handle, "scale", scale_x, scale_y)
end
--Set box to center... screen center, minus half the box width...
local x = (((Screen_center_x / scale_x)- (border_width/2)) )
local y = (((Screen_center_y / scale_y) - (border_height/2)) )
vint_set_property(box_h, "anchor", x, y)
elseif self.alignment == DIALOG_ALIGN_LEFT then
end
self.width = width
self.height = height
end
function Vdo_dialog:morph_complete()
self.morph_playing = false
--destroy content...
if self.previous_content_h ~= -1 then
vint_object_destroy(self.previous_content_h)
self.previous_content_h = -1
end
if self.morph_complete_cb ~= nil then
self.morph_complete_cb()
end
end
-------------------------------------------------------------------------------
-- Sets the shadow for the dialog box...
-- @param width Width of shadow...
-- @param height Height of shadow...
-------------------------------------------------------------------------------
function Vdo_dialog:set_shadow(width, height)
-- Find shadow objects
local nw_h = self.shadow.nw
local n_h = self.shadow.n
local ne_h = self.shadow.ne
local e_h = self.shadow.e
local se_h = self.shadow.se
local s_h = self.shadow.s
local sw_h = self.shadow.sw
local w_h = self.shadow.w
--Top left Corner
local start_x = 0
local start_y = 0
--Padding if width/height are a bit less than the outside of the box...
local pad_width = 10
local pad_height = 38
width = width + pad_width
height = height + pad_height
local sides_width, sides_height = element_get_actual_size(n_h)
--N
element_set_actual_size(n_h, width, sides_height)
--NE
vint_set_property(ne_h, "anchor", width + start_x, start_y)
--E
vint_set_property(e_h, "anchor", width + start_x, start_y)
element_set_actual_size(e_h, height, sides_height)
--SE
vint_set_property(se_h, "anchor", width + start_x, height + start_y)
--S
vint_set_property(s_h, "anchor", start_x, height + start_y)
element_set_actual_size(s_h, width, -sides_height)
--SW
vint_set_property(sw_h, "anchor", start_x, height + start_y)
--element_set_actual_size(sw_h, width, sides_height)
--W
element_set_actual_size(w_h, height, sides_height)
end
-------------------------------------------------------------------------------
-- Moves highlight bar to index...
-------------------------------------------------------------------------------
function Vdo_dialog:add_clone_to_list(clone_h)
local clone_count = #self.current_dialog.widget_clones
self.current_dialog.widget_clones[clone_count] = clone_h
end
-------------------------------------------------------------------------------
-- Moves highlight bar to index...
-------------------------------------------------------------------------------
function Vdo_dialog:highlight_option(idx, skip)
local options = self.current_dialog.options
local selected_option = options.selected_option
if skip == nil or skip == false then
if options.selected_option ~= nil then
dialog_option_end_kbd_input(self.dialog_handle, options.selected_option)
end
end
dialog_option_accept_kbd_input(self.dialog_handle, idx)
--Check to make sure index isn't out of range...
if idx > options.option_count - 1 then
idx = options.option_count - 1
end
if options[idx] ~= nil and options[idx].disabled ~= nil and options[idx].disabled then
return
end
--hide highlight if there are no options...
if options.option_count == 0 then
vint_set_property(self.highlight.handle, "visible", false)
return
else
vint_set_property(self.highlight.handle, "visible", true)
end
--move highlight bar...
local x, y = vint_get_property(options[idx].h, "anchor")
vint_set_property(self.highlight.handle, "anchor", x, y)
--Color options...
for i = 0, options.option_count - 1 do
local option_h = options[i].h
local option_1_h = vint_object_find("option_txt_1", option_h)
if idx == i then
vint_set_property(option_1_h, "tint", DIALOG_BOX_TEXT_SELECTED.R, DIALOG_BOX_TEXT_SELECTED.G, DIALOG_BOX_TEXT_SELECTED.B)
else
vint_set_property(option_1_h, "tint", DIALOG_BOX_TEXT_UNSELECTED.R, DIALOG_BOX_TEXT_UNSELECTED.G, DIALOG_BOX_TEXT_UNSELECTED.B)
end
end
options.selected_option = idx
end
-------------------------------------------------------------------------------
--
-------------------------------------------------------------------------------
function Vdo_dialog:set_dialog_callback()
end
-------------------------------------------------------------------------------
-- opens dialog...
-------------------------------------------------------------------------------
function Vdo_dialog:open(do_trans_in)
self:show()
-- stop fade out
local anim_h = vint_object_find("fade_out_anim", self.handle)
self:close_finished()
if do_trans_in == true then
-- start fade in
anim_h = vint_object_find("fade_in_anim", self.handle)
vint_set_property(anim_h, "target_handle", self.handle)
lua_play_anim(anim_h)
else
vint_set_property(self.handle, "alpha", 1.0)
end
end
-------------------------------------------------------------------------------
-- Closes dialog...
-------------------------------------------------------------------------------
function Vdo_dialog:close()
--start fade out...
local anim_out_h = vint_object_find("fade_out_anim", self.handle)
local tween_h = vint_object_find("new_tween2_1", anim_out_h)
vint_set_property(anim_out_h, "target_handle", self.handle)
local callback_string = self:package_tween_callback("close_finished")
vint_set_property(tween_h, "end_event", callback_string)
lua_play_anim(anim_out_h)
end
function Vdo_dialog:close_finished()
dialog_close_finished()
end
-------------------------------------------------------------------------------
-- Show
-------------------------------------------------------------------------------
function Vdo_dialog:show()
vint_set_property(self.handle, "visible", true)
end
-------------------------------------------------------------------------------
-- Hide
-------------------------------------------------------------------------------
function Vdo_dialog:hide()
vint_set_property(self.handle, "visible", false)
end
function Vdo_dialog:set_color(main_bg_color, highlight_color)
local border_h = vint_object_find("border", self.handle)
vint_set_property(border_h, "tint", main_bg_color.R, main_bg_color.G, main_bg_color.B)
self.highlight:set_highlight_color(highlight_color)
local spinner_gfx_h = vint_object_find("spinner_gfx_1", self.base_content_h)
vint_set_property(spinner_gfx_h, "tint", main_bg_color.R, main_bg_color.G, main_bg_color.B)
end
-------------------------------------------------------------------------------
-- Navigation...
-------------------------------------------------------------------------------
function Vdo_dialog:nav(direction)
local options = self.current_dialog.options
local selected_option = options.selected_option
local option_count = options.option_count
if option_count <= 0 then
return false
end
if selected_option == nil then
options.selected_option = 0
selected_option = 0
end
local new_option = selected_option + direction
if new_option < 0 then
new_option = options.option_count - 1
elseif new_option == options.option_count then
--exceeded limit go
new_option = 0
end
if options[new_option] ~= nil and options[new_option].disabled ~= nil and options[new_option].disabled then -- if the option is disabled, try again.
if direction == 0 then
direction = direction + 1
end
new_option = new_option + direction
if new_option < 0 then
new_option = options.option_count - 1
elseif new_option == options.option_count then
--exceeded limit go
new_option = 0
end
end
dialog_box_set_current_option(self.dialog_handle, new_option)
self:highlight_option(new_option)
return true
end
-- Add mouse inputs to the options
function Vdo_dialog:add_mouse_inputs(callback_action, callback_nav, input_tracker, priority)
local options = self.current_dialog.options
if (options == nil) or (callback_action == nil) or (callback_nav == nil) then
return
end
-- Default priority value to 200
priority = priority or 200
-- Clear out old wide hitboxes
if self.wide_hitboxes ~= nil then
for idx, wide_hitbox in pairs(self.wide_hitboxes) do
vint_object_destroy(wide_hitbox.handle)
end
end
self.wide_hitboxes = {}
local highlight_w, highlight_h = vint_get_property(self.highlight.handle, "screen_size")
local options_obj_handle = vint_object_find("options_obj", self.handle)
for i = 0, options.option_count - 1 do
if options[i].disabled == nil or options[i].disabled == false then
-- X = 0
-- Width = highlight.width
-- Y = option[i].y
-- Height = option[i].height
local option_x, option_y = vint_get_property(options[i].h, "anchor")
local option_w, option_h = vint_get_property(options[i].h, "screen_size")
local wide_index = #self.wide_hitboxes + 1
local wide_name = "wide_hitbox"..wide_index
local wide_handle = vint_object_create(wide_name, "bitmap", options_obj_handle)
self.wide_hitboxes[wide_index] = {}
self.wide_hitboxes[wide_index].handle = wide_handle
self.wide_hitboxes[wide_index].idx = i
vint_set_property(wide_handle, "auto_offset", "w")
vint_set_property(wide_handle, "visible", false)
vint_set_property(wide_handle, "depth", 100)
vint_set_property(wide_handle, "screen_size", highlight_w - 8, option_h + 2)
vint_set_property(wide_handle, "anchor", 0, option_y + 1)
vint_set_property(wide_handle, "mouse_depth", -5000)
options[i].wide_handle = wide_handle
input_tracker:add_mouse_input("mouse_click", callback_action, priority, options[i].wide_handle)
input_tracker:add_mouse_input("mouse_move", callback_nav, priority, options[i].wide_handle)
end
end
local bg_h = vint_object_find("background", self.handle)
vint_set_property(bg_h, "mouse_depth", -4000)
input_tracker:add_mouse_input("mouse_move", callback_nav, priority, bg_h)
input_tracker:add_mouse_input("mouse_click", callback_action, priority, bg_h)
--loop through and see if we have any hintbars to add inputs to...
local widgets_count = self.current_dialog.widgets.widgets_count
for i = 0, widgets_count - 1 do
local widget = self.current_dialog.widgets[i]
local widget_type = widget.type
if widget_type == DIALOG_WIDGET_TYPE_TEXT then
local is_waiting = widget.is_waiting
if is_waiting then
self.hint_bar:add_mouse_inputs("dialog", input_tracker)
self.hint_bar:override_mouse_depths(-5000)
end
end
end
end
-- Search through the options and match the index
function Vdo_dialog:get_option_index(handle)
local options = self.current_dialog.options
for i = 0, options.option_count - 1 do
if options[i].wide_handle == handle then
return i
end
end
return -1
end
-------------------------------------------------------------------------------
-- Selects current option, sends data to callback...
-------------------------------------------------------------------------------
function Vdo_dialog:select()
local options = self.current_dialog.options
local selected_option = options.selected_option
if selected_option ~= nil and options[selected_option] ~= nil and options[selected_option].disabled ~= nil and options[selected_option].disabled then
return
end
if options[selected_option] ~= nil and options[selected_option].has_second_option then
return
end
return dialog_box_set_result(self.dialog_handle, selected_option, DIALOG_ACTION_SELECT)
end
-------------------------------------------------------------------------------
-- Returns the currently selected option
-------------------------------------------------------------------------------
function Vdo_dialog:get_selected()
return self.current_dialog.options.selected_option
end
-------------------------------------------------------------------------------
-- Returns whether the option has a second option
-------------------------------------------------------------------------------
function Vdo_dialog:has_second_option(option_idx)
if self.current_dialog == nil or self.current_dialog.options == nil or self.current_dialog.options[option_idx] == nil then
return false
end
return self.current_dialog.options[option_idx].has_second_option
end
-------------------------------------------------------------------------------
-- Fires back event...
-------------------------------------------------------------------------------
function Vdo_dialog:back()
local options = self.current_dialog.options
local selected_option = options.selected_option
return dialog_box_set_result(self.dialog_handle, selected_option, DIALOG_ACTION_BACK)
end
-------------------------------------------------------------------------------
-- cleanup Dialog VDO!
-------------------------------------------------------------------------------
function Vdo_dialog:cleanup()
end
-- Given a set of options, return several width metric about them
--
-- options: Set of dialog options to work with. Usually self.current_dialog.options, unless called from create()
--
-- return 1: the maximum width of all single options that has no second option
-- return 2: the maximum width of all single options that does have a second option
-- return 3: the maximum width of all second options
function Vdo_dialog:get_option_widths(options)
local option_count = options.option_count
local solo_option_1_max_width = 0
local paired_option_1_max_width = 0
local paired_option_2_max_width = 125 -- This is also the default width of the text box... Approximatly 8 characters...
if game_get_platform() == "PC" then
paired_option_2_max_width = 250 -- Double it on PC so typing directly in it isn't so jarring
end
for i = 0, option_count - 1 do
local option_1_text_h = vint_object_find("option_txt_1", options[i].h)
local option_1_width = element_get_actual_size(option_1_text_h)
if options[i].has_second_option == true then
local option_2_text_h = vint_object_find("option_txt_2", options[i].h)
local option_2_width = element_get_actual_size(option_2_text_h)
paired_option_1_max_width = max(paired_option_1_max_width, option_1_width)
paired_option_2_max_width = max(paired_option_2_max_width, option_2_width)
else
solo_option_1_max_width = max(solo_option_1_max_width, option_1_width)
end
end
return solo_option_1_max_width, paired_option_1_max_width, paired_option_2_max_width
end
-- Given a set of options, return the necessary width of the dialog box to contain them
--
-- options: Set of dialog options to work with. Usually self.current_dialog.options, unless called from create()
--
-- return 1: the necessary width of the dialog box
function Vdo_dialog:get_dialog_width(options, widgets)
local options_obj_h = vint_object_find("options_obj", self.base_content_h)
local base_option_obj_h = vint_object_find("option", options_obj_h)
local x, y = vint_get_property(base_option_obj_h, "anchor")
local solo_option_1_max_width, paired_option_1_max_width, paired_option_2_max_width = self:get_option_widths(options)
local options_largest_width = max(solo_option_1_max_width, paired_option_1_max_width + paired_option_2_max_width + 5)
local options_width = x + options_largest_width + DIALOG_BOX_CONTENT_OPTIONS_HORIZONTAL_SPACING + DIALOG_BOX_CONTENT_OPTIONS_HORIZONTAL_OFFSET
local widgets_width = self:get_widgets_width(widgets)
-- SMH: I'm sure leaving these lines commented out is "wrong", but in the only case this
-- function is being used, it's necessary to prevent lua from failing to find the title
-- text obj and then try to index null when I try to get its size.
-- local title_txt_obj = vint_object_find("title_txt", self.base_content_h)
-- local title_width, title_height = title_txt_obj:get_actual_size()
-- title_width = title_width + 6 --for padding
local dialog_width = max(DIALOG_BOX_MIN_WIDTH, options_width)
dialog_width = max(dialog_width, widgets_width)
-- dialog_width = max(dialog_width, title_width)
return dialog_width
end
-- Given a set of options, return their cumulative height
--
-- options: Set of dialog options to work with. Usually self.current_dialog.options, unless called from create()
--
function Vdo_dialog:get_options_height(options)
local option_count = options.option_count
if option_count <= 0 then
return 0
end
local x, y = vint_get_property(options[option_count-1].h, "anchor")
return y + DIALOG_BOX_CONTENT_OPTIONS_SPACING - 12
end
-- Given a set of options, return their cumulative height
--
-- return 1: the maximum height of widgets
function Vdo_dialog:get_widgets_height(widgets)
local widgets_count = widgets.widgets_count
local max_widget_y = DIALOG_BOX_CONTENT_START_Y
for i = 0, widgets_count - 1 do
local height = widgets[i].height
local width = widgets[i].width
local x, y
if widgets[i].type == DIALOG_WIDGET_TYPE_TEXT then
--height = self.text_line_height * widgets[i].num_lines
end
x, y = vint_get_property(widgets[i].h, "anchor")
max_widget_y = max(max_widget_y, y + height + DIALOG_BOX_CONTENT_VERTICAL_SPACING)
end
return max_widget_y - DIALOG_BOX_CONTENT_START_Y
end
-- Given a set of options, return their cumulative width
--
-- return 1: the maximum height of widgets
function Vdo_dialog:get_widgets_width(widgets)
local widgets_count = #widgets
local widgets_width = 0
for i = 0, widgets_count - 1 do
widgets_width = max(widgets_width, widgets[i].width)
end
return widgets_width
end
function Vdo_dialog:resize_options(options)
local option_count = options.option_count
local solo_option_1_max_width, paired_option_1_max_width, paired_option_2_max_width = self:get_option_widths(options)
-- Align second options...
-- todo align right side of box to width of the shit...
for i = 0, option_count - 1 do
local current_option_h = options[i].h
local option_txt_1_h = vint_object_find("option_txt_1", current_option_h)
local option_2_grp_h = vint_object_find("option_2_grp", current_option_h)
local x, y = vint_get_property(option_txt_1_h, "anchor")
vint_set_property(option_2_grp_h, "anchor", x + paired_option_1_max_width + DIALOG_BOX_CONTENT_OPTIONS_HORIZONTAL_SPACING, y)
--Set size of option2 box, + 10 to account for padding...
local option_2_box_width = paired_option_2_max_width + 10
--Resize background
local box_bg_h = vint_object_find("option_box_bg", current_option_h)
local box_bg_width, box_bg_height = element_get_actual_size(box_bg_h)
element_set_actual_size(box_bg_h, option_2_box_width - 4, box_bg_height) --its the box width.. - 4 is the width of the size so we subtract it...
--Resize the north and south sides of the box...
local box_n_h = vint_object_find("option_box_n", current_option_h)
local box_s_h = vint_object_find("option_box_s", current_option_h)
local box_width, box_height = element_get_actual_size(box_n_h)
element_set_actual_size(box_n_h, option_2_box_width, box_height)
element_set_actual_size(box_s_h, option_2_box_width, box_height)
--Reposition right side of box...
local box_e_h = vint_object_find("option_box_e", current_option_h)
local box_x, box_y = vint_get_property(box_e_h, "anchor")
vint_set_property(box_e_h, "anchor", option_2_box_width, box_y)
end
end
-- Given a set of options and widgets, return the necessary height of a dialog box to contain them
--
-- return 1: The necessary height of the dialog box
function Vdo_dialog:get_dialog_height(options, widgets)
return self:get_options_height(options) + self:get_widgets_height(widgets)
end
function Vdo_dialog:set_option_text(option_idx, new_text, do_morph, morph_complete_cb)
if self.morph_playing == true then
self:morph_complete()
end
local options = self.current_dialog.options
local option_1_text_h = vint_object_find("option_txt_1", options[option_idx].h)
if options[option_idx].has_second_option == true then
options[option_idx].tag_2 = new_text
local option_2_text_h = vint_object_find("option_txt_2", options[option_idx].h)
vint_set_property(option_2_text_h, "text_tag", options[option_idx].tag_2)
else
options[option_idx].tag_1 = new_text
local option_1_text_h = vint_object_find("option_txt_1", options[option_idx].h)
vint_set_property(option_1_text_h, "text_tag", options[option_idx].tag_1)
end
self:resize_options(options)
local dialog_box_width = self:get_dialog_width(options, self.current_dialog.widgets)
local dialog_box_height = self:get_dialog_height(options, self.current_dialog.widgets)
if self.width ~= dialog_box_width or self.height ~= dialog_box_height then
if do_morph == true then
--Need to clone and delete old dialog content when finished...
--our morph callback will handle any remaining cleanup..
self.previous_content_h = vint_object_clone(self.base_content_h)
--Move content behind new content...
vint_set_property(self.previous_content_h, "depth", 5000)
if morph_complete_cb ~= nil then
self.morph_complete_cb = morph_complete_cb
else
self.morph_complete_cb = nil
end
else
self.morph_complete_cb = nil
end
--Change to new size...
self:morph_size(dialog_box_width, dialog_box_height, do_morph)
end
end