./cell_playlist.lua

  1. local	CELL_PLAYLIST_GET_STATIONS = 0 
  2. local CELL_PLAYLIST_GET_SONGS 	= 1 
  3.  
  4. local STATION_ID_KRUU = 1 
  5. local STATION_ID_MAX	 = 2 
  6. local STATION_ID_DEAD = 3 
  7.  
  8. local Station_data = {} 
  9. local Playlist_data = {} 
  10.  
  11. List_left = -1 
  12. List_right = -1 
  13. List_active = -1 
  14.  
  15. local List_data_stations = { 
  16. 	[1] = { 
  17. 		id = STATION_ID_KRUU, 
  18. 		type = TYPE_BUTTON, 
  19. 		label = "KRUU 107.1", 
  20. 	}, 
  21. 	[2] = { 
  22. 		id = STATION_ID_MAX, 
  23. 		type = TYPE_BUTTON, 
  24. 		label = "MAX 97.5", 
  25. 	}, 
  26. 	[3] = { 
  27. 		id = STATION_ID_DEAD, 
  28. 		type = TYPE_BUTTON, 
  29. 		label = "DEADBOMB 89.1", 
  30. 	}, 
  31. } 
  32. local List_data_tracklist = {}  
  33.  
  34. local List_data_left = {}  
  35. local List_data_right = {} 
  36. local List_data_current_station = -1 
  37.  
  38. local List_data_left_is_empty 
  39. local List_data_right_is_empty 
  40.  
  41. local LIST_FOCUS_LEFT 	= 1 
  42. local LIST_FOCUS_RIGHT 	= 2 
  43.  
  44. local LIST_RIGHT_STATE_NAV		= 1 
  45. local LIST_RIGHT_STATE_MOVING = 2 
  46.  
  47. local LIST_LEFT_STATE_STATION = 1 
  48. local LIST_LEFT_STATE_TRACKLIST = 2 
  49.  
  50. local List_right_state  
  51. local List_left_state  
  52.  
  53. local	Artist_name_text_h = -1 
  54. local Track_name_text_h = -1 
  55.  
  56.  
  57. List_data_right[1] = { 
  58. 	id = 20041, 
  59. 	type = TYPE_BUTTON, 
  60. 	label = "NO_", 
  61. 	track_id = 20041, 
  62. } 
  63.  
  64. --Empty playlist default.. 
  65. local List_data_no_playlist = { 
  66. 	[1] = { 
  67. 		id = -1, 
  68. 		type = TYPE_BUTTON, 
  69. 		label = "PLAYLIST_NO_ITEMS", 
  70. 		track_id = -1, 
  71. 	} 
  72. }		 
  73.  
  74. --Empty playlist default.. 
  75. local List_data_no_stationlist = { 
  76. 	[1] = { 
  77. 		id = -1, 
  78. 		type = TYPE_BUTTON, 
  79. 		label = "PLAYLIST_NO_STATION_ITEMS", 
  80. 		track_id = -1, 
  81. 	} 
  82. }		 
  83.  
  84. local Input_tracker_left 
  85. local Input_tracker_right  
  86. local Hint_bar 
  87.  
  88. local Hint_bar_mouse_input_tracker 
  89. local Mouse_input_tracker 
  90.  
  91. local LIST_SIZE = 400 
  92. local LIST_ITEMS = 9 
  93. local LIST_SCALE = .8 
  94. local Cell_playlist_doc_h 
  95.  
  96. ------------------------------------------------------------------------------- 
  97. -- Menu hints... 
  98. -- 
  99. local Station_menu_hints = { 
  100. 	{CTRL_MENU_BUTTON_B, "MENU_BACK"}, 
  101. 	{CTRL_MENU_BUTTON_A, "PLAYLIST_SELECT_STATION"}, 
  102. } 
  103. local Song_menu_hints = { 
  104. 	{CTRL_MENU_BUTTON_B, "MENU_BACK"}, 
  105. 	{CTRL_MENU_BUTTON_A, "PLAYLIST_ADD_TRACK"}, 
  106. } 
  107. local Song_menu_empty_hints = { 
  108. 	{CTRL_MENU_BUTTON_B, "MENU_BACK"}, 
  109. } 
  110. local Playlist_menu_hints = { 
  111. 	{CTRL_MENU_BUTTON_B, "MENU_BACK"}, 
  112. 	{CTRL_MENU_BUTTON_A, "PLAYLIST_MOVE_TRACK"}, 
  113. 	{CTRL_BUTTON_X, "PLAYLIST_REMOVE_TRACK", game_get_key_name(211)}, --"del" 
  114. } 
  115. local Playlist_menu_no_moving_hints = { 
  116. 	{CTRL_MENU_BUTTON_B, "MENU_BACK"}, 
  117. 	{CTRL_BUTTON_X, "PLAYLIST_REMOVE_TRACK", game_get_key_name(211)}, --"del" 
  118. } 
  119.  
  120. local Playlist_menu_move_hints = { 
  121. 	{CTRL_MENU_BUTTON_B, "MENU_BACK"}, 
  122. 	{CTRL_MENU_BUTTON_A, "MENU_TITLE_CONFIRM"} 
  123. } 
  124.  
  125.  
  126. function cell_playlist_init() 
  127. 	local Cell_playlist_doc_h = vint_document_find("cell_playlist") 
  128. 	List_left = Vdo_mega_list:new("plist_left", 0, Cell_playlist_doc_h, "cell_playlist.lua", "List_left") 
  129. 	List_right = Vdo_mega_list:new("plist_right", 0, Cell_playlist_doc_h, "cell_playlist.lua", "List_right") 
  130. 	 
  131. 	--set colors for mixtape list... 
  132. 	List_left:set_highlight_color(COLOR_CHEATS_PRIMARY, COLOR_CHEATS_SECONDARY)	 
  133. 	List_right:set_highlight_color(COLOR_CHEATS_PRIMARY, COLOR_CHEATS_SECONDARY)	 
  134. 	 
  135. 	--Set up title 
  136. 	local cell_title_h = Vdo_cell_title:new("cell_title", 0, Cell_playlist_doc_h) 
  137. 	cell_title_h:set_text("PLAYLIST_TITLE_PLAYLIST") 
  138. 	cell_title_h:set_icon("ui_cell_icon_mix") 
  139. 	cell_title_h:play_dots_anim() 
  140. 	 
  141. 	--Datasubscribe and popluate lists... 
  142. 	List_data_stations = { } 
  143. 	List_data_tracklist = { } 
  144. 	vint_dataresponder_request("cell_playlist_populate", "station_populate", 0, CELL_PLAYLIST_GET_STATIONS) 
  145. 	vint_dataresponder_request("cell_playlist_populate", "plist_populate", 0, CELL_PLAYLIST_GET_SONGS) 
  146. 	 
  147. 	--Empty playlist on right... 
  148. 	List_data_right = plist_generate_right() 
  149.  
  150. 	--Copy stations into left side of list... 
  151. 	List_data_left = table_clone(List_data_stations) 
  152. 	List_left_state = LIST_LEFT_STATE_STATION 
  153. 	 
  154. 	List_left:draw_items(List_data_left, 1, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  155. 	List_right:draw_items(List_data_right, 1, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  156. 	-- subscribe to common inputs 
  157. 	Input_tracker_left = Vdo_input_tracker:new() 
  158. 	Input_tracker_left:add_input("pause", "plist_nav_do_nothing", 50) 
  159. 	Input_tracker_left:add_input("map", "plist_nav_exit", 50) 
  160. 	Input_tracker_left:add_input("select", "plist_left_nav", 50) 
  161. 	Input_tracker_left:add_input("alt_select", "plist_left_nav", 50) 
  162. 	Input_tracker_left:add_input("back", "plist_left_nav", 50)	 
  163. 	Input_tracker_left:add_input("nav_up", "plist_left_nav", 50) 
  164. 	Input_tracker_left:add_input("nav_down", "plist_left_nav", 50) 
  165. 	Input_tracker_left:add_input("nav_left", "plist_left_nav", 50) 
  166. 	Input_tracker_left:add_input("nav_right", "plist_left_nav", 50) 
  167. 	Input_tracker_left:subscribe(false) 
  168. 	 
  169. 	Input_tracker_right = Vdo_input_tracker:new() 
  170. 	Input_tracker_right:add_input("pause", "plist_nav_do_nothing", 50) 
  171. 	Input_tracker_right:add_input("map", "plist_nav_exit", 50) 
  172. 	Input_tracker_right:add_input("select", "plist_right_nav", 50) 
  173. 	if game_get_platform() == "PC" then 
  174. 		Input_tracker_right:add_input("scancode", "plist_right_nav", 50, false, 211) --'del' key 
  175. 		Input_tracker_right:add_input("gamepad_x", "plist_right_nav", 50) 
  176. 	else 
  177. 		Input_tracker_right:add_input("alt_select", "plist_right_nav", 50)  
  178. 	end 
  179. 	Input_tracker_right:add_input("back", "plist_right_nav", 50)	 
  180. 	Input_tracker_right:add_input("nav_up", "plist_right_nav", 50) 
  181. 	Input_tracker_right:add_input("nav_down", "plist_right_nav", 50) 
  182. 	Input_tracker_right:add_input("nav_left", "plist_right_nav", 50) 
  183. 	Input_tracker_right:add_input("nav_right", "plist_right_nav", 50) 
  184. 	Input_tracker_right:subscribe(false) 
  185. 	 
  186. 	List_active = LIST_FOCUS_LEFT 
  187. 	List_left:toggle_highlight(true) 
  188. 	List_right:toggle_highlight(false) 
  189. 	List_right_state = LIST_RIGHT_STATE_NAV 
  190. 	 
  191. 	--Setup Button Hints 
  192. 	Hint_bar = Vdo_hint_bar:new("playlist_hints", 0, Cell_playlist_doc_h) 
  193. 	Hint_bar:set_hints(Station_menu_hints)  
  194. 	Hint_bar:set_visible(true)	 
  195.  
  196. 	Artist_name_text_h = vint_object_find("label_1_txt") 
  197. 	Track_name_text_h = vint_object_find("label_2_txt") 
  198. 	 
  199. 	plist_set_track_artist(nil) 
  200. 	 
  201. 	--Transition the screen in... 
  202. 	cell_transition_screen(CELL_STATE_LANDSCAPE, CELL_SCREEN_PLAYLIST, CELL_SCREEN_MUSIC_SUB, cell_playlist_gained_focus) 
  203. 	 
  204. 	if game_get_platform() == "PC" then 
  205. 		Hint_bar:set_highlight(0) 
  206. 		 
  207. 		Hint_bar_mouse_input_tracker = Vdo_input_tracker:new() 
  208. 		Hint_bar:add_mouse_inputs("cell_playlist", Hint_bar_mouse_input_tracker) 
  209. 		Hint_bar_mouse_input_tracker:subscribe(true) 
  210. 		 
  211. 		Mouse_input_tracker = Vdo_input_tracker:new() 
  212. 		List_left:add_mouse_inputs("cell_playlist", Mouse_input_tracker) 
  213. 		Mouse_input_tracker:subscribe(true) 
  214. 	end 
  215. 	 
  216. 	--glitch 
  217. 	glitch_cell() 
  218. end 
  219.  
  220. function station_populate(station_name, station_id) 
  221. 	local index = #List_data_stations + 1 
  222. 	List_data_stations[index] = { label = station_name, id = station_id, type = TYPE_BUTTON	} 
  223. end 
  224.  
  225. function get_station_index_from_id(station_id)  
  226. 	for i = 1, #List_data_stations do 
  227. 		if List_data_stations[i].id == station_id then 
  228. 			return i 
  229. 		end 
  230. 	end 
  231. end 
  232.  
  233. function plist_populate(artist, track, track_id, station_id, playlist_index) 
  234. 	local index = #Playlist_data + 1 
  235. 	Playlist_data[index] = { 
  236. 		artist = artist, 
  237. 		track = track, 
  238. 		track_id = track_id, 
  239. 		station_id = station_id, 
  240. 		station_index = get_station_index_from_id(station_id), 
  241. 		playlist_index = playlist_index, 
  242. 		internal_id = index, 
  243. 	} 
  244. end 
  245.  
  246. function plist_generate_right() 
  247. 	local num_items = #Playlist_data 
  248. 	local item  
  249. 	local playlist_items = {} 
  250. 	local num_playlist_items = 0 
  251. 	--loop through items and see which ones are in the playlist... 
  252. 	for i = 1, num_items do 
  253. 		item = Playlist_data[i] 
  254. 		if item.playlist_index ~= -1 then 
  255. 			--its in the playlist... save it off... 
  256. 			num_playlist_items = #playlist_items + 1 
  257. 			playlist_items[num_playlist_items] = item 
  258. 		end 
  259. 	end 
  260.  
  261. 	--now we have a list of playlist items... 
  262. 	if num_playlist_items > 0 then 
  263. 		--we need to bubble sort them for the playlist order... 
  264. 		local temp_item_storage 
  265. 		local flag = false 
  266. 		while flag == false do 
  267. 			flag = true 
  268. 			for i = 1, num_playlist_items - 1 do 
  269. 				if playlist_items[i].playlist_index > playlist_items[i + 1].playlist_index then 
  270. 					--swap indexes if the priority is greater 
  271. 					temp_item_storage = table_clone(playlist_items[i]) 
  272. 					playlist_items[i] = table_clone(playlist_items[i + 1]) 
  273. 					playlist_items[i + 1] = temp_item_storage   
  274. 					flag = false 
  275. 					break 
  276. 				end 
  277. 			end 
  278. 		end 
  279. 		 
  280. 		--sort the data into  
  281. 		local data = {} 
  282. 		 
  283. 		for i = 1, num_playlist_items do 
  284. 			data[i] = { 
  285. 				type = TYPE_BUTTON, 
  286. 				label = playlist_items[i].artist .. " - " .. playlist_items[i].track, 
  287. 				internal_id = playlist_items[i].internal_id 
  288. 			} 
  289. 		end 
  290. 		 
  291. 		List_data_right_is_empty = false 
  292. 		return data 
  293. 	else 
  294. 		--no items pass back empty list... 
  295. 		List_data_right_is_empty = true 
  296. 		return List_data_no_playlist 
  297. 	end 
  298. 	 
  299. 	--[[ DEBUG 
  300. 	for i = 1, num_playlist_items do 
  301. 		local artist = playlist_items[i].artist 
  302. 		local playlist_index = playlist_items[i].playlist_index 
  303. 		debug_print("vint", "playlist_index: " .. var_to_string(playlist_index) .. "artist: " .. var_to_string(artist) .. " : " .. i .. "\n") 
  304. 	end 
  305. 	]] 
  306. end 
  307.  
  308. function plist_generate_station_tracks(station_id) 
  309. 	local num_items = #Playlist_data 
  310. 	local item  
  311. 	local station_items = {} 
  312. 	local num_station_items 
  313. 	--loop through items and see which ones are in the station... 
  314. 	for i = 1, num_items do 
  315. 		item = Playlist_data[i] 
  316. 		if item.station_id == station_id and item.playlist_index == -1 then 
  317. 			--its in the station... save it off... 
  318. 			num_station_items = #station_items + 1 
  319. 			station_items[num_station_items] = item 
  320. 		end 
  321. 	end 
  322.  
  323. 	if #station_items == 0 then 
  324. 		--no items... 
  325. 		return station_items 
  326. 	end 
  327. 	 
  328. 	--we need to bubble sort them for the playlist order... 
  329. 	local temp_item_storage 
  330. 	local flag = false 
  331. 	while flag == false do 
  332. 		flag = true 
  333. 		for i = 1, num_station_items - 1 do 
  334. 			if station_items[i].playlist_index > station_items[i + 1].playlist_index then 
  335. 				--swap indexes if the priority is greater 
  336. 				temp_item_storage = table_clone(station_items[i]) 
  337. 				station_items[i] = table_clone(station_items[i + 1]) 
  338. 				station_items[i + 1] = temp_item_storage   
  339. 				flag = false 
  340. 				break 
  341. 			end 
  342. 		end 
  343. 	end 
  344. 	 
  345. 	 
  346. 	--format into list data... 
  347. 	local list_data = {} 
  348. 	for i = 1, num_station_items do 
  349. 		list_data[i] = { 
  350. 			type = TYPE_BUTTON, 
  351. 			label = station_items[i].artist .. " - " .. station_items[i].track, 
  352. 			internal_id = station_items[i].internal_id 
  353. 		} 
  354. 	end 
  355. 	 
  356. 	return list_data 
  357. end 
  358.  
  359. --Adds an item to the end of a list... 
  360. function plist_song_list_add(internal_id) 
  361.  
  362. 	--make sure this list isn't empty... 
  363. 	if List_data_right_is_empty then 
  364. 		--if its empty lets actually make it empty.. 
  365. 		List_data_right = {} 
  366. 		List_data_right_is_empty = false 
  367. 	end 
  368. 	 
  369. 	--get next playlist index... 
  370. 	local playlist_index = #List_data_right + 1 
  371. 	 
  372. 	local item = Playlist_data[internal_id] 
  373. 	--Give the internal copy a new playlist index... 
  374. 	item.playlist_index = playlist_index 
  375. 	 
  376. 	List_data_right[playlist_index] = 	{ 
  377. 		type = TYPE_BUTTON, 
  378. 		label = item.artist .. " - " .. item.track, 
  379. 		internal_id = internal_id, 
  380. 	} 
  381. 	ui_audio_post_event("ui_radio_toggle_on") 
  382. end 
  383.  
  384. ----------------------------------------- 
  385. -- Removes a specific item in the list... 
  386. ----------------------------------------- 
  387. function plist_song_list_remove_item(list, index) 
  388.  
  389. 	--get the number of items in list... 
  390. 	local num_items = #list 
  391. 	 
  392. 	-- remove item in list... 
  393. 	local list_item = table_clone(list[index]) 
  394. 	list[index] = nil 
  395. 	 
  396. 	--Remove this item from playlist internal data it should end up back on the left list... 
  397. 	local internal_id = list_item.internal_id 
  398. 	local item = Playlist_data[internal_id] 
  399. 		 
  400. 	if item ~= nil then 
  401. 		--Give the internal copy a new playlist index... 
  402. 		item.playlist_index = -1 
  403. 		 
  404. 		--slide everthing beyond that item in the list back one... 
  405. 		for loop_index = index, num_items do 
  406. 			--table clone next item 
  407. 			list[loop_index] = table_clone(list[loop_index+1]) 
  408. 		end 
  409. 	end 
  410. 	 
  411. 	--delete last item in list... 
  412. 	list[num_items] = nil 
  413.  
  414. 	return list_item 
  415. end 
  416.  
  417. ---------------------------------------------------------------------------------- 
  418. -- Inserts an item in the list at specific index. 
  419. -- 
  420. -- @param	list 			table to modify... 
  421. -- @param	list_item 	item to insert 
  422. -- @param	index 		index at when to insert... 
  423. ---------------------------------------------------------------------------------- 
  424. function plist_song_list_insert_item(list, list_item, index) 
  425. 	local num_items = (#list) 
  426.  
  427. 	--slide everthing forward that item in the list back one... 
  428. 	for loop_index = num_items, index, -1 do 
  429. 		--table each item into slot above... 
  430. 		local next_item = loop_index + 1 
  431. 		list[next_item] = table_clone(list[loop_index]) 
  432. 		 
  433. 		--Remove this item from playlist internal data it should end up back on the left list... 
  434. 		local internal_id = list[next_item].internal_id 
  435. 		local item = Playlist_data[internal_id] 
  436. 	 
  437. 		--Give the internal copy a new playlist index... 
  438. 		item.playlist_index = next_item 
  439. 	end 
  440. 	 
  441. 	local item = Playlist_data[list_item.internal_id] 
  442.  
  443. 	--Give the internal copy a new playlist index... 
  444. 	item.playlist_index = index 
  445. 	 
  446. 	-- items all shifted... now insert our items want.. 
  447. 	list[index] = list_item 
  448. 	 
  449. 	if List_right_state == LIST_RIGHT_STATE_NAV then  
  450. 		game_UI_audio_play("UI_Reward_Store_Menu_Navigation") 
  451. 	end 
  452. end 
  453.  
  454. ------------------------------------------------------------------------------- 
  455. -- Play list left nav... 
  456. ------------------------------------------------------------------------------- 
  457. function plist_left_nav(event) 
  458. 	if event == "select" then 
  459. 		if List_left:list_is_playing() == false then 
  460. 			if List_left_state == LIST_LEFT_STATE_STATION then 
  461. 				--Navigate to song menu... need to build it... 
  462. 				--Get current station id... and generate the station tracks... 
  463. 				local station_id = List_left:get_id() 
  464. 				List_data_current_station = station_id 
  465. 				List_data_left = plist_generate_station_tracks(station_id) 
  466. 				 
  467. 				if #List_data_left == 0 then 
  468. 					List_data_left = List_data_no_stationlist 
  469. 					List_data_left_is_empty = true 
  470. 				else  
  471. 					List_data_left_is_empty = false 
  472. 				end 
  473. 				 
  474. 				--Populate items in left list... 
  475. 				List_left:draw_items(List_data_left, 1, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  476. 				 
  477. 				List_left_state = LIST_LEFT_STATE_TRACKLIST 
  478. 				 
  479. 				cell_playlist_update_mouse_inputs(true, false)		 
  480. 			else 
  481. 				if List_data_left_is_empty == true then 
  482. 					-- cannot add from an empty list... 
  483. 					return 
  484. 				end 
  485. 				--Move from track list to playlist... 
  486. 				--get track info... 
  487. 				local list_item = List_left:return_selected_data() 
  488. 				local left_index = List_left:get_selection() 
  489. 				local internal_id = list_item.internal_id 
  490.  
  491. 				--TODO: Make sure we havn't removed all the items so we can select the right index... 
  492. 				plist_song_list_remove_item(List_data_left, left_index) 
  493. 				 
  494. 				--Add item to list on right... 
  495. 				plist_song_list_add(internal_id) 
  496. 				 
  497. 				List_right:draw_items(List_data_right, #List_data_right, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  498. 				List_right:toggle_highlight(false) 
  499. 				 
  500. 				if #List_data_left == 0 then 
  501. 					List_data_left = List_data_no_stationlist 
  502. 					List_data_left_is_empty = true 
  503. 				end 
  504. 				 
  505. 				List_left:draw_items(List_data_left, left_index, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  506. 			 
  507. 				cell_playlist_update_mouse_inputs(true, false) 
  508. 			end	 
  509. 		end 
  510. 	elseif event == "back" then 
  511. 		if List_left_state == LIST_LEFT_STATE_TRACKLIST then 
  512. 			if List_left:list_is_playing() == false then 
  513. 				List_data_left = table_clone(List_data_stations) 
  514. 				 
  515. 				local selected_index = get_station_index_from_id(List_data_current_station) 
  516. 				 
  517. 				--Populate items in left list... 
  518. 				List_left:draw_items(List_data_left, selected_index, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  519. 				List_left_state = LIST_LEFT_STATE_STATION 
  520. 				 
  521. 				List_data_current_station = -1 
  522. 				--Update hints 
  523. 				Hint_bar:set_hints(Station_menu_hints) 
  524. 				cell_playlist_update_mouse_inputs(false, true) 
  525. 			end 
  526. 		else 
  527. 			--nav out of menu 
  528. 			cell_playlist_exit() 
  529. 		end 
  530. 	elseif event == "alt_select" then 
  531. 		--do nothing... 
  532. 		return 
  533. 	elseif event == "nav_up" then 
  534. 		if #List_data_left == 1 then 
  535. 			-- don't nav if we only have one item in list... 
  536. 			return 
  537. 		end 
  538. 		List_left:move_cursor(-1) 
  539. 	elseif event == "nav_down" then 
  540. 		if #List_data_left == 1 then 
  541. 			-- don't nav if we only have one item in list... 
  542. 			return 
  543. 		end 
  544. 		List_left:move_cursor(1) 
  545. 	elseif event == "nav_left" or event == "nav_right" then 
  546. 		if List_data_right_is_empty ~= true then 
  547. 			if List_left:list_is_playing() == false then 
  548. 				--only nav right if our playlist is full... 
  549. 				plist_nav_swap() 
  550. 			 
  551. 				--Reset hints because we exit early... 
  552. 				plist_set_hint_and_button_states() 
  553. 			end 
  554. 		end 
  555. 		return 
  556. 	end 
  557. 	 
  558. 	if List_left_state == LIST_LEFT_STATE_TRACKLIST then 
  559. 		plist_set_track_artist(List_left:return_selected_data()) 
  560. 	else 
  561. 		plist_set_track_artist(nil) 
  562. 	end 
  563. 	 
  564. 	--Set button states after any events... 
  565. 	plist_set_hint_and_button_states() 
  566. end 
  567.  
  568. local swap_index = 1 
  569. ------------------------------------------------------------------------------- 
  570. -- Play list right nav... 
  571. ------------------------------------------------------------------------------- 
  572. function plist_right_nav(event) 
  573. 	if event == "select" then 
  574. 		if List_right:list_is_playing() == false then 
  575. 			--Moving track functionality only works if we have 2 or more items. 
  576. 			if #List_data_right > 1 then 
  577. 				 
  578. 				-- Turn into movable item... 
  579. 				if List_right_state == LIST_RIGHT_STATE_NAV then 
  580. 					--change to moving state... 
  581. 					List_right_state = LIST_RIGHT_STATE_MOVING 
  582. 					 
  583. 					-- Remove and reinsert the item as new/flashing 
  584. 					local current_selection = List_right:get_selection() 
  585. 					swap_index = current_selection 
  586. 					local list_item = plist_song_list_remove_item(List_data_right, current_selection) 
  587. 					list_item.is_new = true 
  588. 					plist_song_list_insert_item(List_data_right, list_item, current_selection) 
  589. 					List_right:draw_items(List_data_right, current_selection, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  590. 				 
  591. 				elseif List_right_state == LIST_RIGHT_STATE_MOVING then 
  592. 					--change to naving state... 
  593. 					List_right_state = LIST_RIGHT_STATE_NAV 
  594. 					 
  595. 					-- Remove and reinsert the swap index into the current selection's spot 
  596. 					local current_selection = List_right:get_selection() 
  597. 					local list_item = plist_song_list_remove_item(List_data_right, swap_index) 
  598. 					list_item.is_new = false 
  599. 					plist_song_list_insert_item(List_data_right, list_item, current_selection) 
  600. 					List_right:draw_items(List_data_right, current_selection, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  601. 				end 
  602. 			end 
  603. 		end 
  604. 	elseif event == "alt_select" or event == "gamepad_x" or event == "scancode" then 
  605. 		if List_right_state == LIST_RIGHT_STATE_MOVING then 
  606. 			--do nothing... 
  607. 			return 
  608. 		end 
  609. 		 
  610. 		if List_right:list_is_playing() == false then 
  611. 			-- Remove Track 
  612. 			--swap items... 
  613. 			local current_selection = List_right:get_selection() 
  614. 			local list_item = plist_song_list_remove_item(List_data_right, current_selection) 
  615. 			 
  616. 			if List_data_current_station ~= -1 then 
  617. 				List_data_left = plist_generate_station_tracks(List_data_current_station) 
  618. 				 
  619. 				if #List_data_left == 0 then 
  620. 					List_data_left = List_data_no_stationlist 
  621. 					List_data_left_is_empty = true 
  622. 				else  
  623. 					List_data_left_is_empty = false 
  624. 				end 
  625. 			end 
  626. 			local left_selection = List_left:get_selection() 
  627. 			--Populate items in left list... 
  628. 			List_left:draw_items(List_data_left, left_selection, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  629. 			List_left:toggle_highlight(false)	--hide highlight after redraw. 
  630. 			 
  631. 			-- check if new playlist isn't empty. 
  632. 			if #List_data_right == 0 then 
  633. 				List_data_right = table_clone(List_data_no_playlist) 
  634. 				List_data_right_is_empty = true 
  635. 			end 
  636. 			 
  637. 			List_right:draw_items(List_data_right, current_selection, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  638. 			ui_audio_post_event("ui_radio_toggle_off") 
  639. 			if List_data_right_is_empty then 
  640. 				--nav back left... 
  641. 				plist_nav_swap() 
  642. 				plist_set_hint_and_button_states() 
  643. 				 
  644. 				cell_playlist_update_mouse_inputs(true, false) 
  645. 				return 
  646. 			end 
  647. 			 
  648. 		end		 
  649. 	elseif event == "back" then 
  650. 		if List_right:list_is_playing() == false and List_left:list_is_playing() == false then 
  651. 			-- Go back to station select (or exit) 
  652. 			plist_left_nav("back") 
  653. 			plist_set_hint_and_button_states() 
  654. 			 
  655. 			-- Turn off the left highlight (it gets reactivated by redrawing the left list) 
  656. 			List_left:toggle_highlight(false) 
  657. 			return 
  658. 		end 
  659. 	elseif event == "nav_up" then 
  660. 		 
  661. 		if #List_data_right == 1 then 
  662. 			-- don't nav if we only have one item in list... 
  663. 			return 
  664. 		end 
  665. 		 
  666. 		if List_right_state == LIST_RIGHT_STATE_NAV then 
  667. 			List_right:move_cursor(-1) 
  668. 		elseif List_right_state == LIST_RIGHT_STATE_MOVING then 
  669. 			--swap items... 
  670. 			local current_selection = swap_index --List_right:get_selection() 
  671. 			 
  672. 			--insert into previous slot... 
  673. 			local next_slot = current_selection - 1 
  674. 			if next_slot < 1 then 
  675. 				next_slot = #List_data_right 
  676. 			end 
  677. 						 
  678. 			--get track info and remove item from list... 
  679. 			local list_item = plist_song_list_remove_item(List_data_right, current_selection) 
  680. 			 
  681. 			plist_song_list_insert_item(List_data_right, list_item, next_slot) 
  682. 			 
  683. 			List_right:draw_items(List_data_right, current_selection, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  684. 			List_right:move_cursor(-1) 
  685. 			swap_index = next_slot 
  686. 		end 
  687.  
  688. 	elseif event == "nav_down" then 
  689. 		 
  690. 		if #List_data_right == 1 then 
  691. 			-- don't nav if we only have one item in list... 
  692. 			return 
  693. 		end 
  694. 		 
  695. 		if List_right_state == LIST_RIGHT_STATE_NAV then 
  696. 			List_right:move_cursor(1) 
  697. 		elseif List_right_state == LIST_RIGHT_STATE_MOVING then 
  698. 			--swap items... 
  699. 			local current_selection = swap_index --List_right:get_selection() 
  700.  
  701. 			--insert into next slot... 
  702. 			local next_slot = current_selection + 1 
  703. 			if next_slot > #List_data_right then 
  704. 				next_slot = 1 
  705. 			end 
  706. 		 
  707. 			--get track info... 
  708. 			local list_item = plist_song_list_remove_item(List_data_right, current_selection) 
  709. 			 
  710. 			plist_song_list_insert_item(List_data_right, list_item, next_slot) 
  711. 			 
  712. 			List_right:draw_items(List_data_right, current_selection, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  713. 			List_right:move_cursor(1) 
  714. 			swap_index = next_slot 
  715. 		end 
  716. 		 
  717. 	elseif event == "nav_left" or event == "nav_right" then 
  718. 		if List_right:list_is_playing() == false and List_left:list_is_playing() == false then 
  719. 			--Swap nav... 
  720. 			plist_nav_swap() 
  721. 			 
  722. 			--Reset hints because we exit early... 
  723. 			plist_set_hint_and_button_states() 
  724. 			cell_playlist_update_mouse_inputs(false, true) 
  725. 			return 
  726. 		end 
  727. 	end 
  728. 	 
  729. 	if List_right_state == LIST_RIGHT_STATE_NAV then 
  730. 		plist_set_track_artist(List_right:return_selected_data()) 
  731. 	end 
  732. 	 
  733. 		--Set button states after any events... 
  734. 	plist_set_hint_and_button_states() 
  735. 	cell_playlist_update_mouse_inputs(true, true) 
  736. end 
  737.  
  738. ------------------------------------------------------------------------------- 
  739. -- Updates button states depending on what state we are in. 
  740. -- This has to be done because the highlight must be reset when we redraw the lists. 
  741. -- We redraw so often its easiest to do this all in one function. 
  742. -- 
  743. function plist_set_hint_and_button_states() 
  744.  
  745. 	--set titles of menus 
  746. 	local header_left_h = vint_object_find("playlist_header_left") 
  747. 	if List_left_state == LIST_LEFT_STATE_TRACKLIST then 
  748. 		--set title to tracklist 
  749. 		vint_set_property(header_left_h, "text_tag","PLAYLIST_HEADER_TRACKS") 
  750. 	else 
  751. 		--set title to station  
  752. 		vint_set_property(header_left_h, "text_tag","PLAYLIST_HEADER_STATIONS") 
  753. 	end 
  754.  
  755. 	local hint_data = {} 
  756. 	if List_active == LIST_FOCUS_LEFT then 
  757. 		if List_data_left_is_empty and List_left_state == LIST_LEFT_STATE_TRACKLIST then 
  758. 			--Hide button 
  759. 			List_left:highlight_set_button("") 
  760. 			hint_data = Song_menu_empty_hints 
  761. 		else 
  762. 			if List_left_state == LIST_LEFT_STATE_STATION then 
  763. 				--Left Station State 
  764. 				List_left:highlight_set_button(CTRL_MENU_BUTTON_A) 
  765. 				hint_data = Station_menu_hints 
  766. 			elseif List_left_state == LIST_LEFT_STATE_TRACKLIST then 
  767. 				--Left Tracklist State 
  768. 				List_left:highlight_set_button(CTRL_MENU_BUTTON_A) 
  769. 				hint_data = Song_menu_hints 
  770. 			end 
  771. 		end 
  772. 	elseif List_active == LIST_FOCUS_RIGHT then 
  773. 		if List_data_right_is_empty then 
  774. 			--Hide button 
  775. 			List_right:highlight_set_button("") 
  776. 			hint_data = Song_menu_empty_hints 
  777. 		else 
  778. 			if List_right_state == LIST_RIGHT_STATE_MOVING then 
  779. 				--Right Moving state 
  780. 				List_right:highlight_set_button("ui_cell_playlist_up_down", true) 
  781. 				hint_data = Playlist_menu_move_hints 
  782. 			elseif List_right_state == LIST_RIGHT_STATE_NAV then 
  783. 				local list_right_num_items = #List_data_right 
  784. 				if list_right_num_items > 1 then 
  785. 					--Right Nav state and option to move 
  786. 					List_right:highlight_set_button(CTRL_MENU_BUTTON_A) 
  787. 					hint_data = Playlist_menu_hints 
  788. 				else 
  789. 					-- Only one item no moving here... 
  790. 					List_right:highlight_set_button("") 
  791. 					hint_data = Playlist_menu_no_moving_hints 
  792. 				end 
  793. 			end	 
  794. 		end  
  795. 	end 
  796. 	 
  797. 	-- Override the back button label if stations are not visible 
  798. 	if List_left_state ~= LIST_LEFT_STATE_STATION then 
  799. 		hint_data[1] = {CTRL_MENU_BUTTON_B, "PLAYLIST_HEADER_STATIONS"} 
  800. 	else 
  801. 		hint_data[1] = {CTRL_MENU_BUTTON_B, "MENU_BACK"} 
  802. 	end 
  803. 	Hint_bar:set_hints(hint_data) 
  804. 	cell_playlist_update_mouse_inputs(true, true) 
  805. end 
  806.  
  807.  
  808. --Exit all the way out of the menu 
  809. function plist_nav_exit() 
  810. 	cell_playlist_exit(true) 
  811. end 
  812.  
  813. function plist_nav_swap() 
  814. 	-- Make sure the right list doesn't have a highlighted item 
  815. 	if swap_index <= #List_data_right and List_data_right_is_empty == false then 
  816. 		local list_item = plist_song_list_remove_item(List_data_right, swap_index) 
  817. 		if list_item ~= nil then 
  818. 			list_item.is_new = false 
  819. 			plist_song_list_insert_item(List_data_right, list_item, swap_index) 
  820. 			List_right:draw_items(List_data_right, swap_index, LIST_SIZE, LIST_ITEMS,	LIST_SCALE, true, false) 
  821. 		end 
  822. 	end 
  823.  
  824. 	--Move navigator between list 
  825. 	if List_active == LIST_FOCUS_LEFT then 
  826. 		--Switch to right side... 
  827. 		Input_tracker_left:subscribe(false) 
  828. 		Input_tracker_right:subscribe(true) 
  829. 		List_left:toggle_highlight(false) 
  830. 		List_right:toggle_highlight(true) 
  831. 		List_active = LIST_FOCUS_RIGHT 
  832. 	else 
  833. 		--Switch to left side 
  834. 		Input_tracker_left:subscribe(true) 
  835. 		Input_tracker_right:subscribe(false) 
  836. 		List_left:toggle_highlight(true) 
  837. 		List_right:toggle_highlight(false) 
  838. 		List_active = LIST_FOCUS_LEFT 
  839. 	end 
  840. 	 
  841. 	--always reset the state of right side when swapping... 
  842. 	List_right_state = LIST_RIGHT_STATE_NAV 
  843. 	 
  844. 	if List_active == LIST_FOCUS_LEFT then 
  845. 		if List_left_state ~= LIST_LEFT_STATE_TRACKLIST then 
  846. 			plist_set_track_artist(nil) 
  847. 		else 
  848. 			local list_item = List_left:return_selected_data() 
  849. 			plist_set_track_artist(list_item) 
  850. 		end 
  851. 	else 
  852. 		local list_item = List_right:return_selected_data() 
  853. 		plist_set_track_artist(list_item) 
  854. 	end 
  855. end 
  856.  
  857.  
  858. Plist_play_thread = -1 
  859. function plist_set_track_artist(track_info) 
  860. 	 
  861. 	if Plist_play_thread ~= -1 then 
  862. 		thread_kill(Plist_play_thread) 
  863. 		Plist_play_thread = -1 
  864. 	end 
  865. 	if track_info == nil or track_info.internal_id == nil then 
  866. 		vint_set_property(Artist_name_text_h, "visible", false) 
  867. 		vint_set_property(Track_name_text_h, "visible", false) 
  868. 		playlist_stop_track() 
  869. 	else 
  870. 		vint_set_property(Artist_name_text_h, "visible", true) 
  871. 		vint_set_property(Track_name_text_h, "visible", true) 
  872. 		 
  873. 		local item = Playlist_data[track_info.internal_id] 
  874. 		vint_set_property(Artist_name_text_h, "text_tag", item.artist) 
  875. 		vint_set_property(Track_name_text_h, "text_tag", item.track) 
  876. 		 
  877. 		Plist_play_thread = thread_new("plist_play_delayed_track", item.track_id) 
  878. 	end 
  879. end 
  880.  
  881. function plist_play_delayed_track(track_id) 
  882. 	delay(0.5) 
  883. 	playlist_play_track(track_id) 
  884. 	Plist_play_thread = -1 
  885. end 
  886.  
  887. function plist_song_list_clear() 
  888. 	List_data_left = {} 
  889. end 
  890.  
  891. function plist_nav_do_nothing() 
  892. 	--do nothing... 
  893. end 
  894.  
  895.  
  896. function cell_playlist_cleanup() 
  897. 	--Guarantee cleanup of controls. 
  898. 	Input_tracker_left:subscribe(false) 
  899. 	Input_tracker_right:subscribe(false) 
  900. end 
  901.  
  902.  
  903. ------------------------------------------------------------------------------- 
  904. -- Changes highlight button on right list to use arrow or standard (a) button 
  905. ------------------------------------------------------------------------------- 
  906. function cell_playlist_list_right_use_arrow(use_arrow) 
  907. 	if use_arrow then 
  908. 		--Change button on list... 
  909.  
  910. 	else 
  911. 		 
  912. 	end 
  913. end 
  914.  
  915. ------------------------------------------------------------------------------- 
  916. -- Exits the playlist menu... 
  917. -- 
  918. function cell_playlist_exit(exit_to_game) 
  919.  
  920. 	vint_dataresponder_post("cell_menu_state_dr", "Set", ID_MAIN) 
  921. 	--save playlist 
  922. 	cell_playlist_save() 
  923. 	 
  924. 	--Lock controls 
  925. 	cell_playlist_lost_focus() 
  926. 	 
  927. 	--do the right exit... 
  928. 	if exit_to_game == true then 
  929. 		cell_transition_screen(CELL_STATE_OUT, CELL_SCREEN_NONE, CELL_SCREEN_PLAYLIST, cell_playlist_exit_to_game) 
  930. 	else 
  931. 		cell_transition_screen(CELL_STATE_PORTRAIT, CELL_SCREEN_MUSIC_SUB, CELL_SCREEN_PLAYLIST, cell_playlist_exit_to_sub) 
  932. 	end 
  933. end 
  934.  
  935.  
  936. ------------------------------------------------------------------------------- 
  937. -- Final exit to cell music sub 
  938. -- 
  939. function cell_playlist_exit_to_sub() 
  940. 	ui_audio_post_event("UI_Hub_Menu_Back") 
  941. 	pop_screen() --Playlist Editor 
  942. end 
  943.  
  944. ------------------------------------------------------------------------------- 
  945. -- Final exit to game 
  946. -- 
  947. function cell_playlist_exit_to_game() 
  948. 	ui_audio_post_event("UI_Hub_Menu_Back") 
  949. 	pop_screen()	--Playlist Editor 
  950. 	pop_screen()	--music Sub screen 
  951. 	pop_screen()	--main 
  952. 	pop_screen()	--cell frame 
  953. end 
  954.  
  955. function cell_playlist_save() 
  956. 	local Save_list = { } 
  957. 	if List_data_right_is_empty == false then 
  958. 		--if our list isn't empty we can make the savelist... 
  959. 		for i = 1, #List_data_right do 
  960. 			Save_list[i] = Playlist_data[List_data_right[i].internal_id].track_id 
  961. 		end		 
  962. 	end 
  963. 	cell_playlist_save_list(Save_list) 
  964. end 
  965.  
  966. function debug_right_list() 
  967. 	local num_items = #List_data_right 
  968. 	local item  
  969. 	local playlist_items = {} 
  970. 	local num_playlist_items 
  971. 	--loop through items and see which ones are in the playlist... 
  972. 	for i = 1, num_items do 
  973. 		local internal_id = List_data_right[i].internal_id 
  974. 		local artist = Playlist_data[internal_id].artist 
  975. 		local playlist_index = Playlist_data[internal_id].playlist_index 
  976. 		debug_print("vint", "artist: " .. var_to_string(artist) .. " | playlist_index: " .. var_to_string(playlist_index) .. "\n") 
  977. 	end 
  978. end 
  979.  
  980. function cell_playlist_gained_focus() 
  981. 	Input_tracker_left:subscribe(true) 
  982. 	cell_playlist_update_mouse_inputs(true, true) 
  983. end 
  984.  
  985. function cell_playlist_lost_focus() 
  986. 	Input_tracker_left:subscribe(false) 
  987. 	Input_tracker_right:subscribe(false) 
  988. 	if Mouse_input_tracker ~= nil then 
  989. 		Mouse_input_tracker:subscribe(false) 
  990. 		Hint_bar_mouse_input_tracker:subscribe(false) 
  991. 	end 
  992. end 
  993.  
  994. -- Mouse input functions 
  995. -- 
  996.  
  997. function cell_playlist_mouse_right_click(event, target_handle, mouse_x, mouse_y)	 
  998. 	local new_index2 = List_right:get_button_index(target_handle) 
  999. 	if new_index2 ~= 0 then 
  1000. 		plist_right_nav("alt_select") 
  1001. 	end 
  1002. end 
  1003.  
  1004. function cell_playlist_mouse_click(event, target_handle, mouse_x, mouse_y) 
  1005. 	local hint_index = Hint_bar:get_hint_index(target_handle) 
  1006. 	 
  1007. 	-- Hint bar functionality 
  1008. 	if hint_index == 1 then 
  1009. 		if List_active == LIST_FOCUS_RIGHT then 
  1010. 			plist_left_nav("back") 
  1011. 		else 
  1012. 			plist_right_nav("back") 
  1013. 		end 
  1014. 	elseif hint_index == 2 then 
  1015. 		if List_active == LIST_FOCUS_RIGHT then 
  1016. 			if #List_data_right == 1 then 
  1017. 				plist_right_nav("alt_select") 
  1018. 			else 
  1019. 				plist_right_nav("select") 
  1020. 			end 
  1021. 		else 
  1022. 			plist_left_nav("select") 
  1023. 		end 
  1024. 	elseif hint_index == 3 then 
  1025. 		if List_active == LIST_FOCUS_RIGHT then 
  1026. 			plist_right_nav("alt_select") 
  1027. 		else 
  1028. 		end 
  1029. 	end 
  1030.  
  1031. 	local new_index = List_left:get_button_index(target_handle) 
  1032. 	if new_index ~= 0 then 
  1033. 		-- Swap navigation if not already focused on this list 
  1034. 		if List_active == LIST_FOCUS_RIGHT then 
  1035. 			plist_nav_swap() 
  1036. 			plist_set_hint_and_button_states() 
  1037. 		end 
  1038. 		List_left:set_selection(new_index) 
  1039. 		List_left:move_cursor(0, true) 
  1040. 		plist_set_track_artist(List_left:return_selected_data()) 
  1041. 		plist_left_nav("select") 
  1042. 	end 
  1043. 	 
  1044. 	local new_index2 = List_right:get_button_index(target_handle) 
  1045. 	if new_index2 ~= 0 then 
  1046. 		-- Swap navigation if not already focused on this list 
  1047. 		if List_active == LIST_FOCUS_LEFT then 
  1048. 			plist_nav_swap() 
  1049. 			plist_set_hint_and_button_states() 
  1050. 		end 
  1051. 		List_right:set_selection(new_index2) 
  1052. 		List_right:move_cursor(0, true) 
  1053. 		plist_set_track_artist(List_right:return_selected_data()) 
  1054. 		plist_right_nav("select") 
  1055. 	end 
  1056. end 
  1057.  
  1058. function cell_playlist_mouse_move(event, target_handle) 
  1059. 	Hint_bar:set_highlight(0) 
  1060. 	 
  1061. 	local hint_index = Hint_bar:get_hint_index(target_handle) 
  1062. 	if hint_index ~= 0 then 
  1063. 		Hint_bar:set_highlight(hint_index) 
  1064. 	end 
  1065. 	 
  1066. 	local new_index = List_left:get_button_index(target_handle) 
  1067. 	if new_index ~= 0 then 
  1068. 		-- Swap navigation if not already focused on this list 
  1069. 		if List_active == LIST_FOCUS_RIGHT then 
  1070. 			plist_nav_swap() 
  1071. 			plist_set_hint_and_button_states() 
  1072. 		end 
  1073. 		List_left:set_selection(new_index) 
  1074. 		List_left:move_cursor(0, true) 
  1075. 		plist_set_track_artist(List_left:return_selected_data()) 
  1076. 	end 
  1077. 	 
  1078. 	local new_index2 = List_right:get_button_index(target_handle) 
  1079. 	if new_index2 ~= 0 then 
  1080. 		-- Swap navigation if not already focused on this list 
  1081. 		if List_active == LIST_FOCUS_LEFT then 
  1082. 			plist_nav_swap() 
  1083. 			plist_set_hint_and_button_states() 
  1084. 		end 
  1085. 		List_right:set_selection(new_index2) 
  1086. 		List_right:move_cursor(0, true) 
  1087. 		plist_set_track_artist(List_right:return_selected_data()) 
  1088. 		if List_right_state == LIST_RIGHT_STATE_MOVING then 
  1089. 			List_right:highlight_set_button("ui_cell_playlist_up_down", true) 
  1090. 		end 
  1091. 	end 
  1092. end 
  1093.  
  1094. function cell_playlist_mouse_scroll(event, target_handle, mouse_x, mouse_y, scroll_lines) 
  1095. 	if scroll_lines ~= 0 then 
  1096. 		if List_left:get_scroll_region_handle() == target_handle then 
  1097. 			List_left:scroll_list(scroll_lines * -1) 
  1098. 			cell_playlist_update_mouse_inputs(true, false) 
  1099. 		elseif List_right:get_scroll_region_handle() == target_handle then 
  1100. 			List_right:scroll_list(scroll_lines * -1) 
  1101. 			cell_playlist_update_mouse_inputs(true, false) 
  1102. 		end 
  1103. 	end 
  1104. end 
  1105.  
  1106. function cell_playlist_mouse_drag(event, target_handle, mouse_x, mouse_y) 
  1107. 	if List_left.scrollbar.tab_grp.handle == target_handle then 
  1108. 		local new_start_index = List_left.scrollbar:drag_scrolltab(mouse_y, List_left.num_buttons - (List_left.max_buttons - 1)) 
  1109. 		List_left:scroll_list(0, new_start_index) 
  1110. 	elseif List_right.scrollbar.tab_grp.handle == target_handle then 
  1111. 		local new_start_index = List_right.scrollbar:drag_scrolltab(mouse_y, List_right.num_buttons - (List_right.max_buttons - 1)) 
  1112. 		List_right:scroll_list(0, new_start_index) 
  1113. 	end 
  1114. end 
  1115.  
  1116. -- Updates the mouse inputs for the list and snaps the scrolltab to the closest notch based on the visible index 
  1117. -- 
  1118. function cell_playlist_mouse_drag_release(event, target_handle, mouse_x, mouse_y) 
  1119. 	if List_left.scrollbar.tab_grp.handle == target_handle then 
  1120. 		local start_index = List_left:get_visible_indices() 
  1121. 		List_left.scrollbar:release_scrolltab(start_index, List_left.num_buttons - (List_left.max_buttons - 1)) 
  1122. 		cell_playlist_update_mouse_inputs(true, false) 
  1123. 	elseif List_right.scrollbar.tab_grp.handle == target_handle then 
  1124. 		local start_index = List_right:get_visible_indices() 
  1125. 		List_right.scrollbar:release_scrolltab(start_index, List_right.num_buttons - (List_right.max_buttons - 1)) 
  1126. 		cell_playlist_update_mouse_inputs(true, false) 
  1127. 	end 
  1128. end 
  1129.  
  1130. function cell_playlist_update_mouse_inputs(update_list, update_hint_bar) 
  1131. 	if Mouse_input_tracker ~= nil then 
  1132. 		if update_list == true then 
  1133. 			-- Remove and add the inputs to both lists (if possible) 
  1134. 			Mouse_input_tracker:remove_all() 
  1135. 			if List_data_left_is_empty == false or List_left_state == LIST_LEFT_STATE_STATION then 
  1136. 				List_left:add_mouse_inputs("cell_playlist", Mouse_input_tracker) 
  1137. 			end 
  1138. 			if List_data_right_is_empty == false then 
  1139. 				List_right:add_mouse_inputs("cell_playlist", Mouse_input_tracker, 0, nil, nil, 0, true) 
  1140. 			end 
  1141. 			Mouse_input_tracker:subscribe(true) 
  1142. 		end 
  1143. 		if update_hint_bar == true then 
  1144. 			-- Remove and add the inputs to the hintbar 
  1145. 			Hint_bar_mouse_input_tracker:remove_all() 
  1146. 			Hint_bar:add_mouse_inputs("cell_playlist", Hint_bar_mouse_input_tracker) 
  1147. 			Hint_bar_mouse_input_tracker:subscribe(true) 
  1148. 		end 
  1149. 	end 
  1150. end