Advertisement
Guest User

UPDATED Touchpad Code

a guest
Jul 25th, 2014
483
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.81 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Twitch touches pokemon
  3. // @namespace https://github.com/lostcoaster/twitch-touches-pokemon
  4. // @author lostcoaster
  5. // @author MattiasBuelens
  6. // @version 1.5
  7. // @description A tool adding a touch overlay onto the stream of twitchplayspokemon.
  8. // @grant unsafeWindow
  9.  
  10. // this include string credits Twitch Plays Pokemon Chat Filter
  11. // @include /^https?://(www|beta)\.twitch\.tv\/twitchplayspokemon(\/?)$/
  12. // @include /^https?://(www\.)?tinytwit\.ch\/twitchplayspokemon.*$/
  13.  
  14. // @updateURL https://raw.githubusercontent.com/lostcoaster/twitch-touches-pokemon/master/touch.user.js
  15. // ==/UserScript==
  16.  
  17. // for bookmarklet users : javascript:(function(){document.body.appendChild(document.createElement('script')).src='https://raw.githubusercontent.com/lostcoaster/twitch-touches-pokemon/master/touch.user.js';})();
  18.  
  19. /* jshint
  20. lastsemic:true,
  21. eqeqeq:true,
  22. unused:true
  23. */
  24. /* global
  25. unsafeWindow:false
  26. */
  27.  
  28. (function () {
  29.  
  30. 'use strict';
  31.  
  32. // ----------------------------
  33. // Greasemonkey support
  34. // ----------------------------
  35. // Greasemonkey userscripts run in a separate environment and cannot use global
  36. // variables from the page directly. They need to be accessed via `unsafeWindow`
  37.  
  38. var myWindow;
  39. try {
  40. myWindow = unsafeWindow;
  41. } catch (e) {
  42. myWindow = window;
  43. }
  44.  
  45. var $ = myWindow.jQuery;
  46.  
  47. var Setting = function (key, defaultValue) {
  48. this.key = key;
  49. this.defaultValue = defaultValue;
  50. this.value = undefined;
  51. this.observers = [];
  52. };
  53. Setting.prototype.getValue = function () {
  54. return (this.value !== undefined) ? this.value : this.defaultValue;
  55. };
  56. Setting.prototype.setValue = function (value) {
  57. var newValue = (value !== undefined) ? value : this.defaultValue;
  58. if (newValue !== this.value) {
  59. this.value = newValue;
  60. this.fireObservers(newValue);
  61. }
  62. };
  63. Setting.prototype.restoreDefault = function () {
  64. this.setValue(this.defaultValue);
  65. };
  66. Setting.prototype.load = function (settings) {
  67. this.setValue(settings ? settings[this.key] : undefined);
  68. };
  69. Setting.prototype.save = function (settings) {
  70. settings[this.key] = this.getValue();
  71. };
  72. Setting.prototype.observe = function (observer) {
  73. this.observers.push(observer);
  74. };
  75. Setting.prototype.fireObservers = function (value) {
  76. for (var i = 0; i < this.observers.length; i++) {
  77. this.observers[i].call(null, value, this.key, this);
  78. }
  79. };
  80. Setting.prototype.bind = function (input) {
  81. input = $(input);
  82. if (input.is(':checkbox')) {
  83. this.bindCheckbox(input);
  84. }
  85. };
  86. Setting.prototype.bindCheckbox = function (checkbox) {
  87. var self = this;
  88. // set current value
  89. checkbox.prop('checked', this.getValue());
  90. // bind checkbox to setting
  91. this.observe(function (newValue) {
  92. checkbox.prop('checked', newValue);
  93. });
  94. // bind setting to checkbox
  95. checkbox.change(function () {
  96. self.setValue(checkbox.prop('checked'));
  97. });
  98. };
  99.  
  100.  
  101. var forIn = function (obj, f) {
  102. for (var k in obj) {
  103. if (Object.prototype.hasOwnProperty.call(obj, k)) {
  104. f(k, obj[k]);
  105. }
  106. }
  107. };
  108.  
  109. var touch_pad = {
  110. parameters: {
  111. position_x: 0.701,
  112. position_y: 0.592,
  113. original_height: 434,
  114. bar_height: 30,
  115. ratio: 9 / 16,
  116. screen_height: 174,
  117. screen_width: 231
  118. },
  119.  
  120. settings: {
  121. show_border: new Setting('show_border', true),
  122. direct_send: new Setting('direct_send', false)
  123. },
  124. settings_key: 'twitch-touches-pokemon',
  125.  
  126. scale: 1,
  127.  
  128. interval_handle: (window.touch_pad === undefined ? undefined : touch_pad.interval_handle),
  129.  
  130. // reflect mouse event to coordinate output.
  131. coords: function (event) {
  132. var x = Math.floor((event.pageX - $(event.target).offset().left) / touch_pad.scale);
  133. var y = Math.floor((event.pageY - $(event.target).offset().top) / touch_pad.scale);
  134. x = Math.min(Math.max(x, 1), touch_pad.parameters.screen_width);
  135. y = Math.min(Math.max(y, 1), touch_pad.parameters.screen_height);
  136. return x + ',' + y;
  137. },
  138. // adjust position of the box, parameters are relative position of top-left corner of the box within stream screen
  139. // 0 <= rx,ry <= 1
  140. position: function (rx, ry) {
  141. try{
  142. var base = $('#player');
  143. if(!base.is('object')) // in tinytwitch #player is that object.
  144. base = base.find('object'); // but in twitch player is just a div.
  145. var height = base.height() - touch_pad.parameters.bar_height;
  146. var base_offset = base.offset();
  147. var real_height, real_width, left_margin, top_margin;
  148. if (height / base.width() > touch_pad.parameters.ratio) {
  149. // this is the behavior of BetterTTV, filling horizontally and leave margins on top and bottom
  150. real_width = base.width();
  151. real_height = real_width * touch_pad.parameters.ratio;
  152. touch_pad.scale = real_height / touch_pad.parameters.original_height;
  153. left_margin = 0;
  154. top_margin = (height - real_height) / 2;
  155. } else {
  156. // this is the normal behavior of twitch, filling vertically and leave margins on left and right.
  157. real_height = height;
  158. touch_pad.scale = real_height / touch_pad.parameters.original_height;
  159. real_width = real_height / touch_pad.parameters.ratio;
  160. left_margin = (base.width() - real_width) / 2;
  161. top_margin = 0;
  162. }
  163. $('.touch_overlay').offset({
  164. top: Math.floor(base_offset.top + top_margin + ry * real_height),
  165. left: Math.floor(base_offset.left + left_margin + rx * real_width)
  166. })
  167. .height(Math.floor(touch_pad.parameters.screen_height * touch_pad.scale))
  168. .width(Math.floor(touch_pad.parameters.screen_width * touch_pad.scale));
  169. } catch(err) {
  170. console.error(err); //don't quit
  171. }
  172.  
  173. },
  174.  
  175. aim: function () {
  176. touch_pad.position(touch_pad.parameters.position_x, touch_pad.parameters.position_y); // rough estimation No.2
  177. },
  178.  
  179. init_settings: function () {
  180. forIn(touch_pad.settings, function (k, setting) {
  181. setting.observe(function () {
  182. touch_pad.save_settings();
  183. });
  184. });
  185. },
  186. load_settings: function () {
  187. var settings = JSON.parse(myWindow.localStorage.getItem(touch_pad.settings_key));
  188. forIn(touch_pad.settings, function (k, setting) {
  189. setting.load(settings);
  190. });
  191. },
  192. save_settings: function () {
  193. var settings = {};
  194. forIn(touch_pad.settings, function (k, setting) {
  195. setting.save(settings);
  196. });
  197. myWindow.localStorage.setItem(touch_pad.settings_key, JSON.stringify(settings));
  198. },
  199. restore_default_settings: function () {
  200. forIn(touch_pad.settings, function (k, setting) {
  201. setting.restoreDefault();
  202. });
  203. },
  204.  
  205. init: function () {
  206. if ($('.touch_overlay').length === 0) {
  207.  
  208. $('body')
  209. .append('<div class="touch_overlay" style="cursor:crosshair;z-index:99"></div>')
  210. .append('<style type="text/css">.touchborder{border:red solid 1px;}</style>');
  211.  
  212.  
  213. $('.touch_overlay').unbind()
  214. .mouseup(function (event) {
  215. var output_text = touch_pad.coords(event);
  216. var output_area = $('textarea')
  217. .val(output_text)
  218. .change();
  219.  
  220. // on tinytwitch accessing the textarea is difficult.
  221. if (output_area.length === 0)
  222. myWindow.prompt('Twitch touches pokemon cannot locate the chat box on this page, possibly because it is not on the offical stream page, but you can copy the following value to send it yourself.',
  223. output_text);
  224.  
  225. if (touch_pad.settings.direct_send.getValue()) {
  226. $('.send-chat-button button').click();
  227. }
  228.  
  229. });
  230.  
  231. // add the reaiming into settings menu. idea stolen from the chat-filter : http://redd.it/1y8ukl
  232. $('.chat-settings')
  233. .append('<div class="chat-menu-header">Touch pad</div>')
  234. .append($('<div class="chat-menu-content"></div>')
  235. .append('<p><label><input id="ttp-show-border" type="checkbox"> Show border</label></p>')
  236. .append('<p><label><input id="ttp-direct-send" type="checkbox"> Send on clicking</label></p>')
  237. .append($('<button>Reposition Touchpad</button>').click(function () {
  238. touch_pad.aim();
  239. })));
  240. }
  241.  
  242. // initialize settings
  243. touch_pad.init_settings();
  244. // bind inputs to settings
  245. touch_pad.settings.show_border.bind('#ttp-show-border');
  246. touch_pad.settings.direct_send.bind('#ttp-direct-send');
  247. // observe settings
  248. touch_pad.settings.show_border.observe(function (shown) {
  249. $('.touch_overlay').toggleClass("touchborder", shown);
  250. });
  251. // load settings
  252. touch_pad.load_settings();
  253.  
  254. //start running
  255. touch_pad.aim();
  256.  
  257. if (touch_pad.interval_handle) {
  258. clearInterval(touch_pad.interval_handle);
  259. }
  260. //update the size every 50 ms , thanks to Meiguro's idea!
  261. touch_pad.interval_handle = setInterval(touch_pad.aim, 50);
  262. }
  263. };
  264.  
  265. // initialize on DOM ready
  266. $(function () {
  267. touch_pad.init();
  268. });
  269.  
  270. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement