./vdo_grid_list.lua

  1. Vdo_grid_list_tween_done = true 
  2. local Input_tracker 
  3. local Grid_mouse_input_tracker 
  4. local Scrollbar_input_tracker 
  5.  
  6. local GRID_BUTTON_SPACING	= 3 
  7. local GRID_BUTTON_SIZE 		= 150 
  8. local MOVE_UP					= -2 
  9. local MOVE_DOWN				= 2 
  10. local MOVE_LEFT				= -1 
  11. local MOVE_RIGHT				= 1 
  12.  
  13. local SCALE_STD_RES_GRID_BUTTON = .67 --.9 
  14. local ANCHOR_SCROLLBAR_BUFFER = 6 
  15. local ANCHOR_TITLE_SPACE = 32 
  16. local SIZE_GRID_BUTTON = 59 
  17.  
  18. function vdo_grid_list_init() 
  19. end 
  20.  
  21. function vdo_grid_list_cleanup() 
  22. end 
  23.  
  24. -- Inherited from Vdo_base_object 
  25. Vdo_grid_list = Vdo_base_object:new_base() 
  26.  
  27. function Vdo_grid_list:init() 
  28. 	-- Hide the initial button 
  29. 	vint_set_property(vint_object_find("grid_base"), "visible", false) 
  30. 	vint_set_property(vint_object_find("grid_layered"), "visible", false) 
  31. 	vint_set_property(vint_object_find("grid_check"), "visible", false) 
  32. 	vint_set_property(vint_object_find("grid_canceled"), "visible", false) 
  33. 	vint_set_property(vint_object_find("grid_anchor"), "visible", false) 
  34. 	vint_set_property(vint_object_find("grid_title"), "visible", false) 
  35.  
  36. 	self.scrollbar = Vdo_scrollbar:new("grid_scrollbar", self.handle, self.doc_handle) 
  37. 	self.group = Vdo_base_object:new("grid_group", self.handle, self.doc_handle) 
  38. 	self.bg = Vdo_base_object:new("grid_list_bg",self.handle, self.doc_handle) 
  39. 	self.highlight_name = Vdo_base_object:new("grid_highlight_name", self.handle, self.doc_handle) 
  40. 	self.input_enabled = false 
  41. 	 
  42. 	self.scrollbar:set_visible(false)	 
  43. 	 
  44. 	Vdo_grid_list_tween_done = true 
  45. 	 
  46. 	local highlight = Vdo_hint_button:new( "grid_hint_button", self.handle, self.doc_handle) 
  47. 	highlight:set_button(CTRL_MENU_BUTTON_A) 
  48. 	if game_is_active_input_gamepad() == false then 
  49. 		highlight:set_visible(false) 
  50. 	end 
  51. 		 
  52. 	local list_anim = Vdo_anim_object:new("grid_group_anim", self.handle, self.doc_handle) 
  53. 	list_anim:stop() 
  54. 	 
  55. 	Input_tracker = Vdo_input_tracker:new() 
  56. 	 
  57. 	--clone title and add it to grid here 
  58. 	local base_title_grp = Vdo_base_object:new("grid_title_grp", self.handle, self.doc_handle) 
  59. 	base_title_grp:set_visible(false)	 
  60. 	 
  61. 	self.draw_called = false 
  62. 	self.title_added = false	 
  63. 	self.update_start_row = true	 
  64. 	 
  65. 	if game_get_platform() == "PC" then 
  66. 		Grid_mouse_input_tracker = Vdo_input_tracker:new() 
  67. 		Scrollbar_input_tracker = Vdo_input_tracker:new()				 
  68. 	end 
  69. end 
  70.  
  71. -- Deletes the internal data and destroys the button clones 
  72. function Vdo_grid_list:cleanup() 
  73. 	if self.draw_called then 
  74. 		for i, button in pairs(self.buttons) do 
  75. 			button:object_destroy() 
  76. 			self.buttons[i] = nil 
  77. 		end 
  78. 		self.draw_called = false 
  79. 	end 
  80. 	 
  81. 	if self.title_added then 
  82. 		for i = 1, #self.titles do 
  83. 			self.titles[i]:object_destroy() 
  84. 		end 
  85. 		self.title_added = false 
  86. 		table_clear(self.titles, true) 
  87. 	end 
  88. 	 
  89. 	if Grid_mouse_input_tracker ~= nil then 
  90. 		--Grid_mouse_input_tracker:remove_all() 
  91. 		Grid_mouse_input_tracker:subscribe(false) 
  92. 		 
  93. 		-- Not unsubscribing from the scrollbar here is intentional 
  94. 		-- If you do, it prevents the mouse from dragging the scrollbar correctly 
  95. 	end 
  96. 	 
  97. 	self.data = nil 
  98. 	vint_force_lua_gc() 
  99. end 
  100.  
  101. function Vdo_grid_list:draw_items(input_data, current_option, max_width, max_height, button_w, button_h, hint_button_offset, current_category, outline_scale, background_enabled, show_current_button_bool, grid_spacing, set_size) 
  102. 	max_width = max_width or 999 
  103. 	max_height = max_height or 999 
  104. 	 
  105. 	if self.draw_called == false then 
  106. 		self.update_start_row = true 
  107. 	end 
  108. 	 
  109. 	-- Nuke the shit out of whatever was previously here 
  110. 	self:cleanup() 
  111.  
  112. 	local data = {} 
  113. 	local data_size = 1 
  114. 	 
  115. 	-- Most grids to not contain categories... but we're going to make all the data fit this format (ie. an extra layer of tables) because 
  116. 	-- it greatly simplifies the script.  We just won't draw the header for grids that only have one category. 
  117. 	if input_data[1].category_name == nil then 
  118. 		 
  119. 		if(input_data[0] ~= nil)then -- Some input_data tables come in with a 0 value, copy over to data table but start with 1 instead 
  120. 			data[1] = {} 
  121. 			for i = 0, #input_data do 
  122. 				data[1][data_size] = input_data[i] 
  123. 				i = i + 1 
  124. 				data_size = data_size + 1 
  125. 			end 
  126. 		else 
  127. 			data[1] = input_data 
  128. 		end 
  129. 		 
  130. 		current_category = 1 
  131. 		data[1].category_name = "filler cat name" 
  132. 	else 
  133. 		data = input_data 
  134. 	end 
  135. 	 
  136. 	-- Set up tables to manage handles and data for this object 
  137. 	self.draw_called = true 
  138. 	self.buttons = {} 
  139. 	self.data = data 
  140. 	self.open = false 
  141. 	self.max_width = max_width 
  142. 	self.max_height = max_height	 
  143. 	self.button_w = button_w or GRID_BUTTON_SIZE 
  144. 	self.button_h = button_h or GRID_BUTTON_SIZE 
  145. 	self.hint_button_offset = hint_button_offset 
  146. 	self.outline_scale = outline_scale 
  147. 	self.background_enabled = background_enabled 
  148. 	self.show_current_button_bool = show_current_button_bool 
  149. 	self.grid_spacing = grid_spacing or GRID_BUTTON_SPACING 
  150. 	self.set_size = set_size 
  151. 	self.titles = {} 
  152. 	self.rows = 0 
  153. 	self.num_buttons = 0 
  154. 	self.cat_rows = {} 
  155. 	self.cat_buttons = {} 
  156. 	 
  157. 	local curr_row = 1 
  158. 		 
  159. 	self.num_categories = #data 
  160. 	 
  161. 	-- Set up handle for base button 
  162. 	local base_button 
  163. 	 
  164. 	-- Check which button to use 
  165. 	if data[1][1].is_layered then 
  166. 		base_button = Vdo_grid_button_layered:new("grid_layered", self.handle, self.doc_handle) 
  167. 	elseif data[1][1].is_checked ~= nil then 
  168. 		base_button = Vdo_grid_button_check:new("grid_check", self.handle, self.doc_handle) 
  169. 	elseif data[1][1].is_canceled_type then 
  170. 		base_button = Vdo_grid_button_canceled:new("grid_canceled", self.handle, self.doc_handle) 
  171. 	else 
  172. 		base_button = Vdo_grid_button:new("grid_base", self.handle, self.doc_handle) 
  173. 	end 
  174. 	 
  175. 	if base_button.handle == 0 then 
  176. 		return 
  177. 	end	 
  178. 	 
  179. 	--get the x and y of the button 
  180. 	base_button:set_property("anchor", -1 * self.button_w, -1 * self.button_h) 
  181. 	base_button.x, base_button.y = base_button:get_property("anchor") 
  182. 	 
  183. 	--adjust for negative grid padding 
  184. 	if self.grid_spacing < 0 then 
  185. 		base_button:set_anchor(base_button.x + (self.grid_spacing * -2), base_button.y + (self.grid_spacing * -2)) 
  186. 		base_button.x, base_button.y = base_button:get_property("anchor") 
  187. 	end 
  188. 		 
  189. 	-- Set initial category 
  190. 	if current_category == nil or current_category < 1 or current_category > self.num_categories then 
  191. 		current_category = 1 
  192. 	end 
  193. 	self.current_cat = current_category 
  194. 	 
  195. 	-- We need to go through all the categories and add up the rows, and find which row number our 
  196. 	-- current choice is in 
  197. 	local header_offset = 0 
  198. 	if self.num_categories > 1 then 
  199. 		header_offset = 1 
  200. 	end	 
  201. 	 
  202. 	local adjusted_height = (self.max_height * (self.button_h + self.grid_spacing)) + (self.grid_spacing * 2)  
  203. 	local adjusted_width = (self.button_w + self.grid_spacing) * self.max_width + (self.grid_spacing * 2) 
  204. 	 
  205. 	--adjust background for negative grid spacing 
  206. 	if self.grid_spacing < 0 then 
  207. 		adjusted_width = (self.button_w + self.grid_spacing) * self.max_width + (self.grid_spacing * 2) + (self.grid_spacing * -4) 
  208. 		adjusted_height = (self.max_height * (self.button_h + self.grid_spacing)) + (self.grid_spacing * 2) + (self.grid_spacing * -4) 
  209. 	end	 
  210. 	 
  211. 	--set background size and anchor 
  212. 	if self.background_enabled == nil then 
  213. 		self.background_enabled = true 
  214. 	end 
  215. 	 
  216. 	self.bg:set_visible(self.background_enabled) 
  217. 	 
  218. 	element_set_actual_size(self.bg.handle, adjusted_width, adjusted_height ) 
  219. 	 
  220. 	self.bg:set_anchor((self.button_w + self.grid_spacing) * -0.5, (self.button_h + self.grid_spacing) * -0.5)		 
  221. 	 
  222. 	local bg_x, bg_y = self.bg:get_anchor()	 
  223. 	 
  224. 	for i = 1, #data do 
  225. 	 
  226. 		self.cat_buttons[i] = #data[i] 
  227. 		self.num_buttons = self.num_buttons + self.cat_buttons[i] 
  228. 		 
  229. 		-- see if this category holds our current highlighted item 
  230. 		if i == self.current_cat then 
  231. 		 
  232. 			-- Set initial cursor position 
  233. 			if current_option == nil or current_option < 1  or current_option > self.cat_buttons[i] then 
  234. 				current_option = 1 
  235. 			end 
  236. 			 
  237. 			curr_row = self.rows + header_offset + ceil(current_option / self.max_width) 
  238. 		end 
  239. 		 
  240. 		self.cat_rows[i] = header_offset + ceil(self.cat_buttons[i]/max_width) 
  241. 		self.rows = self.rows + self.cat_rows[i] 
  242. 		 
  243. 	end 
  244. 	 
  245. 	--set the curent button to the passed in variable for the current option (as long as it's not nil) 
  246. 	if self.data[self.current_cat][current_option] ~= nil then 
  247. 		self.current_idx = current_option 
  248. 	end 
  249. 	 
  250. 	--if we have less rows than the max visible set the max visible to the number of rows 
  251. 	if self.rows < self.max_height then 
  252. 		self.max_height = self.rows 
  253. 	end	 
  254. 	 
  255. 	local start_row  
  256. 	if self.update_start_row then 
  257. 		-- calculate the first row we should display 
  258. 		start_row = curr_row - floor(self.max_height / 2) 
  259. 		if start_row < 1 then 
  260. 			start_row = 1 
  261. 		end 
  262. 		if start_row + self.max_height - 1 > self.rows then 
  263. 			start_row = self.rows - self.max_height + 1 
  264. 		end 
  265. 		 
  266. 		self.start_row = start_row 
  267. 		 
  268. 	else 
  269. 		-- If self.update_start_row is false, use self.start_row since then the starting row was already set 
  270. 		start_row = self.start_row 
  271. 	end 
  272. 	 
  273. 	local new_x = base_button.x 
  274. 	local new_y = base_button.y 
  275. 	 
  276. 	--loop through the visible rows and populate our table of buttons 
  277. 	local data_index 
  278. 	local cat_index 
  279. 	local grid_index = 1	 
  280. 	local draw_header = false	 
  281. 	 
  282. 	if self.num_categories > 1 then 
  283. 		local row_count = 0 
  284. 		for i = 1,self.num_categories do 
  285.  
  286. 			if start_row <= row_count + self.cat_rows[i] then 
  287. 				cat_index = i 
  288.  
  289. 				if start_row - row_count == 1 then 
  290. 					-- the first row to draw is a header row 
  291. 					draw_header = true 
  292. 					data_index = ((start_row - row_count - 1) * self.max_width) + 1 
  293. 				else 
  294. 					-- -2 to account for indexing starting at 1, and 1 row for category header 
  295. 					data_index = ((start_row - row_count - 2) * self.max_width) + 1				 
  296. 				end 
  297. 				 
  298. 				-- found category, stop loop 
  299. 				break 
  300. 			end 
  301. 			 
  302. 			row_count = row_count + self.cat_rows[i] 
  303. 		end 
  304. 	else 
  305. 		cat_index = 1 
  306. 		data_index = ((start_row - 1) * self.max_width) + 1	 
  307. 	end	 
  308. 		 
  309. 	local title_count = 0 
  310. 	 
  311. 	for i = 1,self.max_height do 
  312. 		-- are we on a category header row? 
  313. 		-- BTW, I can't believe lua doesn't have a continue operation... 
  314. 		if draw_header then 
  315. 			draw_header = false 
  316.  
  317. 			-- draw the category header 
  318. 			title_count = title_count + 1 
  319. 			self:add_subtitle(self.data[cat_index].category_name, title_count, new_y) 
  320. 					 
  321. 		else 	 
  322. 	 
  323. 			--only use grid spacing after the first row 
  324. 			--if i > 1 then 
  325. 				new_y = base_button.y + ((self.button_h + self.grid_spacing) * (i)) 
  326. 			--else 
  327. 			--	new_y = 0--base_button.y 
  328. 			--end 
  329. 			 
  330. 			--loop through the columns 
  331. 			for j = 1, max_width do 
  332. 				--check so that we don't run out of valid data 
  333. 				if data_index > self.num_buttons then 
  334. 					break 
  335. 				end 
  336. 				 
  337. 				--only use grid spacing after the first column 
  338. 				--if j == 1 then 
  339. 				--	new_x = 0--base_button.x 
  340. 				--else 
  341. 					new_x = base_button.x + ((self.button_w + self.grid_spacing) * j)	 
  342. 				--end 
  343. 								 
  344. 				if self.data[1][1].is_layered then 
  345. 					self.buttons[grid_index] = Vdo_grid_button_layered:clone(base_button.handle) 
  346. 				elseif self.data[1][1].is_checked ~= nil then 
  347. 					self.buttons[grid_index] = Vdo_grid_button_check:clone(base_button.handle)					 
  348. 				elseif self.data[1][1].is_canceled_type ~= nil then 
  349. 					self.buttons[grid_index] = Vdo_grid_button_canceled:clone(base_button.handle)					 
  350. 				else 
  351. 					self.buttons[grid_index] = Vdo_grid_button:clone(base_button.handle) 
  352. 				end				 
  353. 				self.buttons[grid_index]:set_visible(true) 
  354. 				local button = self.buttons[grid_index] 
  355. 				 
  356. 				local button_data = data[cat_index][data_index] 
  357.  
  358. 				-- Set the button icon 
  359. 				-- check for dual icons 
  360. 				if button_data.dual_wield == true then 
  361. 					button:set_icon(button_data.icon, true) 
  362. 				else 
  363. 					self:set_icon(button, button_data) 
  364. 				end 
  365. 			 
  366. 				-- Set the button toggle text 
  367. 				if button_data.label ~= nil then 
  368. 					button:set_text(button_data.label) 
  369. 				else 
  370. 					button:set_text_crc(button_data.label_crc) 
  371. 				end				 
  372. 				 
  373. 				-- Only color it if it's not a layered button 
  374. 				if self.data[1][1].is_layered == nil or self.data[1][1].is_layered == false then 
  375. 					button:set_color(button_data.color.red, button_data.color.green, button_data.color.blue)					 
  376. 				end 
  377.  
  378. 				-- If it's canceled_type button, then set whether it starts disabled 
  379. 				if self.data[1][1].is_canceled_type then 
  380. 					button:set_cancel(button_data.disabled) 
  381. 				end 
  382. 				 
  383. 				--debug_print("vint", "cat_index = "..cat_index..", grid_index = "..grid_index..", data_index = "..data_index.."\n") 
  384. 				 
  385. 				if self.data[cat_index][data_index].is_checked == true then 
  386. 					button:set_checkbox(1,self.highlight_color) 
  387. 				end 
  388. 				 
  389. 				-- Make the button visible 
  390. 				button:set_visible(true) 
  391. 				button:set_property("anchor", new_x, new_y) 
  392. 				 
  393. 				if set_size == true then 
  394. 					button:set_size(button_w,button_h) 
  395. 									 
  396. 					if vint_is_std_res() == true then			 
  397. 						button:set_scale(SCALE_STD_RES_GRID_BUTTON, SCALE_STD_RES_GRID_BUTTON) 
  398. 					end	 
  399. 				end				 
  400. 				 
  401. 				--check to see if we want unhighlighted buttons greyed out, used for radio station select 
  402. 				if self.tint_current_button == true then 
  403. 					local grey = 100 
  404. 					button:set_color(grey/255,grey/255,grey/255) 
  405. 				end 
  406. 				 
  407. 				-- if this is the highlighted choice, save for easy reference 
  408. 				if cat_index == self.current_cat and data_index == self.current_idx then 
  409. 					self.current_button = button 
  410. 				end 
  411. 				 
  412. 				self.prev_title = button_data.title 
  413. 				 
  414. 				data_index = data_index + 1 
  415. 				grid_index = grid_index + 1 
  416. 				 
  417. 				-- have we reached the end of the category? 
  418. 				if self.num_categories > 1 and data_index > self.cat_buttons[cat_index] then 
  419. 					data_index = 1 
  420. 					cat_index = cat_index + 1 
  421. 					draw_header = true 
  422. 					break 
  423. 				end 
  424. 			end 
  425. 		end 
  426. 	end 
  427.  
  428. 	if self.rows > self.max_height then 
  429. 		 
  430. 		self.scrollbar:set_anchor(bg_x + adjusted_width + GRID_BUTTON_SPACING + ANCHOR_SCROLLBAR_BUFFER, bg_y) 
  431. 		 
  432. 		if game_get_platform() == "PC" then	 
  433. 			local adjusted_total_height = (self.rows * (self.button_h + self.grid_spacing)) + (self.grid_spacing * 2)  
  434. 			self.scrollbar:set_size(SCROLLBAR_WIDTH, adjusted_height, adjusted_total_height) 
  435. 			 
  436. 			-- If self.update_start_row was false, then the scrollbar's value is already being set. 
  437. 			if self.update_start_row then 
  438. 				self.scrollbar:set_value(self.rows - (self.max_height - 1), self.start_row) 
  439. 			end 
  440. 			 
  441. 		else 
  442. 			self.scrollbar:set_size(SCROLLBAR_WIDTH, adjusted_height) 
  443. 			self.scrollbar:set_value(self.rows, curr_row) 
  444. 		end 
  445. 		 
  446. 		self.scrollbar:set_property("visible",true) 
  447. 	else 
  448. 		self.scrollbar:set_property("visible",false) 
  449. 	end 
  450. 	 
  451. 	--position name for highlighted item 
  452. 	self.highlight_name:set_anchor(bg_x, bg_y + adjusted_height + GRID_BUTTON_SPACING, 1) 
  453. 	 
  454. 	-- Highlight current button 
  455. 	local highlight_button = Vdo_grid_button:new("grid_top_button", self.handle, self.doc_handle) 
  456. 	local highlight_button_outline = Vdo_grid_button:new("grid_top_button_outline", self.handle, self.doc_handle) 
  457. 	local highlight_button_layered = Vdo_grid_button:new("grid_top_button_layered", self.handle, self.doc_handle) 
  458. 	local highlight_button_outline_layered = Vdo_grid_button:new("grid_top_button_outline_layered", self.handle, self.doc_handle) 
  459. 	local highlight_button_check = Vdo_grid_button_check:new("grid_top_button_check", self.handle, self.doc_handle) 
  460. 	local highlight_button_canceled = Vdo_grid_button_canceled:new("grid_top_button_canceled", self.handle, self.doc_handle) 
  461.  
  462. 	highlight_button:set_visible(false)	 
  463. 	highlight_button_outline:set_visible(false)	 
  464. 	highlight_button_layered:set_visible(false)	 
  465. 	highlight_button_outline_layered:set_visible(false)	 
  466. 	highlight_button_check:set_visible(false)	 
  467. 	highlight_button_canceled:set_visible(false)	 
  468. 	 
  469. 	-- Make sure current_button was set to a valid button, otherwise set it to the first button 
  470. 	if self.current_button.handle < 1 then 
  471. 		self.current_button = self.buttons[1] 
  472. 	end 
  473. 	self.current_button:set_visible(true) 
  474. 	 
  475. 	if self.data[1][1].is_layered then 
  476. 		highlight_button = Vdo_grid_button_layered:new("grid_top_button_layered", self.handle, self.doc_handle) 
  477. 		highlight_button_outline = Vdo_grid_button_layered:new("grid_top_button_outline_layered", self.handle, self.doc_handle)	 
  478. 		highlight_button_outline:set_visible(true) 
  479. 	elseif self.data[1][1].is_checked ~= nil then 
  480. 		highlight_button = Vdo_grid_button_check:new("grid_top_button_check", self.handle, self.doc_handle) 
  481. 		highlight_button_outline = Vdo_grid_button_check:new("grid_top_button_check", self.handle, self.doc_handle)	 
  482. 		--highlight_button:set_checkbox(1,self.highlight_color)		 
  483. 	elseif self.data[1][1].is_canceled_type ~= nil then 
  484. 		highlight_button = Vdo_grid_button_canceled:new("grid_top_button_canceled", self.handle, self.doc_handle) 
  485. 		highlight_button_outline = Vdo_grid_button_canceled:new("grid_top_button_canceled", self.handle, self.doc_handle)			 
  486. 	else 
  487. 		highlight_button = Vdo_grid_button:new("grid_top_button", self.handle, self.doc_handle) 
  488. 		highlight_button_outline = Vdo_grid_button:new("grid_top_button_outline", self.handle, self.doc_handle) 
  489. 		highlight_button_outline:set_visible(true) 
  490. 	end	 
  491. 	 
  492. 	-- Hide button underneath for checked buttons 
  493. 	if self.data[self.current_cat][current_option].is_checked ~= nil then 
  494. 		self.current_button:set_visible(false) 
  495. 	end 
  496. 	 
  497. 	-- check to see if we want to show the icon behind the highlight, used on radio station select 
  498. 	-- after the first draw save the status in self.show_current_button 
  499. 	if self.show_current_button_bool ~= nil then 
  500. 		--self.show_current_button = show_current_button 
  501. 		self.current_button:set_visible(show_current_button_bool) 
  502. 	end 
  503.  
  504. 	local button_data = self.data[self.current_cat][self.current_idx] 
  505. 		 
  506. 	--set the size of the highlight 
  507. 	self:set_highlight_size(button_data.dual_wield) 
  508.  
  509. 	highlight_button:set_visible(true)	 
  510. 		 
  511. 			 
  512. 	if outline_scale ~= nil then 
  513. 		highlight_button_outline:set_scale(outline_scale, outline_scale)			 
  514. 	end 
  515. 	 
  516. 	if self.data[1][1].is_layered == nil or self.data[1][1].is_layered == false then 
  517. 		highlight_button:set_color(button_data.color.red, button_data.color.green, button_data.color.blue) 
  518. 	end 
  519. 	 
  520. 	--do we have a check box type button? 
  521. 	--if so set the highlight color if highlight color is valid 
  522. 	if self.highlight_color ~= nil and self.data[1][1].is_checked ~= nil  then 
  523. 		highlight_button:set_highlight_color(self.highlight_color) 
  524. 	end 
  525. 	 
  526. 	--Set the button icon 
  527. 	self:set_icon(highlight_button, button_data)	 
  528. 	self:set_icon(highlight_button_outline, button_data)	 
  529. 	 
  530. 	-- set hightlight anchor position 
  531. 	local button_x,button_y = self.current_button:get_property("anchor") 
  532. 	local highlight = Vdo_base_object:new( "grid_highlight", self.handle, self.doc_handle) 
  533. 	highlight:set_property( "anchor", button_x, button_y) 
  534. 	highlight:set_visible(true) 
  535. 	 
  536. 	--don't play highlight anim if index is the same 
  537. 	--if old_idx ~= self.current_idx then 
  538. 	local highlight_anim = Vdo_anim_object:new("highlight_anim", self.handle, self.doc_handle) 
  539. 	highlight_anim:play() 
  540. 	--end 
  541. 		 
  542. 	local hint_button = Vdo_base_object:new("grid_hint_button", self.handle, self.doc_handle) 
  543. 	local highlight_scale_twn = Vdo_tween_object:new("grid_highlight_scale_twn", self.handle, self.doc_handle) 
  544. 	 
  545. 	if hint_button_offset == nil then 
  546. 		-- Reposition hint button to bottom right corner of highlighted button 
  547. 		local highlight_width, highlight_height = highlight_button:get_screen_size() 
  548. 		local highlight_scale_x, highlight_scale_y = highlight_scale_twn:get_end_value()		 
  549. 		hint_button:set_anchor(button_x + (highlight_width * highlight_scale_x * .5) - 35, button_y + (highlight_height * highlight_scale_y * .5) - 35) 
  550. 	else 
  551. 		hint_button:set_anchor(button_x + hint_button_offset, button_y + hint_button_offset) 
  552. 	end	 
  553. 		 
  554. 	-- Set highlighted item name 
  555. 	local highlight_label = self.data[self.current_cat][self.current_idx].label 
  556. 	local highlight_label_crc = self.data[self.current_cat][self.current_idx].label_crc 
  557. 	 
  558. 	if highlight_label ~= nil then 
  559. 		self.highlight_name:set_text(highlight_label) 
  560. 	else 
  561. 		self.highlight_name:set_text_crc(highlight_label_crc) 
  562. 	end	 
  563. 	 
  564. 	-- align grid list to the top right of the button for easier placement in the doc 
  565. 	--local first_btn_width, first_btn_height = self.buttons[1]:get_screen_size()	 
  566. 	self.group:set_anchor((self.button_w - SIZE_GRID_BUTTON) * 0.5, (self.button_h - SIZE_GRID_BUTTON)* 0.5) 
  567. 	 
  568. 	--disable the clip/mask for now 
  569. 	--local grid_clip = Vdo_base_object:new("grid_clip") 
  570. 	--grid_clip:set_property("clip_enabled", false) 
  571. 	 
  572. 	self.update_start_row = true 
  573. end 
  574.  
  575. function Vdo_grid_list:move_cursor(direction, do_not_redraw, is_index_set) 
  576. 	if not self.draw_called then 
  577. 		return 
  578. 	end 
  579. 	 
  580. 	local num_rows = ceil(self.cat_buttons[self.current_cat] / self.max_width) 
  581. 	 
  582. 	-- Don't update the start row when using the mouse to select something 
  583. 	if direction == 0 then 
  584. 		self.update_start_row = false 
  585. 	end 
  586. 	 
  587. 	--check if we have more than one row or category 
  588. 	if self.num_categories == 1 and num_rows <= 1 and (direction == MOVE_UP or direction == MOVE_DOWN) then 
  589. 		return 
  590. 	--check if we have one item 
  591. 	elseif self.num_categories == 1 and self.num_buttons <= 1 then 
  592. 		return 
  593. 	else 
  594. 		--check if we can process input 
  595. 		if Vdo_grid_list_tween_done then 
  596. 		 
  597. 			-- Clear out old highlight 
  598. 			for idx, button in pairs(self.buttons) do 
  599. 				button:set_highlight(false)			 
  600. 			end 
  601. 			 
  602. 			-- apply movement 
  603. 			local move_offset 
  604. 			if direction == MOVE_UP then 
  605. 				move_offset = - self.max_width 
  606. 			elseif direction == MOVE_DOWN then 
  607. 				move_offset = self.max_width 
  608. 			else 
  609. 				move_offset = direction 
  610. 			end 
  611. 			local old_idx = self.current_idx 
  612. 			local prev_row = ceil(self.current_idx / self.max_width) 
  613.  
  614. 			-- apply movement 
  615. 			self.current_idx = self.current_idx + move_offset 
  616. 			local new_row = ceil(self.current_idx / self.max_width) 
  617. 			 
  618.  
  619. 			-- do we need a header row? 
  620. 			local offset = 1 
  621. 			if self.num_categories > 1 then 
  622. 				offset = 2 
  623. 			end 
  624. 			 
  625. 			local num_buttons = self.cat_buttons[self.current_cat]		 
  626. 			local last_row_len = num_buttons - ((self.cat_rows[self.current_cat] - offset) * self.max_width) 
  627. 			 
  628. 			if is_index_set then 
  629. 				-- if the index was set from mouse_move, update only the highlight since the grid's contents have not changed 
  630. 				self:update_highlight(self.hint_button_offset) 
  631. 				 
  632. 			else 
  633. 				-- handle all wrapping 
  634. 				if direction == MOVE_RIGHT then 
  635. 					-- row wrap 
  636. 					if new_row ~= prev_row then 
  637. 						self.current_idx = self.current_idx - self.max_width 
  638. 					end 
  639. 					-- last short row wrap 
  640. 					if self.current_idx > num_buttons then 
  641. 						self.current_idx = self.current_idx - last_row_len 
  642. 					end 
  643. 				elseif direction == MOVE_LEFT then 
  644. 					-- row wrap 
  645. 					if new_row ~= prev_row then 
  646. 						self.current_idx = self.current_idx + self.max_width 
  647. 					end 
  648. 					-- last short row wrap 
  649. 					if self.current_idx > num_buttons then 
  650. 						self.current_idx = self.current_idx - (self.max_width - last_row_len) 
  651. 					end 
  652. 				elseif direction == MOVE_UP then 
  653. 					-- top of grid wrap 
  654. 					if self.current_idx < 1 then 
  655. 					 
  656. 						-- go to previous category 
  657. 						self.current_cat = self.current_cat - 1 
  658. 						if self.current_cat < 1 then 
  659. 							self.current_cat = self.num_categories 
  660. 						end 
  661. 						 
  662. 						local num_rows_new_cat = ceil(self.cat_buttons[self.current_cat] / self.max_width) 
  663. 						 
  664. 						-- We now need to calculate the index in the new category to use 
  665. 						self.current_idx = (num_rows_new_cat * self.max_width) - (self.max_width - old_idx) 
  666.  
  667. 						if self.current_idx > self.cat_buttons[self.current_cat] then 
  668. 							if( self.cat_buttons[self.current_cat] <= self.max_width ) then  
  669. 								self.current_idx = old_idx 
  670. 							else 
  671. 								self.current_idx = self.current_idx - self.max_width 
  672. 							end 
  673. 							 
  674. 							if self.current_idx > self.cat_buttons[self.current_cat] or self.current_idx < 1 then 
  675. 								self.current_idx = self.cat_buttons[self.current_cat] 
  676. 							end 
  677. 						end 
  678.  
  679. 					end 
  680. 				elseif direction == MOVE_DOWN then 
  681. 					-- end of grid wrap 
  682. 					if self.current_idx > num_buttons then 
  683. 					 
  684. 						-- go to next category 
  685. 						self.current_cat = self.current_cat + 1 
  686. 						if self.current_cat > self.num_categories then 
  687. 							self.current_cat = 1 
  688. 						end 
  689. 						 
  690. 						-- We now need to calculate the index in the new category to use 
  691. 						self.current_idx = ((old_idx - 1) % self.max_width) + 1 
  692. 						if self.current_idx > self.cat_buttons[self.current_cat] then 
  693. 							self.current_idx = self.cat_buttons[self.current_cat] 
  694. 						end 
  695.  
  696. 					end 
  697. 				end 
  698. 				 
  699. 				--redraw the list 
  700. 				if do_not_redraw ~= true then 
  701. 					--input_data, current_option, max_width, max_height, button_w, button_h, hint_button_offset, current_category, outline_scale, background_enabled, show_current_button, grid_padding, set_size 
  702. 					self:draw_items(self.data, self.current_idx, self.max_width, self.max_height, self.button_w, self.button_h, self.hint_button_offset, self.current_cat, self.outline_scale, self.background_enabled, self.show_current_button_bool, self.grid_spacing, self.set_size) 
  703. 					self:update_mouse_inputs() 
  704. 				end 
  705. 			end 
  706. 		end 
  707. 		 
  708. 		--check if we should play scrolling audio 
  709. 		if direction ~= 0 or is_index_set then 
  710. 			if self.num_buttons > 1 then 
  711. 				game_UI_audio_play("UI_Reward_Store_Menu_Navigation") 
  712. 			end 
  713. 		end 
  714. 	end 
  715. end 
  716.  
  717. function Vdo_grid_list:get_selection() 
  718. 	if not self.draw_called then 
  719. 		return 
  720. 	end 
  721.  
  722. 	return self.current_idx 
  723. end 
  724.  
  725. -- Gets an optional ID value if one is saved 
  726. function Vdo_grid_list:get_id() 
  727. 	if not self.draw_called then 
  728. 		return 
  729. 	end 
  730. 	 
  731. 	return self.data[self.current_cat][self.current_idx].id 
  732. end 
  733.  
  734. function Vdo_grid_list:get_data_from_id(id) 
  735.  
  736. 	for i, category in pairs (self.data) do 
  737. 		for j, entry in pairs (category) do 
  738. 			if entry.id == id then 
  739. 				return entry 
  740. 			end 
  741. 		end 
  742. 	end 
  743.  
  744. end 
  745.  
  746. function Vdo_grid_list:button_a() 
  747. 	if not self.draw_called then 
  748. 		return 
  749. 	end 
  750. 		 
  751. 	--check if we can process input 
  752. 	if not Vdo_grid_list_tween_done then 
  753. 		return 
  754. 	end 
  755. 	 
  756. 	self:toggle_checked()	 
  757. end 
  758.  
  759. function Vdo_grid_list:button_b() 
  760. 	if not self.draw_called then 
  761. 		return 
  762. 	end 
  763.  
  764. end 
  765.  
  766. function Vdo_grid_list:toggle_checked() 
  767. 	local current_idx = self.current_idx 
  768. 	local current_cat = self.current_cat 
  769. 	local current_data = self.data[current_cat][current_idx] 
  770. 	if current_data.is_checked then 
  771. 		local current_button = self.buttons[current_idx] 
  772. 		if current_data.checked ~= nil then 
  773. 			if current_data.locked == false or current_data.locked == nil then 
  774. 				if current_data.checked == true then 
  775. 					current_data.checked = false 
  776. 				else 
  777. 					current_data.checked = true 
  778. 				end 
  779. 			end 
  780. 		end 
  781. 		current_button:set_check_box(current_data.checked,current_data.locked) 
  782.  
  783. 	elseif current_data.is_canceled_type then 
  784. 		local new_disabled_state = not current_data.disabled 
  785. 		current_data.disabled = new_disabled_state 
  786. 		local current_button = self.buttons[current_idx] 
  787. 		local highlight_button = Vdo_grid_button_canceled:new("grid_top_button_canceled", self.handle, self.doc_handle) 
  788. 		current_button:set_cancel(new_disabled_state) 
  789. 		highlight_button:set_cancel(new_disabled_state) 
  790. 	end 
  791.  
  792. end 
  793.  
  794.  
  795. function Vdo_grid_list:return_data() 
  796. 	if not self.draw_called then 
  797. 		return 
  798. 	end 
  799. 	 
  800. 	return self.data 
  801. end 
  802.  
  803. function Vdo_grid_list:return_selected_data() 
  804. 	if not self.draw_called then 
  805. 		return 
  806. 	end 
  807. 	 
  808. 	return self.data[self.current_cat][self.current_idx] 
  809. end 
  810.  
  811. function Vdo_grid_list:return_selected_index() 
  812. 	if not self.draw_called then 
  813. 		return 
  814. 	end 
  815. 	 
  816. 	return self.current_idx 
  817. end 
  818.  
  819. function Vdo_grid_list:return_selected_cat() 
  820. 	if not self.draw_called then 
  821. 		return 
  822. 	end 
  823. 	 
  824. 	return self.current_cat 
  825. end 
  826.  
  827. function Vdo_grid_list:is_tween_done() 
  828. 	return Vdo_grid_list_tween_done 
  829. end 
  830.  
  831. function vdo_grid_list_scroll_done(tween_h, event_name) 
  832. 	-- remove this callback 
  833. 	remove_tween_end_callback( vint_object_find("grid_group_anchor_tween") ) 
  834. 	Vdo_grid_list_tween_done = true 
  835. end 
  836.  
  837. function Vdo_grid_list:nav_enable(is_on, callback_action, callback_nav) 
  838. 		 
  839. 	if is_on then 
  840. 		-- Subscribe to the button presses we need 
  841. 		Input_tracker:add_input("select", callback_action, 150) 
  842. 		Input_tracker:add_input("back", callback_action, 150) 
  843. 		Input_tracker:add_input("nav_up", callback_nav, 150) 
  844. 		Input_tracker:add_input("nav_down", callback_nav, 150)			 
  845. 		Input_tracker:add_input("nav_left", callback_nav, 150) 
  846. 		Input_tracker:add_input("nav_right", callback_nav, 150)		 
  847. 		Input_tracker:subscribe(true)	 
  848. 		--self:set_visible(true) 
  849. 		 
  850. 		-- Subscribe to the mouse inputs we need 
  851. 		if Grid_mouse_input_tracker ~= nil then 
  852. 			self:add_mouse_inputs(callback_action, callback_nav, Grid_mouse_input_tracker) 
  853. 			Grid_mouse_input_tracker:subscribe(true) 
  854. 			Scrollbar_input_tracker:subscribe(true) 
  855. 		end 
  856. 		 
  857. 		if self.store_input_tracker then 
  858. 			self.store_input_tracker:subscribe(false) 
  859. 		end		 
  860. 	else 
  861. 		-- Remove the button presses we needed 
  862. 		Input_tracker:remove_input("select") 
  863. 		Input_tracker:remove_input("back") 
  864. 		Input_tracker:remove_input("nav_up") 
  865. 		Input_tracker:remove_input("nav_down") 
  866. 		Input_tracker:remove_input("nav_left") 
  867. 		Input_tracker:remove_input("nav_right")		 
  868. 		Input_tracker:subscribe(false) 
  869. 		--self:set_visible(false) 
  870. 		 
  871. 		if Grid_mouse_input_tracker ~= nil then 
  872. 			Grid_mouse_input_tracker:remove_all() 
  873. 			Scrollbar_input_tracker:remove_all() 
  874. 		end 
  875. 		 
  876. 		if self.store_input_tracker and self.input_enabled then 
  877. 			self.store_input_tracker:subscribe(true) 
  878. 		end			 
  879. 	end 
  880. 	 
  881. 	self.input_enabled = is_on 
  882. end 
  883.  
  884. function Vdo_grid_list:set_highlight_color(color) 
  885. 	self.scrollbar:set_highlight_color(color) 
  886. 	self.highlight_name:set_color(color.R, color.G, color.B) 
  887. 	self.highlight_color = color 
  888. end 
  889.  
  890. function Vdo_grid_list:show_grid(is_visible) 
  891.  
  892. 	--self:set_visible(is_visible) 
  893. 	 
  894. end 
  895.  
  896. function Vdo_grid_list:add_subtitle(title_name, title_index, y_pos) 
  897.  
  898. 	--clone title and add it to grid here 
  899. 	local base_title_grp = Vdo_base_object:new("grid_title_grp", self.handle, self.doc_handle) 
  900. 	 
  901. 	self.titles[title_index] = Vdo_base_object:clone(base_title_grp.handle) 
  902. 	self.titles[title_index].title = Vdo_base_object:new("grid_title",self.titles[title_index].handle, self.doc_handle) 
  903. 	self.titles[title_index].line = Vdo_base_object:new("grid_title_line",self.titles[title_index].handle, self.doc_handle) 
  904. 	 
  905. 	self.titles[title_index].title:set_text(title_name) 
  906. 	self.titles[title_index].title:set_visible(true) 
  907.  
  908. 	local text_width, text_height = self.titles[title_index].title:get_actual_size() 
  909. 	local bg_width, bg_height = self.bg:get_actual_size() 
  910. 	 
  911. 	self.titles[title_index].line:set_anchor(text_width + 10, text_height * 0.5) 
  912. 	 
  913. 	self.titles[title_index].line:set_actual_size(bg_width - (text_width + 30), 3) 
  914.  
  915. 	self.titles[title_index].line:set_visible(true) 
  916. 	self.titles[title_index].line:set_alpha(1) 
  917. 	 
  918. 	self.titles[title_index]:set_anchor(self.button_w * -0.5 + 10, y_pos + self.button_h) 
  919. 	 
  920. 	self.titles[title_index]:set_visible(true) 
  921. 	 
  922. 	self.title_added = true 
  923.  
  924. end 
  925.  
  926. function Vdo_grid_list:set_icon(button, button_data) 
  927. 	if button_data.is_layered then 
  928. 		button:set_icon(button_data)	 
  929. 	else	 
  930. 		if nil ~= button_data.icon then 
  931. 			button:set_icon(button_data.icon) 
  932. 		elseif nil ~= button_data.icon_crc then 
  933. 			button:set_icon_crc(button_data.icon_crc) 
  934. 		end	 
  935. 	end 
  936.  
  937. 	if button_data.is_canceled_type then 
  938. 		button:set_cancel(button_data.disabled) 
  939. 	end 
  940. 	 
  941. 	if button_data.is_checked then 
  942. 		button:set_checkbox(1, self.highlight_color) 
  943. 	end 
  944. end 
  945.  
  946. function Vdo_grid_list:set_highlight_size(dual_is_visible) 
  947. 	local highlight_button	 
  948. 	if self.data[1][1].is_layered then 
  949. 		highlight_button = Vdo_grid_button_layered:new("grid_top_button_layered", self.handle) 
  950. 	elseif self.data[1][1].is_checked ~= nil then 
  951. 		highlight_button = Vdo_grid_button_check:new("grid_top_button_check", self.handle) 
  952. 	elseif self.data[1][1].is_canceled_type ~= nil then 
  953. 		highlight_button = Vdo_grid_button_canceled:new("grid_top_button_canceled", self.handle) 
  954. 	else 
  955. 		highlight_button = Vdo_grid_button:new("grid_top_button", self.handle) 
  956. 	end 
  957. --	highlight_button:set_size(self.button_w, self.button_h) 
  958. 	--highlight_button:set_scale(self.outline_scale, self.outline_scale) 
  959. 	 
  960. 	if dual_is_visible == true then 
  961. 		highlight_button:set_highlight(true, true)		 
  962. 	else 
  963. 		highlight_button:set_highlight(true)		 
  964. 	end 
  965. end 
  966.  
  967. -- Only updates the highlighted button based on the current index without redrawing the entire list 
  968. -- This function's code copies the highlight button code in draw_items 
  969. -- 
  970. function Vdo_grid_list:update_highlight(hint_button_offset) 
  971. 	-- Highlight current button 
  972. 	local highlight_button = Vdo_grid_button_layered:new("grid_top_button", self.handle, self.doc_handle) 
  973. 	local highlight_button_outline = Vdo_grid_button_layered:new("grid_top_button_outline", self.handle, self.doc_handle) 
  974. 	local highlight_button_layered = Vdo_grid_button_layered:new("grid_top_button_layered", self.handle, self.doc_handle) 
  975. 	local highlight_button_outline_layered = Vdo_grid_button_layered:new("grid_top_button_outline_layered", self.handle, self.doc_handle) 
  976. 	local highlight_button_check = Vdo_grid_button_check:new("grid_top_button_check", self.handle, self.doc_handle) 
  977. 	local highlight_button_canceled = Vdo_grid_button_canceled:new("grid_top_button_canceled", self.handle, self.doc_handle) 
  978.  
  979. 	highlight_button:set_visible(false)	 
  980. 	highlight_button_outline:set_visible(false)	 
  981. 	highlight_button_layered:set_visible(false)	 
  982. 	highlight_button_outline_layered:set_visible(false)	 
  983. 	highlight_button_check:set_visible(false)	 
  984. 	highlight_button_canceled:set_visible(false)	 
  985. 	 
  986. 	-- Get the current button based on the current index 
  987. 	local grid_index = self.current_idx - ((self.start_row - 1) * self.max_width) 
  988. 	self.current_button = self.buttons[grid_index] 
  989. 	self.current_button:set_visible(true) 
  990. 	 
  991. 	if self.data[1][1].is_layered then 
  992. 		highlight_button = Vdo_grid_button_layered:new("grid_top_button_layered", self.handle, self.doc_handle) 
  993. 		highlight_button_outline = Vdo_grid_button_layered:new("grid_top_button_outline_layered", self.handle, self.doc_handle)	 
  994. 		highlight_button_outline:set_visible(true) 
  995. 	elseif self.data[1][1].is_checked ~= nil then 
  996. 		highlight_button = Vdo_grid_button_check:new("grid_top_button_check", self.handle, self.doc_handle) 
  997. 	elseif self.data[1][1].is_canceled_type ~= nil then 
  998. 		highlight_button = Vdo_grid_button_canceled:new("grid_top_button_canceled", self.handle, self.doc_handle) 
  999. 	else 
  1000. 		highlight_button = Vdo_grid_button:new("grid_top_button", self.handle, self.doc_handle) 
  1001. 		highlight_button_outline = Vdo_grid_button:new("grid_top_button_outline", self.handle, self.doc_handle) 
  1002. 		highlight_button_outline:set_visible(true) 
  1003. 	end	 
  1004. 	 
  1005. 	-- Hide button underneath for checked buttons 
  1006. 	if self.data[self.current_cat][self.current_idx].is_checked ~= nil then 
  1007. 		self.current_button:set_visible(false) 
  1008. 		 
  1009. 		--hide check for highlight 
  1010. 		--self.current_button:set_checkbox(-1) 
  1011. 	end 
  1012. 	 
  1013. 	local dual_is_visible = self.data[self.current_cat][self.current_idx].dual_wield 
  1014. 	 
  1015. 	--set the size of the highlight 
  1016. 	self:set_highlight_size(dual_is_visible) 
  1017.  
  1018. 	highlight_button:set_visible(true) 
  1019. 	 
  1020. 	local val = self.data[self.current_cat][self.current_idx] 
  1021. 	 
  1022. 	if self.data[1][1].is_layered == nil or self.data[1][1].is_layered == false then 
  1023. 		highlight_button:set_color(val.color.red, val.color.green, val.color.blue) 
  1024. 	end 
  1025. 	 
  1026. 	if self.highlight_color ~= nil then 
  1027. 		highlight_button:set_highlight_color(self.highlight_color) 
  1028. 	end 
  1029. 	 
  1030. 	--Set the button icon 
  1031. 	self:set_icon(highlight_button, val) 
  1032. 	self:set_icon(highlight_button_outline, val) 
  1033.  
  1034. 	-- set hightlight anchor position 
  1035. 	local button_x,button_y = self.current_button:get_property("anchor") 
  1036. 	local highlight = Vdo_base_object:new( "grid_highlight", self.handle, self.doc_handle) 
  1037. 	highlight:set_property( "anchor", button_x, button_y) 
  1038. 	highlight:set_visible(true) 
  1039. 	 
  1040. 	--don't play highlight anim if index is the same 
  1041. 	--if old_idx ~= self.current_idx then 
  1042. 	local highlight_anim = Vdo_anim_object:new("highlight_anim", self.handle, self.doc_handle) 
  1043. 	highlight_anim:play() 
  1044. 	--end 
  1045. 		 
  1046. 	local hint_button = Vdo_base_object:new("grid_hint_button", self.handle, self.doc_handle) 
  1047. 	local highlight_scale_twn = Vdo_tween_object:new("grid_highlight_scale_twn", self.handle, self.doc_handle) 
  1048. 	 
  1049. 	if hint_button_offset == nil then 
  1050. 		-- Reposition hint button to bottom right corner of highlighted button 
  1051. 		local highlight_width, highlight_height = highlight_button:get_screen_size() 
  1052. 		local highlight_scale_x, highlight_scale_y = highlight_scale_twn:get_end_value()		 
  1053. 		hint_button:set_anchor(button_x + (highlight_width * highlight_scale_x * .5) - 35, button_y + (highlight_height * highlight_scale_y * .5) - 35) 
  1054. 	else 
  1055. 		hint_button:set_anchor(button_x + hint_button_offset, button_y + hint_button_offset) 
  1056. 	end	 
  1057. 		 
  1058. 	-- Set highlighted item name 
  1059. 	local highlight_label = self.data[self.current_cat][self.current_idx].label 
  1060. 	local highlight_label_crc = self.data[self.current_cat][self.current_idx].label_crc 
  1061. 	 
  1062. 	if highlight_label ~= nil then 
  1063. 		self.highlight_name:set_text(highlight_label) 
  1064. 	else 
  1065. 		self.highlight_name:set_text_crc(highlight_label_crc) 
  1066. 	end 
  1067. 	 
  1068. 	self.group:set_anchor((self.button_w - SIZE_GRID_BUTTON) * 0.5, (self.button_h - SIZE_GRID_BUTTON)* 0.5) 
  1069. end 
  1070.  
  1071.  
  1072. -- ===================================== 
  1073. --       Mouse Specific Functions 
  1074. -- ===================================== 
  1075.  
  1076. -- Returns the data index of the button selected based on the target handle. 
  1077. -- Returns 0 (invalid index) if no button was found 
  1078. -- 
  1079. function Vdo_grid_list:get_data_index(target_handle) 
  1080. 	if not self.draw_called then 
  1081. 		debug_print("vint", "Vdo_grid_list:get_selection called() with invalid document handle") 
  1082. 		return 
  1083. 	end 
  1084. 	 
  1085. 	for idx, button in pairs(self.buttons) do 
  1086. 		if button.handle == target_handle then 
  1087. 			if self.rows > self.max_height then 
  1088. 				if self.num_categories > 1 then 
  1089. 					-- This should never happen 
  1090. 					if self.data[self.button_cats[idx]][self.button_ids[idx]] == nil then 
  1091. 						local bad_idx = idx 
  1092. 						return 0 
  1093. 					end 
  1094. 					return self.button_ids[idx], self.button_cats[idx] 
  1095. 				else 
  1096. 					-- This works for grids without categories, but not ones with 
  1097. 					local data_index = (self.start_row - 1) * self.max_width + idx 
  1098. 					if self.data[self.current_cat][data_index] ~= nil then 
  1099. 						return data_index, 1 -- 1 is the category 
  1100. 					end 
  1101. 				end 
  1102. 			else 
  1103. 				return idx 
  1104. 			end 
  1105. 		end 
  1106. 	end 
  1107. 	 
  1108. 	return 0 
  1109. end 
  1110.  
  1111. function Vdo_grid_list:get_visible_rows() 
  1112. 	local end_row 
  1113. 	if self.rows > self.max_height then 
  1114. 		end_row = self.start_row + (self.max_height - 1) 
  1115. 	else 
  1116. 		end_row = self.rows 
  1117. 	end 
  1118. 	 
  1119. 	return self.start_row, end_row 
  1120. end 
  1121.  
  1122. function Vdo_grid_list:set_selection(new_index, new_category) 
  1123. 	if not self.draw_called then 
  1124. 		debug_print("vint", "Vdo_grid_list:get_selection called() with invalid document handle") 
  1125. 		return 
  1126. 	end 
  1127. 	 
  1128. 	self.current_idx = new_index 
  1129. 	if new_category ~= nil then 
  1130. 		self.current_cat = new_category 
  1131. 	else 
  1132. 		self.current_cat = 1 
  1133. 	end 
  1134. end 
  1135.  
  1136. -- Set and store the ui_screen, needed for the callback functions for the scroll and drag events 
  1137. function Vdo_grid_list:set_ui_screen(ui_screen) 
  1138. 	self.ui_screen = ui_screen 
  1139. end 
  1140.  
  1141. function Vdo_grid_list:add_mouse_inputs(callback_action, callback_nav, input_tracker, priority, update_scrollbar) 
  1142. 	if (self.buttons == nil) or (callback_action == nil) or (callback_nav == nil) then 
  1143. 		return 
  1144. 	end 
  1145. 	 
  1146. 	-- Store the callback functions for the update_mouse_inputs function 
  1147. 	if self.callback_action ~= callback_action then 
  1148. 		self.callback_action = callback_action 
  1149. 	end 
  1150. 	 
  1151. 	if self.callback_nav ~= callback_nav then 
  1152. 		self.callback_nav = callback_nav 
  1153. 	end 
  1154. 	 
  1155. 	-- Default priority value to 150 
  1156. 	priority = priority or 150 
  1157.  
  1158. 	-- Add mouse_click and mouse_move events for each button in the list 
  1159. 	for idx, button in pairs(self.buttons) do 
  1160. 		input_tracker:add_mouse_input("mouse_click", callback_action, 50, button.handle) 
  1161. 		input_tracker:add_mouse_input("mouse_move", callback_nav, 50, button.handle) 
  1162. 	end 
  1163. 	 
  1164. 	-- Add mouse inputs for the scroll region and scrolltab if needed 
  1165. 	if self.rows > self.max_height and self.ui_screen ~= nil then 
  1166. 		input_tracker:add_mouse_input("mouse_scroll", self.ui_screen.."_mouse_scroll", priority, self.bg.handle) 
  1167. 		-- This forces the scroll wheel to work in "empty" areas of the grid 
  1168. 		input_tracker:add_mouse_input("mouse_click", callback_action, priority, self.bg.handle) 
  1169. 		 
  1170. 		if update_scrollbar == nil or update_scrollbar == true then 
  1171. 			self.scrollbar:add_mouse_inputs(self.ui_screen, Scrollbar_input_tracker, priority) 
  1172. 		end 
  1173. 	end 
  1174.  
  1175. 	-- Calculate the buttons' categories and ids (if categories are being used) 
  1176. 	if self.num_categories > 1 then 
  1177. 		-- Set the row of each self.data element 
  1178. 		local cur_row = 1 
  1179. 		local row_offset 
  1180. 		for i = 1, self.num_categories do 
  1181. 			cur_row = cur_row + 1 
  1182. 			for j = 1, #self.data[i] do 
  1183. 				row_offset = ((j - 1) - self:recursive_mod((j - 1), self.max_width)) / self.max_width 
  1184. 				self.data[i][j].row = cur_row + row_offset 
  1185. 			end 
  1186. 			cur_row = cur_row + (row_offset + 1) 
  1187. 		end 
  1188. 		 
  1189. 		self.button_cats = {} 
  1190. 		self.button_ids = {} 
  1191. 		self.num_button_ids = 0 
  1192. 		local end_row = self.start_row + self.max_height - 1 
  1193. 		-- Loop through it all again, creating the button_ids and button_cats lists 
  1194. 		for i = 1, self.num_categories do 
  1195. 			for j = 1, #self.data[i] do 
  1196. 				if self.data[i][j].row >= self.start_row and self.data[i][j].row <= end_row then 
  1197. 					self.num_button_ids = self.num_button_ids + 1 
  1198. 					self.button_cats[self.num_button_ids] = i 
  1199. 					self.button_ids[self.num_button_ids] = j 
  1200. 				end 
  1201. 			end 
  1202. 		end 
  1203. 	end 
  1204. end 
  1205.  
  1206. -- Custom recursive mod function because it doesn't exist 
  1207. function Vdo_grid_list:recursive_mod(value, modulus) 
  1208. 	if (value >= modulus) then 
  1209. 		return self:recursive_mod(value - modulus, modulus) 
  1210. 	else 
  1211. 		return value 
  1212. 	end 
  1213. end 
  1214.  
  1215. -- Rebuilds the mouse input subscriptions, usually done when the list was rebuilt with draw_items() 
  1216. -- 
  1217. function Vdo_grid_list:update_mouse_inputs(input_tracker) 
  1218. 	if game_get_platform() ~= "PC" then 
  1219. 		return 
  1220. 	end 
  1221.  
  1222. 	-- Default the input tracker to the Grid_mouse_input_tracker if not specified 
  1223. 	if input_tracker == nil then 
  1224. 		input_tracker = Grid_mouse_input_tracker 
  1225. 	end 
  1226. 	 
  1227. 	input_tracker:remove_all() 
  1228. 	self:add_mouse_inputs(self.callback_action, self.callback_nav, input_tracker, 50, false) 
  1229. 	input_tracker:subscribe(true) 
  1230. end 
  1231.  
  1232. function Vdo_grid_list:scroll_list(scroll_lines, new_start_index) 
  1233. 	new_start_index = new_start_index or 0 
  1234. 	if scroll_lines == 0 and (new_start_index == self.start_row or new_start_index == 0) then 
  1235. 		return 
  1236. 	end 
  1237. 	 
  1238. 	 
  1239. 	local old_start_row = self.start_row 
  1240. 	if new_start_index ~= 0 then 
  1241. 		-- Set the new start index (calculated by the scrolltab) 
  1242. 		self.start_row = new_start_index 
  1243. 	 
  1244. 	else 
  1245. 		-- Update the rows that are visible if scrolled with the scroll wheel 
  1246. 		self.start_row = self.start_row + scroll_lines 
  1247. 		local end_row = self.start_row + (self.max_height - 1) 
  1248. 		if self.start_row < 1 then 
  1249. 			self.start_row = 1 
  1250. 		elseif end_row > self.rows then 
  1251. 			self.start_row = self.rows - (self.max_height - 1) 
  1252. 		end 
  1253. 	end 
  1254. 	local end_row = self.start_row + (self.max_height - 1) 
  1255. 	 
  1256. 	-- Move the highlight to a visible row if necessary (cannot go outside the visible range) 
  1257. 	if self.num_categories == 1 then 
  1258. 		local current_row = ceil(self.current_idx / self.max_width) 
  1259. 		if current_row < self.start_row then 
  1260. 			self.current_idx = self.current_idx + ((self.start_row - current_row) * self.max_width) 
  1261. 		elseif current_row > end_row then 
  1262. 			self.current_idx = self.current_idx - ((current_row - end_row) * self.max_width) 
  1263. 		end 
  1264. 	end 
  1265. 	 
  1266. 	-- Don't want draw_items to scroll the list or move the scrolltab 
  1267. 	self.update_start_row = false; 
  1268. 	if scroll_lines ~= 0 then 
  1269. 		self.scrollbar:set_value(self.rows - (self.max_height - 1), self.start_row) 
  1270. 	end 
  1271. 	 
  1272. 	-- Only update the list if the visible rows have changed 
  1273. 	if old_start_row ~= self.start_row then 
  1274. 		self:draw_items(self.data, self.current_idx, self.max_width, self.max_height, self.button_w, self.button_h, self.hint_button_offset, self.current_cat, self.outline_scale, self.background_enabled, self.show_current_button_bool, self.grid_spacing, self.set_size) 
  1275. 		--self:draw_items(self.data, self.current_idx, self.max_width, self.max_height, self.button_w, self.button_h, self.hint_button_offset, self.current_cat) 
  1276. 		self:update_mouse_inputs() 
  1277. 	end 
  1278. end 
  1279.  
  1280. function Vdo_grid_list:show_highlight_text( show_text ) 
  1281. 	--show_text is a boolean from the screen 
  1282. 	self.highlight_name:set_visible( show_text ) 
  1283. end 
  1284.  
  1285. function Vdo_grid_list:show_current_button( show_button ) 
  1286. 	--show_button is a boolean, used on the radio station select screen  
  1287. 	self.show_current_button_bool = show_button 
  1288. end 
  1289.  
  1290. function Vdo_grid_list:tint_current_button( tint_button ) 
  1291. 	--tint_button is a boolean, used on the radio station select screen 
  1292. 	--tints unhighlighted buttons grey 
  1293. 	self.tint_current_button = tint_button 
  1294. end 
  1295.  
  1296. function Vdo_grid_list:set_input_tracker(input_tracker) 
  1297. 	self.store_input_tracker = input_tracker 
  1298. end 
  1299.