./vdo_hint_bar.lua

  1. local TEXT_SCALE_NORMAL 	= 0.8		--Text size for mini hintbar 
  2. local TEXT_SCALE_MINI 		= 0.7		--Text size for mini hintbar 
  3. local BUTTON_SCALE_NORMAL 	= 1.0		--Button size for mini hintbar 
  4. local BUTTON_SCALE_MINI 	= 0.8		--Button size for mini hintbar 
  5.  
  6. local HINT_PADDING_NORMAL 	= 5				--Spacing between button and text 
  7. local HINT_SPACING_NORMAL 	= 30				--Spacing between each button and text 
  8.  
  9. local HINT_PADDING_MINI 	= 0 				--Spacing between button and text 
  10. local HINT_SPACING_MINI		= 25				--Spacing between each button and text 
  11.  
  12. local COLOR_UNHIGHLIGHT_TEXT = {R=160/255,G=160/255,B=160/255} 
  13.  
  14. Vdo_hint_bar_objects = { } 
  15. local Vdo_hint_bar_gamepad_listener = -1 
  16.  
  17. function vdo_hint_bar_init() 
  18. 	local h = vint_object_find("button") 
  19. 	vint_set_property(h, "visible", false) 
  20. 	h = vint_object_find("hint_text") 
  21. 	vint_set_property(h, "visible", false) 
  22. 	 
  23. 	Vdo_hint_bar_gamepad_listener = vint_scriptevent_listen( "gamepad_active", "vdo_hint_bar_update_gamepad_state" ) 
  24. end 
  25.  
  26. function vdo_hint_bar_cleanup() 
  27. 	vint_scriptevent_stop_listening( Vdo_hint_bar_gamepad_listener ) 
  28. end 
  29.  
  30. -- Inherited from Vdo_base_object 
  31. Vdo_hint_bar = Vdo_base_object:new_base() 
  32.  
  33. function Vdo_hint_bar:init() 
  34. 	if self.is_initialized == nil then 
  35. 		self.hint_objects = {} 
  36. 		 
  37. 		--Defaults for int spacing 
  38. 		self.hint_padding = HINT_PADDING_NORMAL	--Spacing between button and text 
  39. 		self.hint_spacing = HINT_SPACING_NORMAL	--Spacing between each button and text 
  40.  
  41. 		self.hint_objects[1] = { 
  42. 			button = Vdo_hint_button:new("button", self.handle, self.doc_handle), 
  43. 			text = Vdo_base_object:new("hint_text", self.handle, self.doc_handle), 
  44. 		} 
  45. 		self.hint_objects.num = 1 
  46. 		self.hint_data = 0 
  47. 		self.height = 0 
  48. 		self.width = 0 
  49. 		 
  50. 		--to store the buttons that we cloned and pulsed 
  51. 		self.pulse_buttons = {}		 
  52. 	end 
  53. 	self.hint_data = 0 
  54. 	--Make sure we clear our old hints out  
  55. 	self:set_hints() 
  56. 	self.is_initialized = true 
  57. 	 
  58. 	self.input_tracker = nil 
  59. 	 
  60. 	-- We only need to store off the hint bar if we are running pc so we can change icons when gamepad updates 
  61. 	if game_get_platform() == "PC" then 
  62. 		for k,v in pairs( Vdo_hint_bar_objects ) do 
  63. 			-- Check if there are any unloaded docs that were using hint_bars and clear them 
  64. 			if vint_object_exists( v.hint_objects[1].text.handle ) == false then 
  65. 				Vdo_hint_bar_objects[k] = nil 
  66. 			end 
  67. 		end 
  68. 	 
  69. 		Vdo_hint_bar_objects[ #Vdo_hint_bar_objects + 1 ] = self 
  70. 	end 
  71. 	 
  72. end 
  73.  
  74. function Vdo_hint_bar:cleanup() 
  75.  
  76. 	for k,v in pairs( Vdo_hint_bar_objects ) do 
  77. 		if v == self or vint_object_exists( v.hint_objects[1].text.handle ) == false then 
  78. 			Vdo_hint_bar_objects[ k ] = nil 
  79. 		end 
  80. 	end 
  81. 	 
  82. 	if( self.hint_objects ~= nil ) then 
  83. 		--Remove old buttons and clear out stored objects 
  84. 		for i = 2, self.hint_objects.num do 
  85. 			self.hint_objects[i].button:object_destroy() 
  86. 			self.hint_objects[i].text:object_destroy() 
  87. 			self.hint_objects[i] = nil 
  88. 		end 
  89. 	end 
  90. 	 
  91. 	self.hint_data = nil 
  92. end 
  93.  
  94. --Sets hints of hint object 
  95. -- Example of hint_data object param 
  96. --[[ 
  97. 	hint_data = { 
  98. 		{CTRL_MENU_BUTTON_B, "BACK"}, 
  99. 		{CTRL_BUTTON_X, "SAVE GAME"}, 
  100. 		{CTRL_BUTTON_Y, "EAT DONG"}, 
  101. 	} 
  102. ]] 
  103. function Vdo_hint_bar:set_hints(hint_data, force_gamepad_icons, force_kbd_icons, force_scale) 
  104.  
  105. 	self.hint_data = hint_data 
  106. 	 
  107. 	self.hint_objects[1].button:set_visible(true) 
  108. 	self.hint_objects[1].text:set_visible(true)  
  109. 	 
  110. 	--Only reset the scale if we are not doing a rebuild... 
  111. 	local do_force_scale = false 
  112. 	if force_scale == nil then 
  113. 		do_force_scale = true 
  114. 		force_scale = 1.0 
  115. 	end 
  116. 	 
  117. 	--reset force_scale... 
  118. 	self.hint_objects[1].text:set_property("scale", force_scale, 1.0) 
  119. 	 
  120. 	self:clear_mouse_input_subs() 
  121. 	 
  122. 	--Remove old buttons and clear out stored objects 
  123. 	for i = 2, self.hint_objects.num do 
  124. 		self.hint_objects[i].button:object_destroy() 
  125. 		self.hint_objects[i].text:object_destroy() 
  126. 		self.hint_objects[i] = nil 
  127. 	end 
  128. 	 
  129. 	self.hint_objects.num = 0 
  130. 	local button_width_total = 0 
  131. 	if hint_data == nil or hint_data ==  false then 
  132. 		self.hint_objects[1].button:set_visible(false) 
  133. 		self.hint_objects[1].text:set_visible(false)  
  134. 	else 
  135.  
  136. 		local hint_data_count = #hint_data 
  137. 		 
  138. 		local button, text, text_old 
  139. 		local text_width, text_height, text_x, text_y 
  140. 		local button_width, button_height, button_x, button_y 
  141. 		local button_x_new, text_x_new 
  142. 		local def_button_width 
  143. 		local x_start = 0 
  144. 		 
  145. 		--Create new buttons and set 
  146. 		 
  147. 		for i = 1, hint_data_count do 
  148. 			if i == 1 then 
  149. 				--First button in menu... (no clones) 
  150. 				button = self.hint_objects[1].button 
  151. 				text = self.hint_objects[1].text 
  152. 			else 
  153. 				--Clone Objects from original 
  154. 				button = Vdo_hint_button:clone(self.hint_objects[1].button.handle, self.handle) 
  155. 				text = Vdo_base_object:clone(self.hint_objects[1].text.handle, self.handle) 
  156. 			end	 
  157. 			 
  158. 			--Set Text and Button Image			 
  159. 			local btn_img_string = hint_data[i][1] 
  160. 			local btn_pc_key_text = hint_data[i][3] 
  161. 			local btn_text_string = hint_data[i][2] 
  162. 			button:set_button(btn_img_string, btn_pc_key_text, force_gamepad_icons, force_kbd_icons) 
  163. 			text:set_text(btn_text_string) 
  164. 			 
  165. 			-- Save the button width to make it easier to offset the buttons based on their size 
  166. 			local button_offset 
  167. 			if i == 1 then 
  168. 				--First button... we process differently. 
  169. 				text_x, text_y = text:get_anchor() 
  170. 				 
  171. 				-- Only get the default width from the first button, though this might change later to be hardcoded (30 is the current width of a button image) 
  172. 				def_button_width = button:get_default_width() 
  173. 				button_x, button_y = button:get_anchor() 
  174. 				button_width, button_height = button:get_size() 
  175. 				button_offset = (button_width - def_button_width) / 2 
  176. 				button_x_new = button_offset 
  177. 				 
  178. 				x_start = button_width * 0.5 
  179. 				 
  180. 				--text position is the sum of button position, half the width fo the button and a hint padding value. 
  181. 				text_x_new = button_x_new + (button_width / 2 ) + self.hint_padding 
  182. 				button_width_total = button_width_total + (button_width) + self.hint_padding 
  183. 			else 
  184. 				--Reposition and align based on previous button 
  185. 				text_old = self.hint_objects[i - 1].text 
  186. 				text_width, text_height = text_old:get_actual_size() 
  187. 				text_x, text_y = text_old:get_anchor() 
  188. 				 
  189. 				button_x, button_y = button:get_anchor() 
  190. 				button_width, button_height = button:get_size() 
  191. 				button_offset = (button_width - def_button_width) / 2 
  192. 				button_x_new = button_offset + text_x + text_width + self.hint_spacing 
  193. 				 
  194. 				--text position is the sum of button position, half the width fo the button and a hint padding value. 
  195. 				text_x_new = button_x_new + (button_width / 2 ) + self.hint_padding 
  196. 				button_width_total = button_width_total + (button_width * .5) + self.hint_spacing 
  197. 			end 
  198. 			 
  199. 			button:set_anchor(button_x_new, button_y) 
  200. 			text:set_anchor(text_x_new, text_y) 
  201. 			 
  202. 			--Store into global for processing / cleanup 
  203. 			self.hint_objects[i] = {} 
  204. 			self.hint_objects[i].button = button 
  205. 			self.hint_objects[i].text = text 
  206. 			self.hint_objects.num = self.hint_objects.num + 1 
  207. 		end 
  208. 		 
  209. 		 
  210. 		--Calculate width and height of hint bar by checking the position and width of the last text field... 
  211. 		local text_h = self.hint_objects[self.hint_objects.num].text.handle 
  212. 		local width, height = element_get_actual_size(text_h) 
  213. 		local x, y = vint_get_property(text_h, "anchor") 
  214. 		 
  215. 		width = width + x  
  216. 		 
  217. 		self.height = button_height 
  218. 		self.width = width 
  219. 		self.hint_data = hint_data 
  220. 		 
  221. 		--Re-enable text shadow... 
  222. 		if self.shadow_enabled then 
  223. 			self:enable_text_shadow(self.shadow_enabled) 
  224. 		end 
  225. 		 
  226. 		if self.width_max ~= nil and do_force_scale == true then 
  227. 			local test_width = self.width 
  228. 			--button_width =  
  229. 			if test_width > self.width_max then 
  230. 				 -- Add extra padding to our button widths... 
  231. 				button_width_total = button_width_total + 20 
  232. 				 
  233. 				--scale text 
  234. 				local new_scale = (self.width_max - button_width_total )/(test_width - button_width_total) 
  235. 				--Reset our hints with the new scale. 
  236. 				self:set_hints(hint_data, force_gamepad_icons, force_kbd_icons, new_scale) 
  237. 			end 
  238. 		end 
  239. 	end 
  240. 	 
  241. 	self:add_mouse_input_subs() 
  242.  
  243. 	if game_machinima_hide_hints() then 
  244. 		local hint_data_count  = #self.hint_objects 
  245. 		for i = 1, hint_data_count do 
  246. 			self.hint_objects[i].button:set_visible(false) 
  247. 			self.hint_objects[i].text:set_visible(false)  
  248. 		end 
  249. 	end 
  250. end 
  251.  
  252. -- Pulses one of the buttons in the hint bar... 
  253. -- 
  254. -- @param button_id 	id of button position that we want to pulse... 
  255. function Vdo_hint_bar:pulse(button_id) 
  256. 	 
  257. 	--Wipe out any previously pulsing buttons... 
  258. 	for idx, val in pairs(self.pulse_buttons) do 
  259. 		val:object_destroy() 
  260. 	end 
  261. 	 
  262. 	self.pulse_buttons = {} 
  263. 	 
  264. 	local button = Vdo_base_object:clone(self.hint_objects[button_id].button.handle, self.handle) 
  265. 	local text = Vdo_base_object:clone(self.hint_objects[button_id].text.handle, self.handle) 
  266. 	button:set_depth(-100) 
  267. 	text:set_depth(-100) 
  268. 	button:set_property("render_mode", "additive_alpha") 
  269. 	text:set_property("render_mode", "additive_alpha") 
  270. 	 
  271. 	self.pulse_buttons.button = button 
  272. 	self.pulse_buttons.text = text 
  273. 	 
  274. 	local text_twn = Vdo_tween_object:new("pulse_text_twn", self.handle, self.doc_handle) 
  275. 	local btn_twn = Vdo_tween_object:new("pulse_btn_twn", self.handle, self.doc_handle) 
  276. 	local btn2_twn = Vdo_tween_object:new("pulse_btn2_twn", self.handle, self.doc_handle) 
  277. 	text_twn:set_target_handle(text.handle) 
  278. 	btn_twn:set_target_handle(button.handle) 
  279. 	btn2_twn:set_target_handle(button.handle) 
  280. 	 
  281. 	local anim = Vdo_anim_object:new("button_pulse", self.handle, self.doc_handle) 
  282. 	anim:play() 
  283. end 
  284.  
  285. function Vdo_hint_bar:enable_text_shadow(enable) 
  286. 	if enable then 
  287. 		for i = 1, self.hint_objects.num do 
  288. 			self.hint_objects[i].text:set_property("shadow_enabled", true) 
  289. 			self.hint_objects[i].text:set_property("shadow_offset", 2, 2) 
  290. 			self.hint_objects[i].text:set_property("shadow_alpha", .75) 
  291. 			self.hint_objects[i].text:set_property("shadow_tint", 0,0,0) 
  292. 		end 
  293. 	else 
  294. 		for i = 1, self.hint_objects.num do 
  295. 			self.hint_objects[i].text:set_property("shadow_enabled", false) 
  296. 		end 
  297. 	end 
  298. 	self.shadow_enabled = enable 
  299. end 
  300.  
  301. ------------------------------------------------------------------------------- 
  302. -- All objects get centered.... 
  303. ------------------------------------------------------------------------------- 
  304. function Vdo_hint_bar:enable_centered(enable) 
  305. 	self.centered = enable 
  306. end 
  307.  
  308. function Vdo_hint_bar:set_color(color) 
  309. 	for i = 1, self.hint_objects.num do 
  310. 		self.hint_objects[i].text:set_color(color.R, color.G, color.B)		 
  311. 	end 
  312. end 
  313.  
  314.  
  315. ------------------------------------------------------------------------------- 
  316. -- Makes button hints 18 point and rebuilds the button list... 
  317. -- 
  318. -- @param	enable	(bool) determines whether or the buttons should be 18pt. 
  319. ------------------------------------------------------------------------------- 
  320. function Vdo_hint_bar:enable_mini_mode(enable) 
  321. 	 
  322. 	if enable == true then 
  323. 		--If enabled resize button list... 
  324. 		self.hint_objects[1].button:set_scale(BUTTON_SCALE_MINI, BUTTON_SCALE_MINI) 
  325. 		self.hint_objects[1].text:set_property("text_scale", TEXT_SCALE_MINI, TEXT_SCALE_MINI) 
  326. 		self.hint_padding = HINT_PADDING_MINI 
  327. 		self.hint_spacing = HINT_SPACING_MINI 
  328. 	else 
  329. 		self.hint_objects[1].button:set_scale(BUTTON_SCALE_NORMAL, BUTTON_SCALE_NORMAL) 
  330. 		self.hint_objects[1].text:set_property("text_scale", TEXT_SCALE_NORMAL, TEXT_SCALE_NORMAL) 
  331. 		 
  332. 		self.hint_padding = HINT_PADDING_NORMAL 
  333. 		self.hint_spacing = HINT_SPACING_NORMAL 
  334. 	end 
  335.  
  336. 	--reset and rebuild hints... 
  337. 	if self.hint_data ~= 0 then 
  338. 		self:set_hints(self.hint_data) 
  339. 	end 
  340. end 
  341.  
  342. ------------------------------------------------------------------------------- 
  343. -- Returns the size of the hints in pixels. 
  344. -- 
  345. -- @return	width		Width of the button hints in pixels 
  346. -- @return	height	Height of the button hints in pixels 
  347. ------------------------------------------------------------------------------- 
  348. function Vdo_hint_bar:get_size() 
  349. 	return self.width, self.height 
  350. end 
  351.  
  352. function Vdo_hint_bar:set_width_max(width_max) 
  353. 	self.width_max = width_max 
  354. end 
  355.  
  356. function Vdo_hint_bar:get_hint_index(target_handle) 
  357. 	for i = 1, self.hint_objects.num do 
  358. 		if self.hint_objects[i].text.handle == target_handle or self.hint_objects[i].button.handle == target_handle then 
  359. 			return i 
  360. 		end 
  361. 	end 
  362. 	 
  363. 	-- Return 0 as an invalid index 
  364. 	return 0 
  365. end 
  366.  
  367. function Vdo_hint_bar:set_highlight(index, color) 
  368. 	for i = 1, self.hint_objects.num do 
  369. 		self.hint_objects[i].text:set_color(COLOR_UNHIGHLIGHT_TEXT.R, COLOR_UNHIGHLIGHT_TEXT. G, COLOR_UNHIGHLIGHT_TEXT.B) 
  370. 	end 
  371. 	 
  372. 	if index ~= 0 then 
  373. 		if self.hint_objects[index] ~= nil then 
  374. 			if color == nil then 
  375. 				color = COLOR_SAINTS_PURPLE 
  376. 			end 
  377. 			 
  378. 			game_UI_audio_play("Ui_main_menu_nav_up") 
  379. 			self.hint_objects[index].text:set_color(color.R, color.G, color.B) 
  380. 		else 
  381. 			debug_print("vint", "hint_bar:set_highlight - invalid index") 
  382. 		end 
  383. 	end 
  384. end 
  385.  
  386. --[[ --------------------------------------------------------------------- 
  387. -- Function - vdo_hint_bar_update_gamepad_state 
  388. -- Description - Called by code anytime gamepad is plugged or unplugged. 
  389. -- Parameters - none 
  390. -- Returns - nil 
  391. ]]-- --------------------------------------------------------------------- 
  392. function vdo_hint_bar_update_gamepad_state() 
  393. 	local v = Vdo_hint_bar_objects 
  394. 	for k, obj in pairs( Vdo_hint_bar_objects ) do 
  395. 	 
  396. 		if( vint_document_find(obj.func_prefix) == 0 ) then 
  397. 			-- Should have been cleaned up in screen scripts, so lets do it here 
  398. 			Vdo_hint_bar_objects[k] = nil 
  399. 		elseif( obj.hint_data ~= nil and obj.hint_objects[1].text:get_visible() ~= nil )then 
  400. 			 
  401. 			local is_input_tracker_subscribed = false 
  402. 			 
  403. 			if( obj.input_tracker ~= nil )then 
  404. 				is_input_tracker_subscribed = obj.input_tracker.is_subscribed 
  405. 			end 
  406. 			 
  407. 			obj:set_hints(obj.hint_data) 
  408. 			 
  409. 			if( obj.input_tracker ~= nil and is_input_tracker_subscribed == true )then 
  410. 				obj.input_tracker:subscribe(true) 
  411. 			end 
  412. 		end 
  413. 	end 
  414. end 
  415.  
  416. ------------------------------------------------------------------------------- 
  417. --								Mouse/PC Functions 
  418. ------------------------------------------------------------------------------- 
  419. -- Adds mouse input subscriptions to the input tracker 
  420. -- 
  421. -- @param	func_prefix			Name of the screen that is currently using the hint bar 
  422. -- @param	input_tracker		The input tracker to hold the mouse inputs events 
  423. -- @param	priority				THe priority of the input event 
  424. function Vdo_hint_bar:add_mouse_inputs(func_prefix, input_tracker, priority) 
  425. 	if func_prefix == nil or input_tracker == nil then 
  426. 		return 
  427. 	end 
  428. 	 
  429. 	self.priority = priority or 50 
  430. 	self.func_prefix = func_prefix 
  431.  
  432. 	if( self.input_tracker == nil ) then 
  433. 		self:clear_mouse_input_subs() 
  434. 	end 
  435.  
  436. 	if( self.input_tracker ~= input_tracker ) then 
  437. 		self.input_tracker = input_tracker 
  438. 	end 
  439. 	 
  440. 	self:add_mouse_input_subs()	 
  441. end 
  442.  
  443. --[[ --------------------------------------------------------------------- 
  444. -- Function - clear_mouse_input_subs 
  445. -- Description - Clears out all the current mouse input subscriptions 
  446. -- Parameters - none 
  447. -- Returns - nil 
  448. ]]-- --------------------------------------------------------------------- 
  449. function Vdo_hint_bar:clear_mouse_input_subs() 
  450. 	if( self.input_tracker == nil ) then 
  451. 		return 
  452. 	end 
  453. 	 
  454. 	for i = 1, self.hint_objects.num do 
  455. 		if self.hint_objects[i].text:get_visible() then	 
  456. 			self.input_tracker:remove_input_by_object_handle("mouse_click", self.hint_objects[i].text.handle) 
  457. 			self.input_tracker:remove_input_by_object_handle("mouse_move", self.hint_objects[i].text.handle) 
  458. 			self.input_tracker:remove_input_by_object_handle("mouse_click", self.hint_objects[i].button.handle) 
  459. 			self.input_tracker:remove_input_by_object_handle("mouse_move", self.hint_objects[i].button.handle) 
  460. 		end 
  461. 	end 
  462. end 
  463.  
  464. --[[ --------------------------------------------------------------------- 
  465. -- Function - clear_mouse_input_subs 
  466. -- Description - Add all the current mouse input subscriptions 
  467. -- Parameters - none 
  468. -- Returns - nil 
  469. ]]-- --------------------------------------------------------------------- 
  470. function Vdo_hint_bar:add_mouse_input_subs() 
  471. 	if( self.input_tracker == nil ) then 
  472. 		return 
  473. 	end 
  474. 	 
  475. 	local mouse_click_function = self.func_prefix.."_mouse_click" 
  476. 	local mouse_move_function = self.func_prefix.."_mouse_move" 
  477. 	 
  478. 	for i = 1, self.hint_objects.num do 
  479. 		if self.hint_objects[i].text:get_visible() then	 
  480. 			self.input_tracker:add_mouse_input("mouse_click", mouse_click_function, self.priority, self.hint_objects[i].text.handle) 
  481. 			self.input_tracker:add_mouse_input("mouse_move", mouse_move_function, self.priority, self.hint_objects[i].text.handle) 
  482. 			self.input_tracker:add_mouse_input("mouse_click", mouse_click_function, self.priority, self.hint_objects[i].button.handle) 
  483. 			self.input_tracker:add_mouse_input("mouse_move", mouse_move_function, self.priority, self.hint_objects[i].button.handle) 
  484. 		end 
  485. 	end 
  486. end 
  487.  
  488. function Vdo_hint_bar:override_mouse_depths(depth) 
  489. 	for i = 1, self.hint_objects.num do 
  490. 		if self.hint_objects[i].text:get_visible() then 
  491. 			vint_set_property(self.hint_objects[i].text.handle, "mouse_depth", depth) 
  492. 			vint_set_property(self.hint_objects[i].button.handle, "mouse_depth", depth) 
  493. 		end 
  494. 	end 
  495. end