SHOW:
|
|
- or go back to the newest paste.
| 1 | // ==UserScript== | |
| 2 | // @id [email protected] | |
| 3 | // @name Twitch Plays Pokémon Touch Controller | |
| 4 | // @version 0.3.2 | |
| 5 | // @author Meiguro <[email protected]> http://meiguro.com/ | |
| 6 | // @namespace https://github.com/Meiguro/twitch-plays-control | |
| 7 | // @description Add Touch controls to Twitch Plays Pokemon touch-enabled games. | |
| 8 | // @include /^https?://(www|beta)?\.?twitch.tv/twitch_?plays.*$/ | |
| 9 | // @grant unsafeWindow, GM_addStyle, GM_info | |
| 10 | // @run-at document-start | |
| 11 | // @updateURL https://raw.githubusercontent.com/Meiguro/twitch-plays-control/master/twitch-plays-control.meta.js | |
| 12 | // @installURL https://raw.githubusercontent.com/Meiguro/twitch-plays-control/master/twitch-plays-control.user.js | |
| 13 | // @downloadURL https://raw.githubusercontent.com/Meiguro/twitch-plays-control/master/twitch-plays-control.user.js | |
| 14 | // ==/UserScript== | |
| 15 | ||
| 16 | /** | |
| 17 | * v0.3.2 CHANGELOG ༼ つ ◕_◕ ༽つ | |
| 18 | * | |
| 19 | * - Fixed the coordinate range to be 1,1 - 319,239. | |
| 20 | * | |
| 21 | * v0.3.1 | |
| 22 | * | |
| 23 | * - Updated to the new 3DS layout. Reset your controller settings if the | |
| 24 | * touch input box is in the wrong location. | |
| 25 | * | |
| 26 | * - The logic has been separated into components for maintainability. There | |
| 27 | * should be no break in functionality. | |
| 28 | * | |
| 29 | * Enjoy! | |
| 30 | * | |
| 31 | * - Meiguro | |
| 32 | */ | |
| 33 | ||
| 34 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
| |
| 35 | /* globals GM_addStyle, GM_info */ | |
| 36 | ||
| 37 | var util2 = require('util2');
| |
| 38 | ||
| 39 | var dd = require('dd');
| |
| 40 | dd.ui = require('dd-ui');
| |
| 41 | ||
| 42 | var Entity = require('entity');
| |
| 43 | var Touch = require('touch');
| |
| 44 | var Chat = require('chat');
| |
| 45 | var Settings = require('settings');
| |
| 46 | var mywindow = require('window');
| |
| 47 | ||
| 48 | require('gm-shims');
| |
| 49 | ||
| 50 | var Control = function(def) {
| |
| 51 | Entity.call(this, def); | |
| 52 | this.config = {};
| |
| 53 | }; | |
| 54 | ||
| 55 | util2.inherit(Control, Entity, Control.prototype); | |
| 56 | ||
| 57 | Control.DefaultConfig = {
| |
| 58 | delay: 50, | |
| 59 | screen: {
| |
| 60 | aspect: 1280 / 720, | |
| 61 | position: [0.997, 0.977], | |
| 62 | scale: 0.392, | |
| 63 | size: [320, 240], | |
| 64 | barHeight: 30 | |
| 65 | }, | |
| 66 | enabled: true, | |
| 67 | showBorder: true, | |
| 68 | showCoordTooltip: true, | |
| 69 | showCross: true, | |
| 70 | autoSend: true, | |
| 71 | showDroplets: true, | |
| 72 | streamDelay: 15, | |
| 73 | }; | |
| 74 | ||
| 75 | Control.PlayerSelector = '.dynamic-player, .player-container'; | |
| 76 | ||
| 77 | Control.prototype.updateLoad = function() {
| |
| 78 | if (this.loaded) { return; }
| |
| 79 | if (!this.loadable()) { return; }
| |
| 80 | ||
| 81 | this.onload(); | |
| 82 | }; | |
| 83 | ||
| 84 | Control.prototype.update = function(force) {
| |
| 85 | this.updateLoad(); | |
| 86 | ||
| 87 | Entity.prototype.update.call(this, force); | |
| 88 | }; | |
| 89 | ||
| 90 | Control.prototype.onClick = function(e) {
| |
| 91 | this.component('touch').onClick(e);
| |
| 92 | }; | |
| 93 | ||
| 94 | Control.prototype.onMove = function(e) {
| |
| 95 | this.component('touch').onMove(e);
| |
| 96 | }; | |
| 97 | ||
| 98 | Control.prototype.onPressReset = function(e) {
| |
| 99 | $.extend(true, this.config, Control.DefaultConfig); | |
| 100 | ||
| 101 | this.eachComponent(function(component) {
| |
| 102 | for (var k in component) {
| |
| 103 | var $elem = component[k]; | |
| 104 | if ($elem.$change) {
| |
| 105 | $elem.$change(); | |
| 106 | } | |
| 107 | } | |
| 108 | }); | |
| 109 | ||
| 110 | this.update(true); | |
| 111 | this.saveConfig(); | |
| 112 | }; | |
| 113 | ||
| 114 | Control.prototype.onPressChangeChatServer = function(e) {
| |
| 115 | this.component('chat').onPressChangeChatServer(e);
| |
| 116 | }; | |
| 117 | ||
| 118 | Control.prototype.saveConfig = function() {
| |
| 119 | localStorage.TPControl = JSON.stringify(this.config); | |
| 120 | }; | |
| 121 | ||
| 122 | Control.prototype.loadConfig = function() {
| |
| 123 | if (!localStorage.TPControl) {
| |
| 124 | localStorage.TPControl = this.config; | |
| 125 | } else {
| |
| 126 | try {
| |
| 127 | var lastConfig = JSON.parse(localStorage.TPControl); | |
| 128 | for (var k in lastConfig) {
| |
| 129 | this.config[k] = lastConfig[k]; | |
| 130 | } | |
| 131 | } catch(e) {
| |
| 132 | console.log(e); | |
| 133 | } | |
| 134 | } | |
| 135 | }; | |
| 136 | ||
| 137 | Control.prototype.init = function() {
| |
| 138 | var self = this; | |
| 139 | ||
| 140 | window.$ = mywindow.jQuery; | |
| 141 | ||
| 142 | $.extend(true, this.config, Control.DefaultConfig); | |
| 143 | ||
| 144 | this.loadConfig(); | |
| 145 | this.saveConfig(); | |
| 146 | ||
| 147 | dd.onChange = this.saveConfig.bind(this); | |
| 148 | ||
| 149 | if (this.config.screen.size[0] != Control.DefaultConfig.screen.size[0]) {
| |
| 150 | $.extend(true, this.config.screen, Control.DefaultConfig.screen); | |
| 151 | } | |
| 152 | ||
| 153 | $('.tpc-mouse-box').remove();
| |
| 154 | $('.tpc-control-settings').remove();
| |
| 155 | ||
| 156 | var touch = new Touch(); | |
| 157 | var chat = new Chat(); | |
| 158 | var settings = new Settings(); | |
| 159 | ||
| 160 | this.addComponent(touch); | |
| 161 | this.addComponent(chat); | |
| 162 | this.addComponent(settings); | |
| 163 | ||
| 164 | var $player = touch.$player = $(Control.PlayerSelector); | |
| 165 | var $mouseBox = touch.$mouseBox = $('<div/>').addClass('tpc-mouse-box');
| |
| 166 | var $coordTooltip = touch.$coordTooltip = $('<div/>').addClass('tpc-coord-tooltip');
| |
| 167 | ||
| 168 | var $chatSettings = settings.$chatSettings = $(Settings.ChatSelector); | |
| 169 | var $controlSettings = settings.$controlSettings = $('<div/>').addClass('tpc-control-settings');
| |
| 170 | ||
| 171 | $player.css({ position: 'relative' });
| |
| 172 | $chatSettings.css({ position: 'absolute' });
| |
| 173 | ||
| 174 | $mouseBox.css({
| |
| 175 | cursor: 'pointer', | |
| 176 | border: '2px solid rgba(150, 150, 150, 0.2)', | |
| 177 | borderRadius: '5px' | |
| 178 | }); | |
| 179 | ||
| 180 | GM_addStyle( | |
| 181 | '.tpc-mouse-box .tpc-coord-tooltip { display: none; color: #444; font-weight: normal } ' +
| |
| 182 | '.tpc-mouse-box:hover .tpc-coord-tooltip { display: block }');
| |
| 183 | ||
| 184 | $coordTooltip.css({
| |
| 185 | padding: '0px 5px', | |
| 186 | background: 'rgba(255, 255, 255, 0.8)', | |
| 187 | borderRadius: '2px' | |
| 188 | }); | |
| 189 | ||
| 190 | $mouseBox.empty(); | |
| 191 | $mouseBox.append($coordTooltip); | |
| 192 | ||
| 193 | $controlSettings.empty(); | |
| 194 | $controlSettings.append( | |
| 195 | '<div class="chat-menu tpc-touch-menu">' + | |
| 196 | '<div class="chat-menu-header">Touch Control Settings</div>' + | |
| 197 | '<div class="chat-menu-content tpc-control-sliders"></div>' + | |
| 198 | '<div class="chat-menu-content tpc-control-checkboxes"></div>' + | |
| 199 | '<div class="chat-menu-content tpc-control-last"></div>' + | |
| 200 | '</div>' + | |
| 201 | '<div class="chat-menu tpc-chat-menu">' + | |
| 202 | '<div class="chat-menu-header">Chat Server</div>' + | |
| 203 | '<div class="chat-menu-content tpc-control-chat"></div>' + | |
| 204 | '</div>'); | |
| 205 | ||
| 206 | $controlSettings.find('.tpc-control-sliders')
| |
| 207 | .append(touch.xSlider = dd.ui.slider( | |
| 208 | 'tpc-x-slider tpc-slider', 'Touch-box x-position', { min: 0, max: 1, step: 0.0005 },
| |
| 209 | this.config, 'screen.position.0', function() { touch.updateMouseBox(true); }))
| |
| 210 | .append(touch.ySlider = dd.ui.slider( | |
| 211 | 'tpc-y-slider tpc-slider', 'Touch-box y-position', { min: 0, max: 1, step: 0.0005 },
| |
| 212 | this.config, 'screen.position.1', function() { touch.updateMouseBox(true); }))
| |
| 213 | .append(touch.scaleSlider = dd.ui.slider( | |
| 214 | 'tpc-scale-slider tpc-slider', 'Touch-box scale', { min: 0, max: 1, step: 0.0005 },
| |
| 215 | this.config, 'screen.scale', function() { touch.updateMouseBox(true); }));
| |
| 216 | ||
| 217 | $controlSettings.find('.tpc-control-checkboxes')
| |
| 218 | .append(touch.enabledCheckbox = dd.ui.checkbox( | |
| 219 | 'tpc-enabled-checkbox', 'Enable touch control', this.config, 'enabled', | |
| 220 | function() {
| |
| 221 | touch.$mouseBox.css({ display: self.config.enabled ? 'block' : 'none' });
| |
| 222 | })) | |
| 223 | .append(touch.borderCheckbox = dd.ui.checkbox( | |
| 224 | 'tpc-border-checkbox', 'Show border box', this.config, 'showBorder', | |
| 225 | function() {
| |
| 226 | touch.$mouseBox.css({ border: self.config.showBorder ? '2px solid rgba(255, 255, 255, 0.5)' : 'none' });
| |
| 227 | })) | |
| 228 | .append(touch.coordTooltipCheckbox = dd.ui.checkbox( | |
| 229 | 'tpc-tooltip-checkbox', 'Show coord tooltip', this.config, 'showCoordTooltip', | |
| 230 | function() {
| |
| 231 | if (self.config.showCoordTooltip) {
| |
| 232 | touch.$mouseBox.append(touch.$coordTooltip); | |
| 233 | } else {
| |
| 234 | touch.$coordTooltip.remove(); | |
| 235 | } | |
| 236 | })) | |
| 237 | .append(touch.crossCheckbox = dd.ui.checkbox( | |
| 238 | 'tpc-cross-checkbox', 'Use cross pointer', this.config, 'showCross', | |
| 239 | function() {
| |
| 240 | touch.$mouseBox.css({ cursor: self.config.showCross ? 'crosshair' : 'default' });
| |
| 241 | })) | |
| 242 | .append(touch.autoSendCheckbox = dd.ui.checkbox( | |
| 243 | 'tpc-auto-send-checkbox', 'Auto-send touches', this.config, 'autoSend')) | |
| 244 | .append(touch.dropletsCheckbox = dd.ui.checkbox( | |
| 245 | 'tpc-droplet-checkbox', 'Show touch droplets', this.config, 'showDroplets')); | |
| 246 | ||
| 247 | $controlSettings.find('.tpc-control-last')
| |
| 248 | .append(touch.resetButton = dd.ui.button( | |
| 249 | 'tpc-reset-button', 'Reset controller settings', this.onPressReset.bind(this))); | |
| 250 | ||
| 251 | $controlSettings.find('.tpc-control-chat')
| |
| 252 | .append('<p><label>Current <span class="tpc-chat-server"></span></label></p>')
| |
| 253 | .append(chat.chatServerButton = dd.ui.button( | |
| 254 | 'tpc-chat-server-button', 'Change chat server', this.onPressChangeChatServer.bind(this))); | |
| 255 | ||
| 256 | $player.append($mouseBox); | |
| 257 | $chatSettings.append($controlSettings); | |
| 258 | ||
| 259 | $mouseBox.on('click', this.onClick.bind(this));
| |
| 260 | $mouseBox.on('mousemove', this.onMove.bind(this));
| |
| 261 | ||
| 262 | settings.update(true); | |
| 263 | ||
| 264 | this.loaded = true; | |
| 265 | ||
| 266 | this.start(); | |
| 267 | ||
| 268 | setTimeout(function() {
| |
| 269 | $('.chat-room .loading-mask').remove();
| |
| 270 | }, 5000); | |
| 271 | }; | |
| 272 | ||
| 273 | Control.prototype.loadable = function() {
| |
| 274 | var $ = mywindow.jQuery; | |
| 275 | if (typeof $ !== 'function') { return false; }
| |
| 276 | ||
| 277 | var hasPlayer = $(Control.PlayerSelector).length; | |
| 278 | var hasChatSettings = $(Settings.ChatSelector).length; | |
| 279 | return hasPlayer || hasChatSettings; | |
| 280 | }; | |
| 281 | ||
| 282 | Control.prototype.onload = function() {
| |
| 283 | this.init(); | |
| 284 | if (typeof GM_info === 'object') {
| |
| 285 | console.log(GM_info.script.name + ' v' + GM_info.script.version + ' loaded!'); | |
| 286 | } else {
| |
| 287 | console.log('Twitch Plays Control loaded!');
| |
| 288 | } | |
| 289 | }; | |
| 290 | ||
| 291 | var control = new Control(); | |
| 292 | ||
| 293 | setInterval(control.update.bind(control), Control.DefaultConfig.delay); | |
| 294 | ||
| 295 | control.update(); | |
| 296 | ||
| 297 | mywindow.TPControl = control; | |
| 298 | ||
| 299 | },{"chat":2,"dd":5,"dd-ui":4,"entity":6,"gm-shims":7,"settings":8,"touch":9,"util2":10,"window":11}],2:[function(require,module,exports){
| |
| 300 | var util2 = require('util2');
| |
| 301 | var Component = require('component');
| |
| 302 | ||
| 303 | var mywindow = require('window');
| |
| 304 | ||
| 305 | var Chat = function(def) {
| |
| 306 | Component.call(this, def); | |
| 307 | }; | |
| 308 | ||
| 309 | util2.inherit(Chat, Component, Chat.prototype); | |
| 310 | ||
| 311 | Chat.InputSelector = '.ember-text-area'; | |
| 312 | Chat.ButtonSelector = '.send-chat-button button'; | |
| 313 | Chat.HiddenSelector = '.chat-hidden-overlay'; | |
| 314 | Chat.LogSelector = '.chat-messages .tse-content'; | |
| 315 | Chat.ServerAddress = '199.9.252.26:6667'; | |
| 316 | ||
| 317 | Chat.prototype.name = 'chat'; | |
| 318 | ||
| 319 | Chat.prototype.start = function() {
| |
| 320 | }; | |
| 321 | ||
| 322 | Chat.prototype.getChatSession = function() {
| |
| 323 | if (this.chatSession) {
| |
| 324 | return this.chatSession; | |
| 325 | } | |
| 326 | ||
| 327 | var App = mywindow.App; | |
| 328 | if (App && App.Room) {
| |
| 329 | return (this.chatSession = App.Room._getTmiSession().fulfillmentValue); | |
| 330 | } | |
| 331 | }; | |
| 332 | ||
| 333 | Chat.prototype.getChatConnection = function() {
| |
| 334 | var chatSession = this.getChatSession(); | |
| 335 | var connections = chatSession._connections; | |
| 336 | var cluster = connections.prod || connections.event; | |
| 337 | if (cluster) { return cluster; }
| |
| 338 | for (var k in connections) {
| |
| 339 | return connections[k]; | |
| 340 | } | |
| 341 | }; | |
| 342 | ||
| 343 | Chat.prototype.getCurrentChatAddress = function() {
| |
| 344 | var chatSession = this.getChatSession(); | |
| 345 | if (!chatSession) { return; }
| |
| 346 | var connection = this.getChatConnection(); | |
| 347 | if (!connection) { return; }
| |
| 348 | var addr = connection._addrs[connection._currentAddressIndex]; | |
| 349 | if (!addr) { return; }
| |
| 350 | return addr.host + ':' + addr.port; | |
| 351 | }; | |
| 352 | ||
| 353 | Chat.prototype.connectServer = function(address) {
| |
| 354 | var addr = address.split(':');
| |
| 355 | var chatSession = this.getChatSession(); | |
| 356 | var connection = this.getChatConnection(); | |
| 357 | if (!connection) {
| |
| 358 | window.alert('TPC: Couldn\'t obtain a chat connection to manipulate!');
| |
| 359 | return; | |
| 360 | } | |
| 361 | ||
| 362 | connection.close(); | |
| 363 | connection._addrs = [{ host: addr[0], port: addr[1] }];
| |
| 364 | connection._currentAddressIndex = 0; | |
| 365 | connection._numSocketConnectAttempts = 0; | |
| 366 | connection.open(); | |
| 367 | ||
| 368 | var msg = 'connecting to chat server ' + address + '...'; | |
| 369 | $(Chat.LogSelector + ' .ember-view:last') | |
| 370 | .before('<div class="chat-line admin"><span class="message">' + msg + '</span></div>');
| |
| 371 | }; | |
| 372 | ||
| 373 | Chat.prototype.isChatVisible = function() {
| |
| 374 | return $(Chat.InputSelector).length && !$(Chat.HiddenSelector).is(':visible');
| |
| 375 | }; | |
| 376 | ||
| 377 | Chat.prototype.setInput = function(input, broadcast) {
| |
| 378 | $(Chat.InputSelector).val(input).focus().change().blur(); | |
| 379 | if (this.config.autoSend) {
| |
| 380 | $(Chat.ButtonSelector).click(); | |
| 381 | } | |
| 382 | if (!this.isChatVisible() && broadcast !== false) {
| |
| 383 | localStorage.TPCInput = input; | |
| 384 | } | |
| 385 | }; | |
| 386 | ||
| 387 | Chat.prototype.updateInput = function() {
| |
| 388 | if (!this.entity.loaded) { return; }
| |
| 389 | if (!this.config.enabled) { return; }
| |
| 390 | ||
| 391 | if (!this.isChatVisible()) { return; }
| |
| 392 | ||
| 393 | var input = localStorage.TPCInput; | |
| 394 | delete localStorage.TPCInput; | |
| 395 | if (typeof input === 'string' && input.length > 0) {
| |
| 396 | this.setInput(input, false); | |
| 397 | } | |
| 398 | }; | |
| 399 | ||
| 400 | Chat.prototype.updateChatSession = function() {
| |
| 401 | if (this.chatSession) { return; }
| |
| 402 | ||
| 403 | var TMI = mywindow.TMI; | |
| 404 | if (!TMI) { return; }
| |
| 405 | ||
| 406 | if (this.entity.loaded) {
| |
| 407 | this.getChatSession(); | |
| 408 | } | |
| 409 | }; | |
| 410 | ||
| 411 | Chat.prototype.update = function() {
| |
| 412 | this.updateChatSession(); | |
| 413 | this.updateInput(); | |
| 414 | }; | |
| 415 | ||
| 416 | Chat.prototype.onPressChangeChatServer = function(e) {
| |
| 417 | var defaultAddress = Chat.ServerAddress; | |
| 418 | var currentAddress = this.getCurrentChatAddress(); | |
| 419 | var address = window.prompt( | |
| 420 | 'Enter chat server address:' + | |
| 421 | (currentAddress ? | |
| 422 | '\nCurrent ' + currentAddress : | |
| 423 | '\nExample ' + defaultAddress), | |
| 424 | defaultAddress) || ''; | |
| 425 | address = address.replace(/\s/, ''); | |
| 426 | if (address.length === 0) {
| |
| 427 | return; | |
| 428 | } | |
| 429 | if (!address.match(':')) {
| |
| 430 | address += ':6667'; | |
| 431 | } | |
| 432 | this.connectServer(address); | |
| 433 | }; | |
| 434 | ||
| 435 | module.exports = Chat; | |
| 436 | ||
| 437 | },{"component":3,"util2":10,"window":11}],3:[function(require,module,exports){
| |
| 438 | var Component = function(def) {
| |
| 439 | this.state = def || {};
| |
| 440 | }; | |
| 441 | ||
| 442 | Component.prototype.component = function(name) {
| |
| 443 | return this.entity.component(name); | |
| 444 | }; | |
| 445 | ||
| 446 | Component.prototype.start = function() {};
| |
| 447 | ||
| 448 | Component.prototype.update = function() {};
| |
| 449 | ||
| 450 | module.exports = Component; | |
| 451 | ||
| 452 | },{}],4:[function(require,module,exports){
| |
| 453 | var dd = require('dd');
| |
| 454 | ||
| 455 | dd.ui = dd.ui || {};
| |
| 456 | ||
| 457 | dd.ui.checkbox = function(id, label, obj, ref, onChange) {
| |
| 458 | var $elem = $('<p><label for="'+id+'"><input id="'+id+'" type="checkbox"> '+label+'</label></p>');
| |
| 459 | var $input = $elem.find('input');
| |
| 460 | dd.bindGetSet($elem, $input.prop.bind($input, 'checked')); | |
| 461 | $input.on('change', dd.bindElement($elem, obj, ref, onChange));
| |
| 462 | return $elem; | |
| 463 | }; | |
| 464 | ||
| 465 | dd.ui.slider = function(klass, label, options, obj, ref, onChange) {
| |
| 466 | var $elem = $('<p><label>'+label+'</label></p>');
| |
| 467 | var $slider = $('<div class="'+klass+'"></div>');
| |
| 468 | $slider.slider(options); | |
| 469 | $elem.prepend($slider); | |
| 470 | dd.bindGetSet($elem, $slider.slider.bind($slider, 'value')); | |
| 471 | $slider.slider({ slide: dd.bindElement($elem, obj, ref, onChange) });
| |
| 472 | return $elem; | |
| 473 | }; | |
| 474 | ||
| 475 | dd.ui.button = function(klass, label, onPress) {
| |
| 476 | var $elem = $('<button class="'+klass+'">'+label+'</button>');
| |
| 477 | $elem.on('click', onPress);
| |
| 478 | return $elem; | |
| 479 | }; | |
| 480 | ||
| 481 | module.exports = dd.ui; | |
| 482 | ||
| 483 | },{"dd":5}],5:[function(require,module,exports){
| |
| 484 | var dd = {};
| |
| 485 | ||
| 486 | dd.last = function(a) {
| |
| 487 | return a[a.length - 1]; | |
| 488 | }; | |
| 489 | ||
| 490 | dd.toKey = function(obj, key) {
| |
| 491 | return obj instanceof Array ? parseInt(key) : key; | |
| 492 | }; | |
| 493 | ||
| 494 | dd.getByKeys = function(obj, keys, offset) {
| |
| 495 | for (var i = 0, ii = keys.length - (offset || 0); i < ii; ++i) {
| |
| 496 | obj = obj[dd.toKey(obj, keys[i])]; | |
| 497 | } | |
| 498 | return obj; | |
| 499 | }; | |
| 500 | ||
| 501 | dd.setByKey = function(obj, key, value) {
| |
| 502 | obj[dd.toKey(obj, key)] = value; | |
| 503 | }; | |
| 504 | ||
| 505 | dd.set = function(obj, ref, value) {
| |
| 506 | var keys = ref.split('.');
| |
| 507 | dd.setByKey(dd.getByKeys(obj, keys, 1), dd.last(keys), value); | |
| 508 | }; | |
| 509 | ||
| 510 | dd.get = function(obj, ref) {
| |
| 511 | return dd.getByKeys(obj, ref.split('.'));
| |
| 512 | }; | |
| 513 | ||
| 514 | dd.bindGetSet = function($elem, get, set) {
| |
| 515 | $elem.$get = get; | |
| 516 | $elem.$set = set || get; | |
| 517 | }; | |
| 518 | ||
| 519 | dd.bindElement = function($elem, obj, ref, onChange) {
| |
| 520 | $elem.$obj = obj; | |
| 521 | $elem.$ref = ref; | |
| 522 | $elem.$change = function(e) {
| |
| 523 | if (e) {
| |
| 524 | dd.set(obj, ref, $elem.$get()); | |
| 525 | } else {
| |
| 526 | $elem.$set(dd.get(obj, ref)); | |
| 527 | } | |
| 528 | if (onChange) { onChange(e); }
| |
| 529 | if (dd.onChange) { dd.onChange(e); }
| |
| 530 | }; | |
| 531 | $elem.$change(); | |
| 532 | return $elem.$change; | |
| 533 | }; | |
| 534 | ||
| 535 | module.exports = dd; | |
| 536 | ||
| 537 | },{}],6:[function(require,module,exports){
| |
| 538 | var Entity = function(def) {
| |
| 539 | this.state = def || {};
| |
| 540 | this._components = []; | |
| 541 | this._componentsByName = {};
| |
| 542 | }; | |
| 543 | ||
| 544 | Entity.prototype.component = function(name) {
| |
| 545 | return this._componentsByName[name]; | |
| 546 | }; | |
| 547 | ||
| 548 | Entity.prototype.eachComponent = function(callback) {
| |
| 549 | this._components.forEach(callback.bind(this)); | |
| 550 | }; | |
| 551 | ||
| 552 | Entity.prototype.addComponent = function(component) {
| |
| 553 | if (component.entity) {
| |
| 554 | component.entity.removeComponent(component); | |
| 555 | } | |
| 556 | this._componentsByName[component.name] = component; | |
| 557 | this._components.push(component); | |
| 558 | component.entity = this; | |
| 559 | component.config = this.config; | |
| 560 | }; | |
| 561 | ||
| 562 | Entity.prototype.removeComponent = function(component) {
| |
| 563 | var index = this._components.indexOf(component); | |
| 564 | if (index === -1) { return; }
| |
| 565 | this._components.splice(index, 1); | |
| 566 | delete this._componentsByName[component.name]; | |
| 567 | delete component.entity; | |
| 568 | delete component.config; | |
| 569 | }; | |
| 570 | ||
| 571 | Entity.prototype.start = function() {
| |
| 572 | for (var i = 0, ii = this._components.length; i < ii; ++i) {
| |
| 573 | this._components[i].start(); | |
| 574 | } | |
| 575 | }; | |
| 576 | ||
| 577 | Entity.prototype.update = function(force) {
| |
| 578 | for (var i = 0, ii = this._components.length; i < ii; ++i) {
| |
| 579 | this._components[i].update(force); | |
| 580 | } | |
| 581 | }; | |
| 582 | ||
| 583 | module.exports = Entity; | |
| 584 | ||
| 585 | },{}],7:[function(require,module,exports){
| |
| 586 | (function (global){
| |
| 587 | ||
| 588 | if (typeof GM_addStyle === 'undefined') {
| |
| 589 | global.GM_addStyle = function(style) {
| |
| 590 | $('head:first').append($('<style>').text(style));
| |
| 591 | }; | |
| 592 | } | |
| 593 | ||
| 594 | }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
| |
| 595 | },{}],8:[function(require,module,exports){
| |
| 596 | var util2 = require('util2');
| |
| 597 | var Component = require('component');
| |
| 598 | ||
| 599 | var Settings = function(def) {
| |
| 600 | Component.call(this, def); | |
| 601 | }; | |
| 602 | ||
| 603 | util2.inherit(Settings, Component, Settings.prototype); | |
| 604 | ||
| 605 | Settings.ChatSelector = '.js-chat-settings'; | |
| 606 | Settings.ButtonSelector = '.settings.button'; | |
| 607 | ||
| 608 | Settings.prototype.name = 'settings'; | |
| 609 | ||
| 610 | Settings.prototype.start = function() {
| |
| 611 | }; | |
| 612 | ||
| 613 | Settings.prototype.updateServerLabel = function() {
| |
| 614 | var $chatServer = this.$chatSettings.find('.tpc-chat-server');
| |
| 615 | ||
| 616 | var labelAddress = $chatServer.text(); | |
| 617 | var currentAddress = this.component('chat').getCurrentChatAddress();
| |
| 618 | if (currentAddress !== labelAddress) {
| |
| 619 | $chatServer.text(currentAddress); | |
| 620 | } | |
| 621 | }; | |
| 622 | ||
| 623 | Settings.prototype.updatePosition = function(force) {
| |
| 624 | var overflow = this.$chatSettings.css('overflowY') || '';
| |
| 625 | ||
| 626 | if (overflow.match(/(auto|scroll)/)) {
| |
| 627 | this.$controlSettings.css({ position: 'static', left: 'none', top: 'none' });
| |
| 628 | return; | |
| 629 | } | |
| 630 | ||
| 631 | var minWidth = Math.max(200, this.$chatSettings.width()); | |
| 632 | var position = { left: 0, top: 0 };
| |
| 633 | var offset = this.$chatSettings.offset(); | |
| 634 | var isSlim = offset.left > 0 && offset.left < minWidth; | |
| 635 | ||
| 636 | this.$controlSettings.css({
| |
| 637 | position: 'absolute', | |
| 638 | minWidth: minWidth, | |
| 639 | left: position.left + (minWidth + 5) * (isSlim ? 1 : -1), | |
| 640 | top: position.top + this.$chatSettings.height() - this.$controlSettings.height() | |
| 641 | }); | |
| 642 | }; | |
| 643 | ||
| 644 | Settings.prototype.update = function(force) {
| |
| 645 | if (!this.entity.loaded) { return; }
| |
| 646 | ||
| 647 | if (!this.$chatSettings.length) { return; }
| |
| 648 | if (!this.$chatSettings.is(':visible') && force !== true) { return; }
| |
| 649 | ||
| 650 | this.updateServerLabel(); | |
| 651 | this.updatePosition(); | |
| 652 | }; | |
| 653 | ||
| 654 | module.exports = Settings; | |
| 655 | ||
| 656 | },{"component":3,"util2":10}],9:[function(require,module,exports){
| |
| 657 | var util2 = require('util2');
| |
| 658 | var Component = require('component');
| |
| 659 | ||
| 660 | var Touch = function(def) {
| |
| 661 | Component.call(this, def); | |
| 662 | }; | |
| 663 | ||
| 664 | util2.inherit(Touch, Component, Touch.prototype); | |
| 665 | ||
| 666 | Touch.SizeEdge = [false, false]; | |
| 667 | ||
| 668 | Touch.prototype.name = 'touch'; | |
| 669 | ||
| 670 | Touch.prototype.start = function() {
| |
| 671 | }; | |
| 672 | ||
| 673 | Touch.prototype.getBorderSize = function() {
| |
| 674 | return parseInt(this.$mouseBox.css('borderTopWidth'));
| |
| 675 | }; | |
| 676 | ||
| 677 | Touch.prototype.getTouchPosition = function(e) {
| |
| 678 | var offset = this.$mouseBox.offset(); | |
| 679 | var borderSize = this.getBorderSize(); | |
| 680 | var x = e.clientX - offset.left - 2 * borderSize; | |
| 681 | var y = e.clientY - offset.top - 2 * borderSize; | |
| 682 | ||
| 683 | var minX = 0 + (Touch.SizeEdge[0] ? 0 : 1); | |
| 684 | var minY = 0 + (Touch.SizeEdge[1] ? 0 : 1); | |
| 685 | var maxX = this.config.screen.size[0] - (Touch.SizeEdge[0] ? 0 : 1); | |
| 686 | var maxY = this.config.screen.size[1] - (Touch.SizeEdge[1] ? 0 : 1); | |
| 687 | ||
| 688 | var touchX = Math.ceil(x / this.scale); | |
| 689 | var touchY = Math.ceil(y / this.scale); | |
| 690 | var valid = (touchX >= minX && touchX <= maxX) && | |
| 691 | (touchY >= minY && touchY <= maxY); | |
| 692 | return {
| |
| 693 | mouse: [x, y], | |
| 694 | position: [touchX, touchY], | |
| 695 | input: touchX + ',' + touchY, | |
| 696 | valid: valid | |
| 697 | }; | |
| 698 | }; | |
| 699 | ||
| 700 | Touch.prototype.spawnDroplet = function(position) {
| |
| 701 | var $drop = $('<div/>').addClass('tpc-droplet');
| |
| 702 | var size = 10; | |
| 703 | $drop.css({
| |
| 704 | background: 'rgba(255, 255, 255, 0.8)', | |
| 705 | borderRadius: size, | |
| 706 | position: 'absolute', | |
| 707 | left: position[0] - size / 2, | |
| 708 | top: position[1] - size / 2, | |
| 709 | width: size, | |
| 710 | height: size | |
| 711 | }); | |
| 712 | this.$mouseBox.append($drop); | |
| 713 | $drop | |
| 714 | .animate({
| |
| 715 | left: position[0], | |
| 716 | top: position[1], | |
| 717 | width: 0, | |
| 718 | height: 0 | |
| 719 | }, this.config.streamDelay * 1000) | |
| 720 | .queue(function() {
| |
| 721 | $drop.remove(); | |
| 722 | $drop.dequeue(); | |
| 723 | }); | |
| 724 | }; | |
| 725 | ||
| 726 | Touch.prototype.updateMouseBox = function(force) {
| |
| 727 | var playerWidth = this.$player.width(); | |
| 728 | var playerHeight = this.$player.height() - this.config.screen.barHeight; | |
| 729 | ||
| 730 | if ((this.playerWidth === playerWidth && | |
| 731 | this.playerHeight === playerHeight) && force !== true) {
| |
| 732 | return; | |
| 733 | } | |
| 734 | ||
| 735 | this.playerWidth = playerWidth; | |
| 736 | this.playerHeight = playerHeight; | |
| 737 | ||
| 738 | var aspect = playerWidth / playerHeight; | |
| 739 | ||
| 740 | var excessWidth = 0; | |
| 741 | if (aspect > this.config.screen.aspect) {
| |
| 742 | excessWidth = playerWidth - playerHeight * this.config.screen.aspect; | |
| 743 | } | |
| 744 | ||
| 745 | this.scale = this.config.screen.scale * playerHeight / this.config.screen.size[1]; | |
| 746 | ||
| 747 | var borderSize = this.getBorderSize(); | |
| 748 | var width = this.scale * this.config.screen.size[0]; | |
| 749 | var height = this.scale * this.config.screen.size[1]; | |
| 750 | ||
| 751 | this.$mouseBox.css({
| |
| 752 | position: 'absolute', | |
| 753 | left: excessWidth / 2 + (playerWidth - width - excessWidth) * this.config.screen.position[0] - borderSize, | |
| 754 | top: (playerHeight - height) * this.config.screen.position[1] - borderSize, | |
| 755 | width: width, | |
| 756 | height: height | |
| 757 | }); | |
| 758 | ||
| 759 | if (!this.component('settings').$chatSettings.is(':visible')) {
| |
| 760 | this.$mouseBox.stop(true, true).css({ background: 'transparent' });
| |
| 761 | return; | |
| 762 | } | |
| 763 | ||
| 764 | this.$mouseBox | |
| 765 | .stop(true, true) | |
| 766 | .animate({ backgroundColor: 'rgba(255, 255, 255, 0.5)' }, 100)
| |
| 767 | .delay(1000) | |
| 768 | .animate({ backgroundColor: 'rgba(255, 255, 255, 0)' })
| |
| 769 | .animate({ background: 'transparent' }, 0);
| |
| 770 | }; | |
| 771 | ||
| 772 | Touch.prototype.update = function(force) {
| |
| 773 | if (!this.entity.loaded) { return; }
| |
| 774 | if (!this.config.enabled) { return; }
| |
| 775 | ||
| 776 | this.updateMouseBox(force); | |
| 777 | }; | |
| 778 | ||
| 779 | Touch.prototype.onClick = function(e) {
| |
| 780 | var touch = this.getTouchPosition(e); | |
| 781 | if (!touch.valid) { return; }
| |
| 782 | this.component('chat').setInput(touch.input);
| |
| 783 | if (this.config.showDroplets) {
| |
| 784 | this.spawnDroplet(touch.mouse); | |
| 785 | } | |
| 786 | }; | |
| 787 | ||
| 788 | Touch.prototype.onMove = function(e) {
| |
| 789 | if (!this.config.showCoordTooltip) { return; }
| |
| 790 | var touch = this.getTouchPosition(e); | |
| 791 | var borderSize = this.getBorderSize(); | |
| 792 | this.$coordTooltip | |
| 793 | .text(touch.valid ? touch.input : '') | |
| 794 | .css({
| |
| 795 | position: 'absolute', | |
| 796 | left: touch.mouse[0] + borderSize + 15, | |
| 797 | top: touch.mouse[1] + borderSize - this.$coordTooltip.outerHeight() / 2 | |
| 798 | }); | |
| 799 | }; | |
| 800 | ||
| 801 | module.exports = Touch; | |
| 802 | ||
| 803 | },{"component":3,"util2":10}],10:[function(require,module,exports){
| |
| 804 | /* | |
| 805 | * util2.js by Meiguro - MIT License | |
| 806 | */ | |
| 807 | ||
| 808 | var util2 = (function(){
| |
| 809 | ||
| 810 | var util2 = {};
| |
| 811 | ||
| 812 | util2.noop = function() {};
| |
| 813 | ||
| 814 | util2.copy = function(a, b) {
| |
| 815 | b = b || (a instanceof Array ? [] : {});
| |
| 816 | for (var k in a) { b[k] = a[k]; }
| |
| 817 | return b; | |
| 818 | }; | |
| 819 | ||
| 820 | util2.inherit = function(child, parent, proto) {
| |
| 821 | child.prototype = Object.create(parent.prototype); | |
| 822 | child.prototype.constructor = child; | |
| 823 | if (proto) {
| |
| 824 | util2.copy(proto, child.prototype); | |
| 825 | } | |
| 826 | return child.prototype; | |
| 827 | }; | |
| 828 | ||
| 829 | if (typeof module !== 'undefined') {
| |
| 830 | module.exports = util2; | |
| 831 | } | |
| 832 | ||
| 833 | return util2; | |
| 834 | ||
| 835 | })(); | |
| 836 | ||
| 837 | },{}],11:[function(require,module,exports){
| |
| 838 | /* global unsafeWindow */ | |
| 839 | module.exports = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window; | |
| 840 | ||
| 841 | },{}]},{},[1]) |