SCALE_FONT_STORE_GANG_LIST = 0.8
Store_gang_doc_handle = -1
-- Hint bar and store header vdo's.
local Store_logo1
local Store_logo2
local Not_popup_grp
local Reward_image
-- We used this as a reference to the current submenu we are building.
local Store_gang_building_menu = {}
-- Keeps track of the text tag crc for the category the player chose.
local Store_gang_category_label_crc = 0
-- Slot id (0-3) that is currently the "front" character. Entering interface starts at 0.
local Store_gang_current_slot = 0
local Store_gang_slot_info = {}
-- Similar to character slots, but for vehicles. Entering interface starts at 0.
local Store_gang_current_vehicle_slot = 0
local Store_gang_loaded_from_crib = false
local Hint_bar_mouse_input_tracker
local Game_platform
local Store_gang_input_allowed = false
---------------------------------------------------------------------------
-- Initialize Gang Store (Customization)
---------------------------------------------------------------------------
function store_gang_init()
Store_common_current_highlight_color = COLOR_STORE_REWARDS_PRIMARY
Game_platform = game_get_platform()
Store_gang_loaded_from_crib = store_common_crib_is_loaded()
Store_gang_doc_handle = vint_document_find("store_gang")
-- Set up some callbacks for the common store script
Store_common_allow_input_cb = store_gang_allow_input
Store_common_populate_list_cb = store_gang_populate_list
Store_common_exit_cb = store_gang_exit
-- Subscribe to the button presses we need, Input_tracker is created in store_common.lua
Input_tracker:subscribe(false)
--Setup Button Hints
local hint_data = {
{CTRL_MENU_BUTTON_B, "MENU_BACK"},
}
Store_common_hint_bar:set_hints(hint_data)
Store_common_hint_bar:set_visible(true)
if game_is_active_input_gamepad() then
local hint_rotate_data = {
{CTRL_BUTTON_RS, "CONTROL_ROTATE"},
}
Store_common_rotate_hint:set_hints(hint_rotate_data)
Store_common_rotate_hint:set_visible(true)
end
character_enable_mouse_drag(true)
-- Initialize mouse input trackers and create mouse tracker for the hint bar
if Game_platform == "PC" then
Mouse_input_tracker:subscribe(false)
Hint_bar_mouse_input_tracker = Vdo_input_tracker:new()
Store_common_hint_bar:add_mouse_inputs("store_gang", Hint_bar_mouse_input_tracker)
Hint_bar_mouse_input_tracker:subscribe(true)
end
-- Set Store Header colors
Store_header:set_color(COLOR_STORE_REWARDS_PRIMARY, COLOR_STORE_REWARDS_SECONDARY, COLOR_STORE_REWARDS_TERTIARY)
Store_header:set_visible(true)
Store_header:push_title(nil, "GANG_CUSTOMIZATION")
Active_list:set_highlight_color(COLOR_STORE_REWARDS_PRIMARY, COLOR_STORE_REWARDS_SECONDARY)
-- Everything that is not in the popup so we can fade it when the popup is active
Not_popup_grp = Vdo_base_object:new("not_popup_grp", 0, Store_common_doc_handle)
-- Setup purchase popup
Store_common_popup:set_visible(false)
Store_common_popup:set_color(COLOR_STORE_REWARDS_PRIMARY, COLOR_STORE_REWARDS_SECONDARY, COLOR_STORE_REWARDS_TERTIARY)
Store_common_popup:set_size(STORE_COMMON_LIST_SIZE, (LIST_BUTTON_HEIGHT * 5) + (LIST_BUTTON_SPACE * 5))
-- Setup Color grid
Store_common_color_grid:set_visible(false)
if Store_gang_loaded_from_crib then
-- crib specific stuff
local store_main_grp = Vdo_base_object:new("store_main_grp", 0, Store_common_doc_handle)
store_main_grp:set_anchor(0,0)
bg_saints_set_type(BG_TYPE_CENTER,true,1280)
bg_saints_set_background(false)
-- animate in ui for gang customization (shared by all stores)
local store_gang_in_anim = Vdo_anim_object:new("store_common_in_anim", 0, Store_common_doc_handle)
local end_event_twn = Vdo_tween_object:new("end_event_twn", store_gang_in_anim.handle, Store_common_doc_handle)
end_event_twn:set_end_event("store_unlock_controls")
local twn_h = vint_object_find("store_megalist_grp_twn",store_gang_in_anim.handle,Store_common_doc_handle)
vint_set_property(twn_h,"start_event","store_gang_bg_anim_done")
bg_saints_show(true)
vint_apply_start_values(store_gang_in_anim.handle)
store_gang_in_anim:play(0)
end
-- Pass the table data to the megalist vdo.
Menu_data = Store_gang_top_menu
-- Pass the table data to the megalist vdo.
store_gang_populate_list(Menu_data, 1)
-- acquire information about the 4 gang character slots
store_gang_slot_populate()
vint_dataitem_add_subscription("store_gang_current_object_is_loaded", "update", "store_gang_load_status_update")
end
-- Cleanup function called on document unload.
--
function store_gang_cleanup()
if Store_gang_loaded_from_crib == false then
bg_saints_show(false)
-- Nuke all button subscriptions
Input_tracker:subscribe(false)
store_gang_enable_mouse(false)
end
character_enable_mouse_drag(false)
-- Some things need to be cleaned up right away when a store doc is unloading, particular disabled inputs which have
-- callbacks to the script that is unloading.
store_common_cleanup_current_store()
end
function store_lock_controls()
Input_tracker:subscribe(false)
store_gang_enable_mouse(false)
end
function store_unlock_controls()
Input_tracker:subscribe(true)
store_gang_enable_mouse(true)
end
function store_gang_slot_populate()
Store_gang_slot_info = {}
vint_dataresponder_request("store_gang_slot_dr", "store_gang_slot_add", 0)
end
-- Called by data responder to add a new slot to the table
--
function store_gang_slot_add(is_random, display_name_crc)
local menu_idx = #Store_gang_slot_info + 1
local new_item = {
id = menu_idx - 1,
type = TYPE_BUTTON,
is_random = is_random,
label_crc = display_name_crc,
}
Store_gang_slot_info[menu_idx] = new_item
end
function store_gang_slot_menu_enter()
-- We want left/right movement to rotate characters instead of moving sliders in this interface
Input_tracker:remove_input("nav_left")
Input_tracker:remove_input("nav_right")
Input_tracker:add_input("nav_left", "store_common_nav_up", 50)
Input_tracker:add_input("nav_right", "store_common_nav_down", 50)
-- update labels (gang selections may have been updated in a submenu).
for i = 1, #Menu_data do
local values
values = {[0] = i, [1] = Store_gang_slot_info[i].label_crc}
Menu_data[i].label = vint_insert_values_in_string("GANG_CUST_SLOT", values)
end
local index = Active_list:get_selection()
store_gang_populate_list(Menu_data, index)
-- check for random
store_gang_handle_random()
--store_gang_show_question_marks(true)
end
function store_gang_rotate_characters()
-- We want left/right movement to rotate characters instead of moving sliders in this interface
Input_tracker:remove_input("nav_left")
Input_tracker:remove_input("nav_right")
Input_tracker:add_input("nav_left", "store_common_nav_left", 50)
Input_tracker:add_input("nav_right", "store_common_nav_right", 50)
-- hide random text
local crib_random_grp = Vdo_base_object:new("crib_random_grp", 0, Store_common_doc_handle)
crib_random_grp:set_visible(false)
end
function store_gang_slot_menu_leave()
store_gang_rotate_characters()
--store_gang_show_question_marks(false)
end
-- Player is navigating to a new gang character slot. We need to call C to rotate the players and set new slot
--
function store_gang_slot_nav(menu_data)
vint_dataresponder_post("store_gang_character_dr", "Set_slot", menu_data.id)
Store_gang_current_slot = menu_data.id
store_gang_handle_random()
end
function store_gang_handle_random()
-- if slot is random than display text for which category
local crib_random_grp = Vdo_base_object:new("crib_random_grp", 0, Store_common_doc_handle)
local crib_random_text = Vdo_base_object:new("crib_random_txt", 0, Store_common_doc_handle)
local crib_random_anim_out = Vdo_anim_object:new("crib_random_anim_out", 0, Store_common_doc_handle)
local end_event_twn = Vdo_tween_object:new("random_out_end_event", crib_random_anim_out.handle)
end_event_twn:set_end_event("store_gang_random_anim_complete")
crib_random_anim_out:play(0)
end
function store_gang_random_anim_complete()
local crib_random_anim_in = Vdo_anim_object:new("crib_random_anim_in", 0, Store_common_doc_handle)
local crib_random_grp = Vdo_base_object:new("crib_random_grp", 0, Store_common_doc_handle)
local crib_random_text = Vdo_base_object:new("crib_random_txt", 0, Store_common_doc_handle)
if Store_gang_slot_info[Store_gang_current_slot + 1].is_random == true then
local values, tag
values = {[0] = "GANG_CUST_RANDOM", [1] = Store_gang_slot_info[Store_gang_current_slot + 1].label_crc}
tag = vint_insert_values_in_string("{0} {1:text_tag_crc}", values)
crib_random_text:set_text(tag)
crib_random_grp:set_visible(true)
crib_random_anim_in:play(0)
else
crib_random_grp:set_visible(false)
end
end
-- Player has chosen a gang character slot, and now we need to populate the submenu with the gang categories.
--
function store_gang_category_populate(menu_data)
-- change our input for left/right back to default
store_gang_rotate_characters()
Store_gang_building_menu = menu_data.sub_menu
Store_gang_building_menu.start_index = 1
vint_dataresponder_request("store_gang_category_dr", "store_gang_category_add", 0)
end
-- Called by data responder to add a new category to the menu.
--
function store_gang_category_add(id, display_name_crc, is_current)
local menu_idx = #Store_gang_building_menu + 1
local new_item = {
id = id,
type = TYPE_BUTTON,
label = nil,
label_crc = display_name_crc,
on_sub_menu_fill = store_gang_character_populate,
}
Store_gang_building_menu[menu_idx] = new_item
if is_current == true then
Store_gang_building_menu.start_index = menu_idx
end
end
-- The player has chosen a category; now we need to find the available characters in that category.
--
-- menu_data: standard table with the contents of the menu entry chosen.
--
function store_gang_character_populate(menu_data)
Store_gang_category_label_crc = menu_data.label_crc
Store_gang_building_menu = menu_data.sub_menu
Store_gang_building_menu.start_index = 1
vint_dataresponder_request("store_gang_character_dr", "store_gang_character_add", 0, menu_data.id)
store_gang_show_question_marks(true)
store_gang_character_nav(Store_gang_building_menu[Store_gang_building_menu.start_index])
end
-- When leaving the character style selection menu, we're going to stop showing question marks
--
function store_gang_character_back(menu_data)
store_gang_show_question_marks(false)
end
-- Called by data responder to add a new character to the menu.
--
function store_gang_character_add(id, is_current, is_random)
local menu_idx = #Store_gang_building_menu + 1
local menu_label
local insert_values = { [0] = Store_gang_category_label_crc, [1] = menu_idx }
if is_random then
menu_label = "GANG_CUST_RANDOM"
else
menu_label = vint_insert_values_in_string("{0:text_tag_crc} {1}", insert_values)
end
local new_item = {
type = TYPE_BUTTON,
id = id,
label = menu_label,
label_crc = nil,
--is_locked = is_locked,
on_nav = store_gang_character_nav,
on_select = store_gang_character_update,
on_cancel = store_gang_character_revert,
on_back = store_gang_character_back,
is_random = is_random
}
Store_gang_building_menu[menu_idx] = new_item
if is_current == true then
Store_gang_building_menu.start_index = menu_idx
end
end
-- Called when the player navigates the character list, and we spawn in the characters to show.
--
function store_gang_character_nav(menu_data)
vint_dataresponder_post("store_gang_character_dr", "Load", menu_data.id)
store_gang_slot_populate()
end
-- Called when the player hits accept to keep the character
--
function store_gang_character_update(menu_data)
vint_dataresponder_post("store_gang_character_dr", "Update_char", menu_data.id)
-- update our gang character slot info table
store_gang_slot_populate()
-- go back up 2 menus
store_common_back_menu()
store_common_back_menu()
end
-- Called when the player hits cancel to revert the character
--
function store_gang_character_revert(menu_data)
vint_dataresponder_post("store_gang_character_dr", "Revert_char", menu_data.id)
store_gang_slot_populate()
end
-- Player has chosen to see gang sign menu, and now we need to populate the submenu.
--
function store_gang_sign_populate(menu_data)
Store_gang_building_menu = menu_data.sub_menu
vint_dataresponder_request("store_gang_sign_dr", "store_gang_sign_add", 0)
--[[local hint_rotate_data = {
{CTRL_BUTTON_RS, "STORE_ZOOM"},
}
Store_common_rotate_hint:set_hints(hint_rotate_data)]]--
Store_common_rotate_hint:set_visible(false)
character_enable_mouse_drag(false)
end
-- Called by data responder to add a new gang sign to the menu.
--
function store_gang_sign_add(sign_type, display_name, is_current)
local menu_idx = #Store_gang_building_menu + 1
local new_item = {
id = menu_idx - 1,
type = TYPE_BUTTON,
label = display_name,
label_crc = nil,
on_nav = store_gang_sign_nav,
on_select = store_gang_sign_select,
on_cancel = store_gang_sign_revert,
on_back = store_gang_sign_on_back
}
Store_gang_building_menu[menu_idx] = new_item
if is_current == true then
Store_gang_building_menu.start_index = menu_idx
end
end
-- Called when navigating over a gang sign
--
function store_gang_sign_nav(menu_data)
gang_customization_select_gang_sign(0, menu_data.id)
end
-- Called when selecting a gang sign
--
function store_gang_sign_select(menu_data)
gang_customization_confirm_gang_sign(menu_data.id)
store_common_back_menu()
end
-- Called when reverting from a gang sign
--
function store_gang_sign_revert(menu_data)
gang_customization_revert_gang_sign()
end
-- Called when navigating to a different vehicle slot
--
function store_gang_vehicle_slot_nav(menu_data)
vint_dataresponder_post("store_gang_vehicle_dr", "Set_slot", menu_data.id)
Store_gang_current_vehicle_slot = menu_data.id
end
-- Called when we need to request the available vehicles list.
--
function store_gang_vehicle_populate(menu_data)
Store_gang_building_menu = menu_data.sub_menu
vint_dataresponder_request("store_gang_vehicle_dr", "store_gang_vehicle_add", 0, menu_data.id)
end
-- Called by data responder to add a new vehicle to the menu.
--
function store_gang_vehicle_add(name, is_current)
local menu_idx = #Store_gang_building_menu + 1
local new_item = {
type = TYPE_BUTTON,
id = menu_idx - 1,
label = name,
label_crc = nil,
--is_locked = is_locked,
on_nav = store_gang_vehicle_nav,
on_select = store_gang_vehicle_update,
on_cancel = store_gang_vehicle_revert,
}
Store_gang_building_menu[menu_idx] = new_item
if is_current == true then
Store_gang_building_menu.start_index = menu_idx
end
end
-- Called when the player navigates the vehicle list, and we spawn in the vehicle to show.
--
function store_gang_vehicle_nav(menu_data)
gang_customization_select_vehicle(menu_data.id, Store_gang_current_vehicle_slot)
end
-- Called when the player hits accept to keep the vehicle
--
function store_gang_vehicle_update(menu_data)
gang_customization_confirm_vehicle(Store_gang_current_vehicle_slot)
store_common_back_menu()
end
-- Called when the player hits cancel to revert the vehicle
--
function store_gang_vehicle_revert(menu_data)
gang_customization_revert_vehicle(Store_gang_current_vehicle_slot)
end
-- Called when player requests exiting store.
--
function store_gang_exit()
-- no confirmation needed if we're just going back to the crib menu
if Store_gang_loaded_from_crib then
game_UI_audio_play("UI_Main_Menu_Nav_Back")
-- lock input during animation
store_lock_controls()
-- make background so player is covered up
bg_saints_set_background(false)
local back_out_anim = Vdo_anim_object:new("store_crib_out_anim", 0, Store_common_doc_handle)
local back_out_end_twn = Vdo_tween_object:new("common_anchor_out_twn", back_out_anim.handle)
back_out_end_twn:set_end_event("store_gang_crib_exit")
back_out_anim:play(0)
-- notify C code to reset camera (end customization camera_mode, customization near clip)
store_gang_begin_exit()
else
Store_common_popup:populate_list(Yes_no_choices, 1, STORE_COMMON_LIST_SIZE, 2)
Store_common_popup:set_title("MENU_TITLE_WARNING")
Store_common_popup:set_text("STORE_EXIT_WARNING_BODY")
Store_common_popup:nav_enable(true, "store_gang_exit_final", "store_gang_popup_nav")
Not_popup_grp:set_alpha(.5)
store_gang_enable_mouse(false)
end
end
function store_gang_crib_exit()
pop_screen()
end
-- Called when player has responded to store exit confirmation dialog.
--
-- event: input response from the player
--
function store_gang_exit_final(event)
Store_common_popup:nav_enable(false, nil, nil)
-- The user hit the B button and is exiting
-- This is redundant to selecting "No" in the list
if event == "back" then
game_UI_audio_play("UI_Main_Menu_Nav_Back")
Not_popup_grp:set_alpha(1)
store_gang_enable_mouse(true)
return
end
game_UI_audio_play("UI_Main_Menu_Select")
-- Did we select yes? This assumes yes is the first item
if Store_common_popup:get_selected_data() ~= 1 then
Not_popup_grp:set_alpha(1)
store_gang_enable_mouse(true)
return
end
Not_popup_grp:set_alpha(0)
-- exit the interface
pop_screen()
end
-- Populate the active megalist menu, and hide the previous menu
--
-- list_data: this table contains the data to populate the megalist
-- current_index: the current index in the menu that's selected
--
function store_gang_populate_list(list_data, current_index)
Active_list:draw_items(list_data, current_index, STORE_COMMON_LIST_SIZE, 10, SCALE_FONT_STORE_GANG_LIST)
Active_list:set_visible(true)
if Game_platform == "PC" then
Mouse_input_tracker:remove_all()
Active_list:set_store("store_gang")
Active_list:add_mouse_inputs("store_common", Mouse_input_tracker)
Mouse_input_tracker:subscribe(true)
end
end
-- Clears the price and respect values from the store header.
--
function store_gang_header_revert(menu_data)
Store_header:set_price(nil)
Store_header:set_respect(nil)
end
-- Handles navigation of any popups
function store_gang_popup_nav(event, value)
if event == "mouse_move" then
vint_set_mouse_cursor("")
end
if event == "nav_up" then
Store_common_popup.list:move_cursor(-1)
elseif event == "nav_down" then
Store_common_popup.list:move_cursor(1)
elseif event == "mouse_move" then
-- value contains the target_handle in this case
local new_index = Store_common_popup.list:get_button_index(value)
if new_index ~= 0 then
Store_common_popup.list:set_selection(new_index)
Store_common_popup.list:move_cursor(0, true)
end
else
--do nothing
end
end
function store_gang_style_menu_select(menu_data)
local slot_menu = {
on_enter = store_gang_slot_menu_enter,
on_back = store_gang_slot_menu_leave,
[1] = { type = TYPE_BUTTON, id = 0, on_nav = store_gang_slot_nav, on_sub_menu_fill = store_gang_category_populate, on_back = store_gang_slot_menu_leave},
[2] = { type = TYPE_BUTTON, id = 1, on_nav = store_gang_slot_nav, on_sub_menu_fill = store_gang_category_populate, on_back = store_gang_slot_menu_leave},
[3] = { type = TYPE_BUTTON, id = 2, on_nav = store_gang_slot_nav, on_sub_menu_fill = store_gang_category_populate, on_back = store_gang_slot_menu_leave},
[4] = { type = TYPE_BUTTON, id = 3, on_nav = store_gang_slot_nav, on_sub_menu_fill = store_gang_category_populate, on_back = store_gang_slot_menu_leave}
}
menu_data.sub_menu = slot_menu
-- set starting choice according to current slot
menu_data.sub_menu.start_index = Store_gang_current_slot + 1
character_enable_mouse_drag(true)
end
function store_gang_vehicle_slot_menu_enter(menu_data)
vint_dataresponder_post("store_gang_vehicle_dr", "Set_slot", 0)
Store_gang_current_vehicle_slot = 0
Store_common_rotate_hint:set_visible(false)
character_enable_mouse_drag(false)
end
function store_gang_vehicle_slot_menu_leave(menu_data)
vint_dataresponder_post("store_gang_vehicle_dr", "Set_slot", -1)
if game_is_active_input_gamepad() then
Store_common_rotate_hint:set_visible(true)
end
character_enable_mouse_drag(true)
end
-- While vehicles or gang characters are loading and visible on the screen, we need to set the background property to false.
--
function store_gang_load_status_update(di_h)
--[[
is_loaded = is the current preview target loaded?
]]--
local is_loaded = vint_dataitem_get(di_h)
-- make character show if a character is loaded...
bg_saints_set_background(is_loaded)
Store_gang_input_allowed = is_loaded
end
function store_gang_allow_input()
return Store_gang_input_allowed
end
function store_gang_bg_anim_done(twn_h, event_name)
vint_set_property(twn_h,"start_event",nil)
store_gang_bg_covered()
store_common_bg_anim_complete()
--debug_print("vint","GANG BG DONE")
end
function store_gang_sign_on_back()
character_enable_mouse_drag(true)
if game_is_active_input_gamepad() then
local hint_rotate_data = {
{CTRL_BUTTON_RS, "CONTROL_ROTATE"},
}
Store_common_rotate_hint:set_hints(hint_rotate_data)
Store_common_rotate_hint:set_visible(true)
else
Store_common_rotate_hint:set_visible(false)
end
end
Store_gang_gang_menu = {
[1] = { label = "GANG_CUST_GANG_STYLE_OPT", type = TYPE_BUTTON, on_sub_menu_fill = store_gang_style_menu_select },
[2] = { label = "GANG_CUST_GANG_SIGN_OPT", type = TYPE_BUTTON, on_sub_menu_fill = store_gang_sign_populate }
}
Store_gang_vehicle_menu = {
[1] = { label = "GANG_CUST_SLOT_1", type = TYPE_BUTTON, id = 0, on_nav = store_gang_vehicle_slot_nav, on_sub_menu_fill = store_gang_vehicle_populate, },
[2] = { label = "GANG_CUST_SLOT_2", type = TYPE_BUTTON, id = 1, on_nav = store_gang_vehicle_slot_nav, on_sub_menu_fill = store_gang_vehicle_populate, },
[3] = { label = "GANG_CUST_SLOT_3", type = TYPE_BUTTON, id = 2, on_nav = store_gang_vehicle_slot_nav, on_sub_menu_fill = store_gang_vehicle_populate, },
}
Store_gang_top_menu = {
[1] = { label = "GANG_CUST_GANG_TITLE", type = TYPE_BUTTON, sub_menu = Store_gang_gang_menu, on_nav = store_gang_vehicle_slot_menu_leave },
[2] = { label = "GANG_CUST_VEHICLE_TITLE", type = TYPE_BUTTON, sub_menu = Store_gang_vehicle_menu, on_nav = store_gang_vehicle_slot_menu_enter }
}
-- =====================================
-- Mouse Specific Functions
-- =====================================
function store_gang_enable_mouse(enable)
if Game_platform == "PC" and enable ~= nil then
if Mouse_input_tracker ~= 0 then
Mouse_input_tracker:subscribe(enable)
end
if Hint_bar_mouse_input_tracker ~= nil then
Hint_bar_mouse_input_tracker:subscribe(enable)
end
end
end
function store_gang_mouse_click(event, target_handle)
local hint_index = Store_common_hint_bar:get_hint_index(target_handle)
if hint_index ~= 0 then
store_common_button_b()
end
end
function store_gang_mouse_move(event, target_handle)
vint_set_mouse_cursor("")
-- Reset all highlights
Store_common_hint_bar:set_highlight(0)
-- Check if the mouse is over the hint bar buttons
local hint_index = Store_common_hint_bar:get_hint_index(target_handle)
if hint_index ~= 0 then
Store_common_hint_bar:set_highlight(hint_index, Store_common_current_highlight_color)
return
end
-- Check if the mouse is over a button on the mega list
local old_index = Active_list:get_selection()
local new_index = Active_list:get_button_index(target_handle)
if new_index ~= 0 and new_index ~= old_index then
Active_list:set_selection(new_index)
Active_list:move_cursor(0, true)
-- If the item has a callback for navigation, do it (such as putting clothes on)
local data_item = Active_list:return_selected_data()
if data_item.on_nav ~= nil then
data_item.on_nav(data_item)
end
return
end
end
function store_gang_mouse_scroll(event, target_handle, mouse_x, mouse_y, scroll_lines)
end
function store_gang_mouse_drag(event, target_handle, mouse_x, mouse_y)
end
function store_gang_mouse_drag_release(event, target_handle, mouse_x, mouse_y)
end