Skip to content

Instantly share code, notes, and snippets.

@nabbynz
Last active April 30, 2020 22:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nabbynz/a20de82573eb674f88b63e04e8c5c58d to your computer and use it in GitHub Desktop.
Save nabbynz/a20de82573eb674f88b63e04e8c5c58d to your computer and use it in GitHub Desktop.
TagPro Tiles Mixer
// ==UserScript==
// @name TagPro Tiles Mixer
// @description Mix & match tiles from the different tiles.png textures.
// @version 0.6.0
// @include https://tagpro.koalabeast.com/textures/
// @updateURL https://gist.github.com/nabbynz/a20de82573eb674f88b63e04e8c5c58d/raw/TagPro_Tiles_Mixer.user.js
// @downloadURL https://gist.github.com/nabbynz/a20de82573eb674f88b63e04e8c5c58d/raw/TagPro_Tiles_Mixer.user.js
// @grant none
// @author nabby
// ==/UserScript==
console.log('START: ' + GM_info.script.name + ' (v' + GM_info.script.version + ' by ' + GM_info.script.author + ')');
//Create "Mixer" tab...
$('ul.tab-list').append('<li data-target="#TTM_Container"><a>Tiles Mixer</a></li>');
$('div.tab-content').append('<div id="TTM_Container" class="tab-pane" style="padding:0px; text-align:center; font-size:12px; user-select:none"></div>');
$('#TTM_Container').append('<div id="TTM_Tiles_Outer" style="display:inline-block; position:relative; vertical-align:top; margin:10px; padding:0px; border:6px ridge yellow; border-radius:8px;"></div>');
$('#TTM_Tiles_Outer').append('<div id="TTM_Tiles_Header" style="position:relative; display:flex; justify-content:space-between; align-items:center; margin:10px; padding:0px; height:30px; background:#444; border:1px outset #777; border-radius:5px; z-index:3"></div>');
$('#TTM_Tiles_Header').append('<div><select id="TTM_Textures" style="margin:0 5px; color:black; font-size:13px; width:165px; border-radius:8px; outline:none; border:none; background:linear-gradient(#999, #ccc, #777);"></select>' +
'<button id="TTM_UpdateCTL" style="color:#000; border-radius:10px; margin:0 5px; background:#999; border:1px outset #ccc; padding:0 3px; outline:none;">Refresh</button></div>');
$('#TTM_Tiles_Header').append('<label style="display:none;">FreeMove:<input type="checkbox" id="TTM_FreeMove"></label>');
$('#TTM_Tiles_Header').append('<select id="TTM_Select_Shape" style="margin:0 5px; color:black; font-size:11px; border-radius:3px; outline:none; border:none;" title="Texture clip size (good for clipping from dragged images, or resizing to pixel perfect)">' +
' <option value="square40" data-size="40" data-shape="square" title="40px Square Tile (Default)">Default</option>' +
' <option value="circle38" data-size="38" data-shape="circle" title="38px Circle (Balls)">Balls</option>' +
' <option value="circle30" data-size="30" data-shape="circle" title="30px Circle (Bombs & Powerups)">Bombs & Powerups</option>' +
' <option value="circle28" data-size="28" data-shape="circle" title="28px Circle (Spike)">Spike</option>' +
' <option value="circle16" data-size="16" data-shape="circle" title="16px Circle (Button)">Button</option>' +
'</select>');
$('#TTM_Tiles_Header').append('<div><button id="TTM_Copy_All" style="color:#fff; border-radius:10px; margin:0 5px; background:#333; border:1px outset #4fa; padding:0 6px; outline:none;">Copy All</button>' +
'<button id="TTM_Copy_Walls" style="color:#fff; border-radius:10px; margin:0 5px; background:#333; border:1px outset #4fa; padding:0 6px; outline:none;">Copy Walls</button>' +
'<button id="TTM_Copy_Right" style="color:#fff; border-radius:10px; margin:0 5px; background:#333; border:1px outset #4fa; padding:0 6px; outline:none;">Copy Right</button></div>');
$('#TTM_Tiles_Outer').append('<div id="TTM_Tiles" style="position:relative; margin:10px; padding:0px; width:640px; height:440px; text-align:left; overflow:hidden;"></div>');
$('#TTM_Tiles').append('<div id="TTM_Tiles_Cover" style="position:absolute; margin:0; padding:0px; width:640px; height:440px; z-index:2;"></div>');
$('#TTM_Tiles').append('<canvas id="TTM_Tiles_Canvas">');
$('#TTM_Container').append('<div id="TTM_New_Outer" style="display:inline-block; position:relative; vertical-align:top; margin:10px; padding:0px; border:6px ridge chartreuse; border-radius:8px;"></div>');
$('#TTM_New_Outer').append('<div id="TTM_New_Header" style="position:relative; display:flex; justify-content:space-between; align-items:center; margin:10px; padding:0px; height:30px; background:#444; border:1px outset #777; border-radius:5px; z-index:3;"></div>');
$('#TTM_New_Header').append('<div><button id="TTM_Clear_All" style="color:#fff; border-radius:10px; margin:0 5px; background:#333; border:1px outset #f74; padding:0 6px; outline:none;">Clear All</button>' +
'<button id="TTM_Clear_Walls" style="color:#fff; border-radius:10px; margin:0 5px; background:#333; border:1px outset #f74; padding:0 6px; outline:none;">Clear Walls</button>' +
'<button id="TTM_Clear_Right" style="color:#fff; border-radius:10px; margin:0 5px; background:#333; border:1px outset #f74; padding:0 6px; outline:none;">Clear Right</button></div>');
$('#TTM_New_Header').append('<div id="TTM_ModifyMenu_Container" style="display:none; position:absolute; width:520px; height=200px; top:25px; right:240px; background:#223; border:5px ridge #aab; border-radius:5px;"></div>');
$('#TTM_ModifyMenu_Container').append('<div id="TTM_ModifyMenu_Inner" style="padding:10px; display:flex; flex-flow:column; align-items:center;">' +
' <div style="margin:0 0 5px; padding:0 0 5px; width:100%; border-bottom:1px solid #888;">' +
' <label title="" style="display:flex; justify-content:center; align-items:center; white-space:nowrap;"><span>Hue Rotate: </span><span style="margin:0 10px"><input type="range" id="TTM_TileHue" value="0" min="0" max="360" style="width:180px"></span><span id="TTM_TileHue_Value">0</span>&deg;</label>' +
' <span style="font-size:11px; font-style:italic;">Note: This only affects colors (not greys).</span>' +
' </div>' +
' <div>' +
' <label title="Less than 100 is lower. Over 100 is higher. Unchanged is 100.">Brightness:<input type="number" id="TTM_Brightness" value="100" min="0" max="5000""></label>' +
' <label title="Less than 100 is lower. Over 100 is higher. Unchanged is 100.">Contrast:<input type="number" id="TTM_Contrast" value="100" min="0" max="5000""></label>' +
' <label title="Less than 100 is lower. Over 100 is higher. Unchanged is 100.">Saturation:<input type="number" id="TTM_Saturation" value="100" min="0" max="5000""></label>' +
' <label title="Less than 100 is lower. Over 100 is higher. Unchanged is 100.">Sepia:<input type="number" id="TTM_Sepia" value="0" min="0" max="100""></label>' +
' </div>' +
' <div style="margin-top:5px; border:1px inset #ccc; border-radius:7px;">' +
' <div id="TTM_Presets" style="display:inline-block; border-radius:5px; margin:3px; color:black; background:#c7c7c7; padding:2px 3px;">Presets: </div>' +
' <div style="display:flex; flex-flow:column wrap; align-items:center; max-height:320px; width:500px;">' +
' <div class="TTM_Add_Container">' +
' <label title=""><input type="checkbox" id="TTM_Add_Checkered" data-saveto="checkered" data-group="TTM_Group_Add_Checkered">Add Checkered</label>' +
' <div class="TTM_Group_Add_Checkered" style="display:none">' +
' <label title="">Size: <input type="number" min="1" max="40" value="20" data-saveto="checkered_size"></label>' +
' <label title="">Color: <input type="color" value="#444444" data-saveto="checkered_color"></label>' +
' <label title="">Alt: <input type="number" min="-100" max="100" value="-20" data-saveto="checkered_alt"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" value="100" data-saveto="checkered_opacity"></label>' +
' </div>' +
' </div>' +
' <div class="TTM_Add_Container">' +
' <label title=""><input type="checkbox" id="TTM_Add_Pattern" data-saveto="pattern" data-group="TTM_Group_Add_Pattern">Add Pattern</label>' +
' <div class="TTM_Group_Add_Pattern" style="display:none">' +
' <label title="">Shape: <select data-saveto="pattern_shape">' +
' <option value="square">Square</option>' +
' <option value="circle">Circle</option>' +
' <option value="rightangle">Right Angle</option>' +
' <option value="pyramid">Pyramid</option>' +
' <option value="corner">Corner</option>' +
' </select></label>' +
' <label title="">Color: <input type="color" data-saveto="pattern_color"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" value="100" data-saveto="pattern_opacity"></label>' +
' <label title="">Spacing: <input type="number" min="1" max="40" value="10" data-saveto="pattern_size"></label>' +
' <label title="">Width: <input type="number" min="1" max="40" value="8" data-saveto="pattern_margin"></label>' +
' <label title="">Stroke: <input type="checkbox" data-saveto="pattern_stroke" style="width:11px; height:11px;"></label>' +
' <label title="">Fill: <input type="checkbox" data-saveto="pattern_fill" checked style="width:11px; height:11px;"></label>' +
' </div>' +
' </div>' +
' <div class="TTM_Add_Container">' +
' <label title=""><input type="checkbox" id="TTM_Add_Stripes" data-saveto="stripes" data-group="TTM_Group_Add_Stripes">Add Stripes</label>' +
' <div class="TTM_Group_Add_Stripes" style="display:none">' +
' <label title="">Type: <select data-saveto="stripes_direction">' +
' <option value="horizontal">Horizontal (-)</option>' +
' <option value="vertical">Vertical (|)</option>' +
' <option value="diagonal" selected>Diagonal (\\)</option>' +
' <option value="diagonalback">Diagonal (/)</option>' +
' <option value="plus">Plus (+)</option>' +
' <option value="cross">Cross (X)</option>' +
' </select></label>' +
' <label title="">Size: <input type="number" min="1" max="40" value="10" data-saveto="stripes_size"></label>' +
' <label title="">Line Width: <input type="number" min="1" max="40" value="1" data-saveto="stripes_linewidth"></label>' +
' <label title="">Color: <input type="color" value="#ffffff" data-saveto="stripes_color"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" value="40" data-saveto="stripes_opacity"></label>' +
' </div>' +
' </div>' +
' <div class="TTM_Add_Container">' +
' <label title=""><input type="checkbox" id="TTM_Add_Specks" data-saveto="specks" data-group="TTM_Group_Add_Specks">Add Randoms</label>' +
' <div class="TTM_Group_Add_Specks" style="display:none">' +
' <label title="">Color: <input type="color" data-saveto="specks_color"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" value="50" data-saveto="specks_opacity"></label>' +
' <label title="">Length: <input type="number" min="1" max="20" value="7" data-saveto="specks_length"></label>' +
' <label title="">Count: <input type="number" min="1" max="300" value="20" data-saveto="specks_count"></label>' +
' <label title="0=Random Angles">Angle: <input type="number" min="0" max="360" value="315" data-saveto="specks_angle"></label>' +
' </div>' +
' </div>' +
' <div class="TTM_Add_Container">' +
' <label title=""><input type="checkbox" id="TTM_Add_Shine" data-saveto="shine" data-group="TTM_Group_Add_Shine">Add Shine</label>' +
' <div class="TTM_Group_Add_Shine" style="display:none">' +
' <label title="">X: <input type="number" min="-40" max="40" value="10" data-saveto="shine_x"></label>' +
' <label title="">Y: <input type="number" min="-40" max="40" value="10" data-saveto="shine_y"></label>' +
' <label title="Radius">R: <input type="number" min="1" max="80" value="50" data-saveto="shine_radius"></label>' +
' <label title="">Inner: <input type="color" value="#ffffff" data-saveto="shine_color_inner"></label>' +
' <label title="">Outer: <input type="color" value="#ffffff" data-saveto="shine_color_outer"></label>' +
' <label title="">Opacity: <input type="number" min="0" max="100" value="25" data-saveto="shine_opacity_inner"></label>' +
' <label title="">Opacity: <input type="number" min="0" max="100" value="5" data-saveto="shine_opacity_outer"></label>' +
' <label title="">Behind?: <input type="checkbox" data-saveto="shine_behind"></label>' +
' </div>' +
' </div>' +
' <div class="TTM_Add_Container">' +
' <label title=""><input type="checkbox" id="TTM_Add_Border" data-saveto="border" data-group="TTM_Group_Add_Border">Add Border</label>' +
' <div class="TTM_Group_Add_Border" style="display:none">' +
' <label title="">Color: <input type="color" data-saveto="border_color"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" value="100" data-saveto="border_opacity"></label>' +
' <label title="">Circle?: <input type="checkbox" data-saveto="border_circle"></label>' +
' <label title="">Size: <input type="number" min="1" max="40" value="40" data-saveto="border_size"></label>' +
' <label title="">Width: <input type="number" min="1" max="40" value="1" data-saveto="border_linewidth"></label>' +
' <label title="">Dash: <input type="number" min="1" max="40" value="1" data-saveto="border_dash"></label>' +
' </div>' +
' </div>' +
' </div>' +
' </div>' +
' <div>' +
' <label style="font-weight:normal;"><input type="checkbox" id="TTM_Tint">Tint</label>' +
' <div id="TTM_Tint_Group" style="display:inline; margin:0 0 2px 5px; background:#555; padding:2px; border-radius:2px;">' +
' <label style="font-weight:normal; margin:0;">Color: <input id="TTM_Tint_Color" type="color" value="#ff0000" style="height:17px; border:none;"></label>' +
' <select style="margin:0 5px; color:black; font-size:11px; border-radius:5px; outline:none; border:none;" title="Method 1 is usually best, but some images get better results using a different tinting method.">' +
' <option value="desaturation" title="Desaturation">Method 1</option>' +
' <option value="decomposition" title="Decomposition">Method 2</option>' +
' <option value="brightness" title="Brightness">Method 3</option>' +
' <option value="simple" title="Simple Overlay">Method 4</option>' +
' </select>' +
' <div id="TTM_TintMenu_Message" style="font-size:11px; font-style:italic; color:coral;">Hue is also being rotated</div>' +
' </div>' +
' </div>' +
' <div style="display:flex; align-items:center; border:4px groove #999; padding:6px 16px; border-radius:10px;">' +
' <canvas id="TTM_ModifySourceTilePreview" width="40" height="40" title="Source Preview"></canvas> <span style="font-size:26px; padding:0 12px;">&#10144;</span> <canvas id="TTM_ModifyDestTilePreview" width="40" height="40" title="Target Preview"></canvas>' +
' </div>' +
' <label style="font-weight:normal;" title="Applies the filters to the source tile (left)."><input type="checkbox" id="TTM_Modify_CopySource">Source Tile</label>' +
' <div id="TTM_Modify_Message" style="color:red; font-style:italic; text-align:center;">No target tile selected</div>' +
' <div>' +
' <button id="TTM_Reset_Tile" style="color:#fff; border-radius:10px; margin:10px 10px 0; background:#333; border:1px outset #fff; padding:0 6px; outline:none;" title="Resets all the option values to the defaults">Reset</button>' +
' <button id="TTM_Apply_Tile" style="color:#fff; border-radius:10px; margin:10px 10px 0; background:#333; border:1px outset #fff; padding:0 6px; outline:none;" title="Apply the changes to the new tile below">Apply</button>' +
' </div>' +
'</div>');
$('#TTM_New_Header').append('<div><button id="TTM_Show_ModifyMenu" style="color:#fff; border-radius:10px; margin:0 5px; background:#333; border:1px outset #07b; padding:0 6px; outline:none;">Modify</button></div>');
$('#TTM_New_Header').append('<div id="TTM_Preview" style="color:#fff; text-shadow:1px 1px 1px black; margin:0 5px; background:green; border:1px dashed #aaa; padding:0 6px; outline:none; cursor:default;">Preview</div>');
$('#TTM_New_Header').append('<a href="#" id="TTM_Save" style="color:#fff; border-radius:10px; margin:0 5px; background:dodgerblue; border:1px outset #aaa; padding:0 6px; outline:none;" download="tiles.png" title="Save as tiles.png so you can edit them or upload it to imgur later">Save to PNG</a>');
$('#TTM_New_Header').append('<div id="TTM_Imgur_PreviewWindow" style="position:absolute; display:none; top:0; right:0; background:#333; padding:10px; border:1px solid red; border-radius:4px; box-shadow:0 0 10px 1px pink; z-index:1;">' +
' <div id="TTM_Imgur_PreviewWindow_Info" style="position:absolute; display:inline-block; top:2px; left:2px; width:16px; height:16px; color:#fff; border:1px outset white; border-radius:50%; cursor:pointer;" title="Info">?</div>' +
' <div id="TTM_Imgur_PreviewWindow_Title" style="color:#000; background:#ccc; border-radius:5px; width:90%; margin:0 auto 10px; font-size:14px;"></div>' +
' <div id="TTM_Imgur_PreviewWindow_Close" style="position:absolute; display:inline-block; top:2px; right:2px; width:16px; height:16px; color:#fff; border:1px outset red; border-radius:50%; cursor:pointer;" title="Close">X</div>' +
' <img id="TTM_Imgur_PreviewWindow_Image" src="" style="background:#000; width:480px; height:330px;" title="">' +
' <div style="display:flex; justify-content:space-around; margin:10px 0 0;">' +
' <div id="TTM_Imgur_LoadToMixer" class="TTM_Imgur_Button">Load into Mixer</div>' +
' <div id="TTM_Imgur_ViewOnImgur" class="TTM_Imgur_Button" title="Opens in new tab...">View on Imgur</div>' +
' <div id="TTM_Imgur_SaveToTiles" class="TTM_Imgur_Button" title="Save to the &quot;Import Custom&quot; tab">Save as Game Tiles</div>' +
' <div id="TTM_Imgur_Rename" class="TTM_Imgur_Button">Rename</div>' +
' <div id="TTM_Imgur_Delete" class="TTM_Imgur_Button">Delete</div>' +
' </div>' +
'</div>');
$('#TTM_New_Header').append('<div id="TTM_Imgur_MenuContainer" style="display:none; position:absolute; width:200px; max-height:280px; overflow-y:auto; top:25px; right:0px; background:#502222; border:5px ridge #d33; border-radius:5px;">' +
' <div id="TTM_Imgur_MenuInner" style="position:relative; padding:10px;">' +
' <a href="" id="TTM_Imgur_Upload" style="color:#fff; border-radius:10px; margin:0 5px; background:red; border:1px outset #aaa; padding:0 6px; outline:none;" title="Upload to imgur">Upload to Imgur</a><span id="TTM_Imgur_Spinner"></span>' +
' </div>' +
'</div>');
$('#TTM_New_Header').append('<div><button id="TTM_Imgur_ShowMenu" style="color:#fff; border-radius:10px; margin:0 5px; background:#d33; border:1px outset #999; padding:0 6px; outline:none;">Imgur</button></div>');
$('#TTM_New_Outer').append('<div id="TTM_New" style="position:relative; margin:10px; padding:0px; width:640px; height:440px; overflow:hidden;"></div>');
$('#TTM_New').append('<div id="TTM_New_Cover" style="position:absolute; margin:0px; padding:0px; width:640px; height:440px; z-index:2;"></div>');
$('#TTM_New').append('<canvas id="TTM_New_Canvas" width="640" height="440">');
$('#TTM_New_Outer').append('<div id="TTM_New_Footer" style="position:relative; display:flex; justify-content:center; align-items:center; margin:10px; padding:0px; background:#444; border:1px outset #777; border-radius:5px;"></div>'); //width:640px; height:30px;
$('#TTM_New_Footer').append('<button id="TTM_QuickSave" style="color:#fff; border-radius:10px; margin:5px; background:#333; border:1px outset dodgerblue; padding:0px 6px; outline:none;">Quick Save</button>');
$('#TTM_New_Footer').append('<div id="TTM_QuickSaves" style="position:relative; display:flex; flex-flow:row; justify-content:flex-start; width:536px; margin:0 5px; padding:5px 0; overflow-x:auto; overflow-y:hidden;"></div>');
$('#TTM_Tiles').append('<div id="TTM_Tiles_MouseSquare" style="position:absolute; display:inline-block; left:-9999px; top:-9999px; width:40px; height:40px; border:1px solid white; z-index:1;"></div>');
$('#TTM_New').append('<div id="TTM_New_MouseSquare" style="position:absolute; display:inline-block; left:-9999px; top:-9999px; width:40px; height:40px; border:1px dashed white; z-index:1;"></div>');
$('#TTM_New').append('<div id="TTM_New_MouseSquareFixed" style="position:absolute; display:inline-block; left:-9999px; top:-9999px; width:40px; height:40px; border:1px solid chartreuse; box-shadow:0px 0px 18px 7px #fff"></div>');
addStyle('#TTM_ModifyMenu_Inner input, #TTM_ModifyMenu_Inner select, TTM_ModifyMenu_Inner label { margin:2px; color:black; font-weight:normal; }');
addStyle('#TTM_ModifyMenu_Inner label { font-weight:normal; margin:1px; }');
addStyle('.TTM_Saved { position:relative; margin:3px; padding:1px 5px; color:#bbb; background:#333; font-size:11px; border:1px inset #555; border-radius:5px; cursor:pointer; white-space:nowrap; }');
addStyle('.TTM_DeleteSaved { display:inline-block; margin:0 0 0 3px; width:12px; height:12px; top:0px; right:14px; color:white; background:red; opacity:0.5; font-size:9px; text-align:center; border-radius:50%; cursor:pointer; }');
addStyle('.TTM_ViewImage { display:inline-block; margin:0 0 0 3px; width:12px; height:12px; top:0px; right:0px; color:white !important; background:green; font-size:9px; text-align:center; border-radius:50%; cursor:pointer; }');
addStyle('.TTM_Imgur_Button { background:#555; border-radius:3px; padding:0 5px; color:white !important; cursor:pointer; }');
addStyle('.TTM_Imgur_Button:hover { background:#777; }');
addStyle('.TTM_SetLinkToTiles { display:inline-block; margin:0 0 0 3px; width:12px; height:12px; top:0px; right:0px; color:white; background:orange; font-size:9px; text-align:center; border-radius:50%; cursor:pointer; }');
addStyle('.TTM_Add_Container { display:flex; flex-flow:column wrap; width:245px; border:1px outset #ccc; margin:2px; border-radius:5px; }');
addStyle('.TTM_Preset { display:inline-block; width:18px; font:10px Arial; background:#eee; border:1px solid #777; border-radius:3px; box-shadow:1px 1px 1px #555; margin:1px 2px 1px 0; padding:1px 0; cursor:pointer; }');
addStyle('.TTM_Preset:hover { background:#f00; color:#fff; }');
addStyle('@keyframes TTM_Spinner { to {transform:rotate(360deg);} }');
addStyle('.TTM_Loading:after { content: ""; box-sizing:border-box; position:absolute; width:20px; height:20px; margin-top:-3px; margin-left:4px; border-radius:50%; border-top:2px solid #f70; border-right:2px solid transparent; animation:TTM_Spinner .6s linear infinite; }');
let tilesTarget = {x:null, y:null};
let tilesCtx;
let newCtx = $("#TTM_New_Canvas").get(0).getContext("2d");
let newCtxDataUrl;
let tilesImg = document.createElement('img');
let speedpadImg = document.createElement('img');
let portalImg = document.createElement('img');
let newImg = document.createElement('img');
let randomPup = Math.floor(Math.random()*3);
let fixedTarget = false;
let freeMove = false;
let selectorSize = 40;
let tilesHover = $('#TTM_Tiles_MouseSquare');
let newHover = $('#TTM_New_MouseSquare');
let newHoverFixed = $('#TTM_New_MouseSquareFixed');
let draggedData;
let previewCanvas = document.createElement('canvas');
let tempCanvas = document.createElement('canvas');
let imgurClientId = '1feeb5b9d9cb0c5'; //don't steal my client-id! get your own very quickly from here: https://api.imgur.com/oauth2/addclient
const tileNames = {
'4800': { name:'Spike', tx:480, ty:0 },
'5200': { name:'Gravity Well', tx:520, ty:0 },
'5600': { name:'Red Ball', tx:560, ty:0 },
'6000': { name:'Blue Ball', tx:600, ty:0 },
'48040': { name:'Bomb', tx:480, ty:40 },
'52040': { name:'Yellow Flag', tx:520, ty:40 },
'56040': { name:'Red Flag', tx:560, ty:40 },
'60040': { name:'Blue Flag', tx:600, ty:40 },
'48080': { name:'Bomb (Detonated)', tx:480, ty:80 },
'52080': { name:'Yellow Flag (Taken)', tx:520, ty:80 },
'56080': { name:'Red Flag (Taken)', tx:560, ty:80 },
'60080': { name:'Blue Flag (Taken)', tx:600, ty:80 },
'480120': { name:'Neutral Gate', tx:480, ty:120 },
'520120': { name:'Green Gate', tx:520, ty:120 },
'560120': { name:'Red Gate', tx:560, ty:120 },
'600120': { name:'Blue Gate', tx:600, ty:120 },
'480160': { name:'Juke Juice', tx:480, ty:160 },
'520160': { name:'Floor Tile', tx:520, ty:160 },
'560160': { name:'Red TeamTile', tx:560, ty:160 },
'600160': { name:'Blue TeamTile', tx:600, ty:160 },
'480200': { name:'Rolling Bomb', tx:480, ty:200 },
'520200': { name:'[Empty]', tx:520, ty:200 },
'560200': { name:'Red Endzone', tx:560, ty:200 },
'600200': { name:'Blue Endzone', tx:600, ty:200 },
'480240': { name:'TagPro', tx:480, ty:240 },
'520240': { name:'Button', tx:520, ty:240 },
'560240': { name:'Yellow Potato', tx:560, ty:240 },
'600240': { name:'Yellow Potato (Taken)', tx:600, ty:240 },
'480280': { name:'Top Speed', tx:480, ty:280 },
'520280': { name:'[Empty]', tx:520, ty:280 },
'560280': { name:'Red Potato', tx:560, ty:280 },
'600280': { name:'Red Potato (Taken)', tx:600, ty:280 },
'480320': { name:'Powerup (Taken)', tx:480, ty:320 },
'520320': { name:'[Empty]', tx:520, ty:320 },
'560320': { name:'Blue Potato', tx:560, ty:320 },
'600320': { name:'Blue Potato (Taken)', tx:600, ty:320 },
'480360': { name:'Mars Ball (Top Left)', tx:480, ty:360 },
'520360': { name:'Mars Ball (Top Right)', tx:520, ty:360 },
'560360': { name:'[Empty]', tx:560, ty:360 },
'600360': { name:'[Empty]', tx:600, ty:360 },
'480400': { name:'Mars Ball (Bottom Left)', tx:480, ty:400 },
'520400': { name:'Mars Ball (Bottom Right)', tx:520, ty:400 },
'560400': { name:'[Empty]', tx:560, ty:400 },
'600400': { name:'[Empty]', tx:600, ty:400 },
};
//Bind events...
$('.tab-list').on('click', 'li', function() {
$(this).parents('.tab-list').find('li').removeClass('active');
$(this).parents('.tab-list').parent().find('.tab-pane').removeClass('active');
$(this).addClass('active');
$( $(this).data('target') ).addClass('active');
});
$('#TTM_Tiles_Cover').on('mousemove', function(e) {
let x;
let y;
let mouseOffset = 40;
let sourceTileName = '';
let title = '';
if (freeMove) {
x = e.offsetX - mouseOffset;
y = e.offsetY - mouseOffset;
} else {
let sizeOffset = (40 - selectorSize) / 2;
x = Math.floor(e.offsetX/40)*40 + sizeOffset;
y = Math.floor(e.offsetY/40)*40 + sizeOffset;
let sourceKey = ''+(x-sizeOffset)+(y-sizeOffset);
if (tileNames.hasOwnProperty(sourceKey)) sourceTileName = tileNames[sourceKey].name;
else sourceTileName = 'Wall Tile';
if (fixedTarget) {
let fx = parseInt(newHoverFixed.css('left'));
let fy = parseInt(newHoverFixed.css('top'));
let targetKey = ''+fx+fy;
let targetTileName = 'Wall Tile';
if (tileNames.hasOwnProperty(targetKey)) targetTileName = tileNames[targetKey].name;
title += 'Copy to FIXED target...\n';
title += sourceTileName + ' -> ' + targetTileName;
title += '\n[x:'+x+', y:'+y+']';
} else {
title += 'Copy...\n';
title += sourceTileName;
title += '\n[x:'+x+', y:'+y+']';
}
}
//tilesHover.css({ 'left':x, 'top':y, 'border-color':fixedTarget?'rgba(255,0,0,0.5)':'white' });
tilesHover.css({ 'left':x, 'top':y, 'border':fixedTarget?'2px dashed rgba(0,255,255,0.8)':'1px solid white' });
$(this).attr('title', title);
}).on('mouseenter', function() {
tilesHover.show();
}).on('mouseleave', function() {
tilesHover.hide();
});
$('#TTM_Tiles_Cover').on('click', function(e) {
let x = parseInt( tilesHover.css('left') );
let y = parseInt( tilesHover.css('top') );
let isCircle = ( $('#TTM_Select_Shape').find(':selected').data('shape') === 'circle' ? true : false );
copyTiles(x, y, selectorSize, selectorSize, (fixedTarget ? tilesTarget.x : x), (fixedTarget ? tilesTarget.y : y), selectorSize, selectorSize, isCircle);
});
$('#TTM_New_Cover').on('mousemove', function(e) {
let x = Math.floor(e.offsetX/40)*40;
let y = Math.floor(e.offsetY/40)*40;
let key = ''+x+y;
let title = 'Click to set as target tile.';
let tileName = '';
if (tileNames.hasOwnProperty(key)) tileName = tileNames[key].name;
else tileName = 'Wall Tile';
if (fixedTarget && (x === parseInt(newHoverFixed.css('left'))) && (y === parseInt(newHoverFixed.css('top'))) ) title = 'Click to unset target tile.';
newHover.css({'left':x, 'top':y});
$(this).attr('title', title + '\n' + tileName + ' [x:'+x+', y:'+y +']');
}).on('mouseenter', function() {
newHover.show();
}).on('mouseleave', function() {
newHover.hide();
});
$('#TTM_New_Cover').on('click', function(e) {
let x = parseInt( newHover.css('left') );
let y = parseInt( newHover.css('top') );
let mx = parseInt( newHoverFixed.css('left') );
let my = parseInt( newHoverFixed.css('top') );
if ((x === mx) && (y === my)) {
tilesTarget.x = null;
tilesTarget.y = null;
fixedTarget = false;
newHoverFixed.css({'left':-9999, 'top':-9999});
} else {
tilesTarget.x = x;
tilesTarget.y = y;
fixedTarget = true;
newHoverFixed.css({'left':x, 'top':y});
}
let sx = x;
let sy = y;
let sw = 40;
let sh = 40;
if (x < 480) {
sx = 0;
sy = 0;
sw = 480;
sh = 440;
}
tempCanvas.width = sw;
tempCanvas.height = sh;
let tempCtx = tempCanvas.getContext("2d");
tempCtx.drawImage($('#TTM_Modify_CopySource').is(':checked') ? tilesCtx.canvas : newCtx.canvas, sx,sy,sw,sh, 0,0,sw,sh);
updateModifyTilePreviews();
});
$('#TTM_FreeMove').on('click', function() {
if (this.checked) {
freeMove = true;
} else {
freeMove = false;
}
});
$('#TTM_Select_Shape').on('change', function() {
selectorSize = $(this).find(':selected').data('size');
let borderRadius = ( $(this).find(':selected').data('shape') === 'circle' ? '50%' : '0' );
tilesHover.css({ 'width':selectorSize+'px', 'height':selectorSize+'px', 'border-radius':borderRadius });
});
$('#TTM_Show_ModifyMenu').on('click', function() {
$('#TTM_ModifyMenu_Container').slideToggle();
});
$('#TTM_Tint').on('click', function() {
$('#TTM_Tint_Group').fadeToggle();
if ($('#TTM_Tint').is(':checked') && $('#TTM_TileHue').val() > 0) $('#TTM_TintMenu_Message').show();
else $('#TTM_TintMenu_Message').hide();
});
$('#TTM_TileHue').on('input', function() {
$('#TTM_TileHue_Value').text(this.value);
if ($('#TTM_Tint').is(':checked') && $('#TTM_TileHue').val() > 0) $('#TTM_TintMenu_Message').show();
else $('#TTM_TintMenu_Message').hide();
});
$('#TTM_ModifyMenu_Inner').find('input, select').on('click', function() {
let group = this.dataset.group;
if (group) {
if ( $(this).is(':checked') || ($(this).val() > 0) ) $('#TTM_ModifyMenu_Inner').find('.'+group).fadeIn();
else $('#TTM_ModifyMenu_Inner').find('.'+group).fadeOut();
}
updateModifyTilePreviews(false);
});
$('#TTM_Reset_Tile').on('click', function() {
$('#TTM_TileHue').val('0');
$('#TTM_TileHue_Value').text('0');
$('#TTM_Sepia').val('0');
$('#TTM_Brightness').val('100');
$('#TTM_Contrast').val('100');
$('#TTM_Saturation').val('100');
$('#TTM_Add_Checkered').prop('checked', false);
$('#TTM_ModifyMenu_Inner').find('.TTM_Group_Add_Checkered').hide();
$('#TTM_Add_Pattern').prop('checked', false);
$('#TTM_ModifyMenu_Inner').find('.TTM_Group_Add_Pattern').hide();
$('#TTM_Add_Stripes').prop('checked', false);
$('#TTM_ModifyMenu_Inner').find('.TTM_Group_Add_Stripes').hide();
$('#TTM_Add_Specks').prop('checked', false);
$('#TTM_ModifyMenu_Inner').find('.TTM_Group_Add_Specks').hide();
$('#TTM_Add_Shine').prop('checked', false);
$('#TTM_ModifyMenu_Inner').find('.TTM_Group_Add_Shine').hide();
$('#TTM_Add_Border').prop('checked', false);
$('#TTM_ModifyMenu_Inner').find('.TTM_Group_Add_Border').hide();
$('#TTM_Tint').prop('checked', false);
$('#TTM_Tint_Group').hide();
$('#TTM_Modify_CopySource').prop('checked', false);
$('#TTM_Tint_Color').val('#FF0000');
updateModifyTilePreviews();
});
$('#TTM_Apply_Tile').on('click', function() {
let x = parseInt( newHoverFixed.css('left') );
let y = parseInt( newHoverFixed.css('top') );
if (x < 480) {
tintTiles(0, 0, 480, 440, true, true);
} else {
tintTiles(x, y, 40, 40, true, false);
}
//updateModifyTilePreviews(false);
});
$('#TTM_Modify_CopySource').on('click', function() {
if (!fixedTarget) return;
let x = parseInt( newHoverFixed.css('left') );
let y = parseInt( newHoverFixed.css('top') );
let w = 40;
let h = 40;
if (x < 480) {
x = 0;
y = 0;
w = 480;
h = 440;
}
tempCanvas.width = w;
tempCanvas.height = h;
let tempCtx = tempCanvas.getContext("2d");
tempCtx.drawImage(this.checked ? tilesCtx.canvas : newCtx.canvas, x,y,w,h, 0,0,w,h);
updateModifyTilePreviews();
});
$('#TTM_Textures').on('change', function() {
let value = this.value;
if (value === 'customtileslink') {
value = $('#tiles').val();
$('#TTM_UpdateCTL').fadeIn();
} else if (value === 'dragged') {
value = draggedData;
} else {
$('#TTM_Tiles').scrollTop('0');
$('#TTM_UpdateCTL').hide();
}
loadImage(value);
});
$('#TTM_UpdateCTL').on('click', function() {
loadImage($('#tiles').val());
});
$('#TTM_Copy_Walls').on('click', function() {
copyTiles(0, 0, 480, 440);
});
$('#TTM_Copy_All').on('click', function() {
copyTiles(0, 0, tilesCtx.canvas.width, tilesCtx.canvas.height);
});
$('#TTM_Copy_Right').on('click', function() {
copyTiles(480, 0, 160, tilesCtx.canvas.height);
});
$('#TTM_Clear_Walls').on('click', function() {
newCtx.clearRect(0, 0, 480, 440);
});
$('#TTM_Clear_All').on('click', function() {
newCtx.clearRect(0, 0, newCtx.canvas.width, newCtx.canvas.height);
});
$('#TTM_Clear_Right').on('click', function() {
newCtx.clearRect(480, 0, 160, newCtx.canvas.height);
});
$('#TTM_Save').on('click', function() {
this.href = newCtx.canvas.toDataURL('image/png');
});
let myImgurs = JSON.parse(localStorage.getItem('myImgurs') || '{}');
$('#TTM_Imgur_ShowMenu').on('click', function() {
$('#TTM_Imgur_MenuContainer').slideToggle(200);
});
$('#TTM_Imgur_Upload').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
let url = 'https://api.imgur.com/3/image';
let title = prompt('Enter a name for these tiles:');
if (title === null) return;
let image = newCtx.canvas.toDataURL('image/png').replace('data:image/png;base64,', '');
let data = {
'image': image,
'title': title
};
$('#TTM_Imgur_Spinner').addClass('TTM_Loading');
$.ajax({
url: url,
headers: {
'Authorization': 'Client-ID '+imgurClientId
},
type: 'POST',
data: data
}).done(function(data) {
if (data.success === true) {
let myImgurs = JSON.parse(localStorage.getItem('myImgurs') || '{}');
myImgurs[data.data.id] = data.data;
localStorage.setItem('myImgurs', JSON.stringify(myImgurs));
createNewIcon(title, '#TTM_Imgur_MenuInner', myImgurs[data.data.id]);
} else {
alert('Upload to Imgur failed :(\n\nError: '+data.status);
}
}).fail(function(data) {
alert('Upload to Imgur failed :(\n\nError: '+data.status + ' ' + data.statusText);
}).always(function() {
removeSpinner();
});
});
$('#TTM_Imgur_MenuInner').on('click', '.TTM_Saved', function() {
let imgurId = $(this).data('name');
let myImgurs = JSON.parse(localStorage.getItem('myImgurs') || '{}');
if (imgurId && myImgurs.hasOwnProperty(imgurId)) {
$('#TTM_Imgur_PreviewWindow').data('name', imgurId);
$('#TTM_Imgur_PreviewWindow_Title').text(myImgurs[imgurId].title || myImgurs[imgurId].id);
$('#TTM_Imgur_PreviewWindow_Image').attr('src', myImgurs[imgurId].link);
$('#TTM_Imgur_PreviewWindow').fadeIn(200);
}
}).on('mouseenter', '.TTM_Saved', function() {
$(this).css('border', '1px outset #fff');
}).on('mouseleave', '.TTM_Saved', function() {
$(this).css('border', '1px inset #555');
});
$('#TTM_Imgur_PreviewWindow_Info').on('click', function() {
let imgurId = $('#TTM_Imgur_PreviewWindow').data('name');
let myImgurs = JSON.parse(localStorage.getItem('myImgurs') || '{}');
if (imgurId && myImgurs.hasOwnProperty(imgurId)) {
$.ajax({
url: 'https://api.imgur.com/3/image/'+imgurId,
headers: {
'Authorization': 'Client-ID '+imgurClientId
},
type: 'GET'
}).done(function(data) {
data = data.data;
$('#TTM_Imgur_PreviewWindow_Title').append('<div id="TTM_Imgur_PreviewWindow_TitleInfo" style="font-size:11px; font-style:italic;">' +
' Uploaded: ' + new Date(data.datetime*1000).toDateString() + ' | Size: ' + (data.size / 1024).toFixed(0) + 'KB' + ' | #Views: '+ data.views + ' | Bandwidth: ' + (data.bandwidth / 1024/1024).toFixed(1) + 'MB' +
'</div>');
});
}
});
$('#TTM_Imgur_PreviewWindow_Close').on('click', function() {
closeImgurPreviewWindow();
});
$('#TTM_Imgur_LoadToMixer').on('click', function() {
let imgurId = $('#TTM_Imgur_PreviewWindow').data('name');
let myImgurs = JSON.parse(localStorage.getItem('myImgurs') || '{}');
if (imgurId && myImgurs.hasOwnProperty(imgurId)) {
let img = document.createElement('img');
img.onload = function() {
newCtx.clearRect(0, 0, 640, 440);
newCtx.drawImage(img, 0,0,640,440, 0,0,640,440);
img.onload = null;
img = null;
};
img.crossOrigin = 'Anonymous';
img.src = myImgurs[imgurId].link;
$('#TTM_Imgur_MenuContainer').hide();
closeImgurPreviewWindow();
}
});
$('#TTM_Imgur_ViewOnImgur').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
let imgurId = $('#TTM_Imgur_PreviewWindow').data('name');
let myImgurs = JSON.parse(localStorage.getItem('myImgurs') || '{}');
if (imgurId && myImgurs.hasOwnProperty(imgurId)) {
window.open(myImgurs[imgurId].link.replace('i.','').replace('.png',''), '_blank');
}
});
$('#TTM_Imgur_Rename').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
let imgurId = $('#TTM_Imgur_PreviewWindow').data('name');
let myImgurs = JSON.parse(localStorage.getItem('myImgurs') || '{}');
if (imgurId && myImgurs.hasOwnProperty(imgurId)) {
let newName = prompt('Enter new name for these tiles:\n\n', myImgurs[imgurId].title === null ? '' : myImgurs[imgurId].title);
if (!newName) return true;
let url = 'https://api.imgur.com/3/image/'+myImgurs[imgurId].deletehash;
$('#TTM_Imgur_Rename').addClass('TTM_Loading');
$.ajax({
url: url,
headers: {
'Authorization': 'Client-ID '+imgurClientId
},
type: 'POST',
data: { 'title':newName }
}).done(function(data) {
if (data.success === true) {
myImgurs[imgurId].title = newName;
localStorage.setItem('myImgurs', JSON.stringify(myImgurs));
$('#TTM_Imgur_MenuInner').find('.TTM_Saved[data-name="'+imgurId+'"]').text(newName).attr('title', newName + ' ('+imgurId+')');
$('#TTM_Imgur_PreviewWindow_Title').text(newName);
} else {
alert('Failed to Rename on Imgur :(\n\nError: '+data.status);
}
}).fail(function(data) {
alert('Failed to Rename on Imgur :(\n\nError: '+data.status);
}).always(function() {
removeSpinner();
});
}
});
$('#TTM_Imgur_Delete').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
let $this = $(this).parent();
let imgurId = $('#TTM_Imgur_PreviewWindow').data('name');
let myImgurs = JSON.parse(localStorage.getItem('myImgurs') || '{}');
if (imgurId && myImgurs.hasOwnProperty(imgurId)) {
let response1 = confirm('Are you sure you want to remove these tiles from this list?\n\n');
if (response1) {
$('#TTM_Imgur_Delete').addClass('TTM_Loading');
let response2 = confirm('Delete it from Imgur too?\n\n');
if (response2) {
let url = 'https://api.imgur.com/3/image/'+myImgurs[imgurId].deletehash;
$.ajax({
url: url,
headers: {
'Authorization': 'Client-ID '+imgurClientId
},
type: 'DELETE'
}).done(function(data) {
if (data.success === true) {
closeImgurPreviewWindow();
} else {
alert('Failed to Delete on Imgur :(\n\nError: '+data.status);
}
}).fail(function(data) {
alert('Failed to Delete on Imgur :(\n\nError: '+data.status);
});
}
delete myImgurs[imgurId];
localStorage.setItem('myImgurs', JSON.stringify(myImgurs));
$('#TTM_Imgur_MenuInner').find('.TTM_Saved[data-name="'+imgurId+'"]').remove();
removeSpinner();
}
}
});
$('#TTM_Imgur_SaveToTiles').on('click', function() {
let imgurId = $('#TTM_Imgur_PreviewWindow').data('name');
let myImgurs = JSON.parse(localStorage.getItem('myImgurs') || '{}');
$('#TTM_Imgur_SaveToTiles').addClass('TTM_Loading');
if (imgurId && myImgurs.hasOwnProperty(imgurId)) {
$('#tiles').val(myImgurs[imgurId].link);
$('#custom-textures-btn').trigger('click');
setTimeout(removeSpinner, 1000);
}
});
$('#TTM_QuickSave').on('click', function() {
let name = prompt('Texture pack name:');
if (!name) return;
let savedTemps = JSON.parse(localStorage.getItem('savedTemps') || '{}');
let isNewPack = true;
if (savedTemps.hasOwnProperty(name)) {
if (!confirm('"'+name+'" already exists - OK to overwrite?\n\n')) return;
isNewPack = false;
}
savedTemps[name] = newCtx.canvas.toDataURL('image/png');
localStorage.setItem('savedTemps', JSON.stringify(savedTemps));
if (isNewPack) createNewIcon(name, '#TTM_QuickSaves');
}).on('mouseenter', function() {
$(this).css('background', '#555');
}).on('mouseleave', function() {
$(this).css('background', '#333');
});
$('#TTM_QuickSaves').on('click', '.TTM_Saved', function() {
let name = $(this).data('name');
let savedTemps = JSON.parse(localStorage.getItem('savedTemps') || '{}');
if (savedTemps.hasOwnProperty(name)) {
let img = document.createElement('img');
img.onload = function() {
newCtx.clearRect(0, 0, 640, 440);
newCtx.drawImage(img, 0,0,640,440, 0,0,640,440);
img.onload = null;
img = null;
};
img.crossOrigin = 'Anonymous';
img.src = savedTemps[name];
}
}).on('mouseenter', '.TTM_Saved', function() {
$(this).css('border', '1px outset #fff');
}).on('mouseleave', '.TTM_Saved', function() {
$(this).css('border', '1px inset #555');
});
$('#TTM_QuickSaves').on('click', '.TTM_DeleteSaved', function(e) {
e.stopPropagation();
e.preventDefault();
let name = $(this).parent().data('name');
let savedTemps = JSON.parse(localStorage.getItem('savedTemps') || '{}');
if (name && savedTemps.hasOwnProperty(name)) {
if (!confirm('Delete saved pack "'+name+'?\n\n')) return;
delete savedTemps[name];
localStorage.setItem('savedTemps', JSON.stringify(savedTemps));
let $this = $(this).parent();
$this.fadeOut(600, function() { $this.remove(); });
}
}).on('mouseenter', '.TTM_DeleteSaved', function() {
$(this).css('opacity', '1');
}).on('mouseleave', '.TTM_DeleteSaved', function() {
$(this).css('opacity', '0.5');
});
$('#TTM_Preview').hoverIntent(function() {
newCtxDataUrl = newCtx.canvas.toDataURL('image/png');
newImg.onload = function() {
$('#TTM_Previewer').remove();
$('#TTM_New_Outer').append('<div id="TTM_Previewer" style="position:absolute; display:inline-block; top:45px; right:-20px; padding:10px; background:#111; box-shadow:0px 0px 20px 6px #444; border:8px ridge #ccc; border-radius:10px; z-index:9999;"></div>');
if (newCtxDataUrl.length > 8000) {
let bg = createPreview(newCtxDataUrl, previewCanvas).toDataURL('image/png');
$('#TTM_Previewer').append('<canvas id="TTM_BG_Preview" width="640" height="440" style="background-image: url('+bg+');"></canvas>');
animatePreview();
speedpadImg.crossOrigin = 'Anonymous';
speedpadImg.src = $('#speedpad').val();
portalImg.crossOrigin = 'Anonymous';
portalImg.src = $('#portal').val();
} else {
$('#TTM_Previewer').append('<div>No Tiles?</div>');
}
};
newImg.crossOrigin = 'Anonymous';
newImg.src = newCtxDataUrl;
}, function() {
$('#TTM_Previewer').remove();
});
$(window).on('resize', trySideBySide);
//start it...
setTimeout(function() {
loadCustomValues();
$('#TTM_Tint_Group').hide(0);
if ($('#tiles').val()) {
loadImage($('#tiles').val());
$('#TTM_Textures').val('customtileslink');
} else {
loadImage('/textures/classic/tiles.png');
}
trySideBySide();
//createNewIcons();
}, 800);
//functions...
let drawPop = 0;
let popStartSize = 100;
let popStep = 10;
let extraAnimFramePos = 0;
let frameCount = 0;
let animObjects = {
rball: { p0:{x:840, y:-200}, p1:{x:40, y:40}, p2:{x:40, y:400}, p3:{x:540, y:390}, tx:560, ty:0, speed:0.003, t:0 },
bball: { p0:{x:680, y:-160}, p1:{x:-40, y:130}, p2:{x:0, y:540}, p3:{x:405, y:270}, tx:600, ty:0, speed:0.003, t:0 },
yflag: { p0:{x:120, y:94}, p1:{x:352, y:346}, p2:{x:352, y:346}, p3:{x:352, y:346}, tx:520, ty:40, speed:0.0015, t:0, offx:13, offy:-32 },
};
function animatePreview() {
if (!$('#TTM_BG_Preview').length) return;
let bgCtx = document.getElementById('TTM_BG_Preview').getContext('2d');
bgCtx.clearRect(0, 0, previewCanvas.width, previewCanvas.height);
bgCtx.fillStyle = 'rgba(255,128,0,0.1)';
for (let key in animObjects) {
let value = animObjects[key];
let draw = true;
let pt;
if (key === 'yflag') {
pt = { x:animObjects.bball.x + value.offx, y:animObjects.bball.y + value.offy };
if ((value.speed < 0 && value.t < 0.5) || (value.speed > 0 && value.t > 0.5)) draw = false;
if (draw && pt.x > 370 && pt.y > 230) draw = false;
} else {
pt = calcBezierPoint(value.t, value.p0, value.p1, value.p2, value.p3);
value.x = pt.x;
value.y = pt.y;
if (key === 'rball') {
if (value.speed < 0) draw = false;
if (drawPop === 0 && pt.x+39 > value.p3.x && pt.y > 230 && value.speed < 0) drawPop = popStartSize;
}
}
if (draw) {
if (key === 'rball') {
bgCtx.save();
bgCtx.translate(pt.x, pt.y);
bgCtx.rotate(200+(50*value.t));
bgCtx.drawImage(newImg, value.tx,value.ty,40,40, -20,-20,40,40);
bgCtx.translate(-pt.x, -pt.y);
bgCtx.restore();
} else {
bgCtx.drawImage(newImg, value.tx,value.ty,40,40, pt.x,pt.y,40,40);
}
}
value.t += value.speed;
if (value.t > 1 || value.t < 0) value.speed *= -1;
}
if (drawPop > 0) {
bgCtx.beginPath();
bgCtx.arc(540,390,popStartSize-drawPop, 0, Math.PI*2, false);
bgCtx.fill();
drawPop-=popStep;
} else {
drawPop = 0;
}
if (speedpadImg) {
bgCtx.drawImage(speedpadImg, extraAnimFramePos,0,40,40, 160,80,40,40);
bgCtx.drawImage(speedpadImg, extraAnimFramePos,0,40,40, 80,160,40,40);
}
if (portalImg) {
bgCtx.drawImage(portalImg, extraAnimFramePos,0,40,40, 600,320,40,40);
bgCtx.drawImage(portalImg, extraAnimFramePos,0,40,40, 600,360,40,40);
bgCtx.drawImage(portalImg, extraAnimFramePos,0,40,40, 600,400,40,40);
}
if (frameCount % 8 === 0) extraAnimFramePos+=40;
if (extraAnimFramePos >= 160) extraAnimFramePos = 0;
frameCount++;
window.requestAnimationFrame(animatePreview);
}
function closeImgurPreviewWindow() {
$('#TTM_Imgur_PreviewWindow').fadeOut(200, function() {
$('#TTM_Imgur_PreviewWindow_Image').attr('src', '');
});
}
function removeSpinner() {
$('#TTM_Container').find('.TTM_Loading').removeClass('TTM_Loading');
}
function loadCustomValues() {
let texturePacks = JSON.parse($('#texture-pack-data').text());
let savedTemps = JSON.parse(localStorage.getItem('savedTemps') || '{}');
let myImgurs = JSON.parse(localStorage.getItem('myImgurs') || '{}');
let extraPacks = {};
//sort default packs...
texturePacks.sort(function(a, b) {
if (a.name.toLowerCase() < b.name.toLowerCase()) return -1;
if (a.name.toLowerCase() > b.name.toLowerCase()) return 1;
return 0;
});
for (let i=0; i<texturePacks.length; i++) {
if (texturePacks[i].name === 'Classic') { //put this one at the start :)
texturePacks.splice(0, 0, texturePacks.splice(i, 1)[0]);
}
}
//some extra packs...
let message = '(Note: this texture is not part of the official TagPro texture packs collection)';
extraPacks['88 Electric'] = { author:'Rob Flagetti'+message, tiles:'PzZ5u57', speedpad:'5i2b07D', speedpadRed:'WwQ70DK', speedpadBlue:'fIeILub', portal:'RFQgPXz', splats:'dSGptD4' };
extraPacks['Aperture Laboratories'] = { author:'SuperSans'+message, tiles:'Fg9GIN2', speedpad:'CPoMTrR', speedpadRed:'Az9vhYO', speedpadBlue:'nMVO8KV', portal:'nPdqzJ2', splats:'HSufen1' };
extraPacks['Brioche Light Diagonal'] = { author:'Brioche'+message, tiles:'GCVOxf0', speedpad:'HCTWYrI', speedpadRed:'PnFxbGc', speedpadBlue:'BxhPCj6', portal:'8hUe7G0', splats:'kbkOC6x' };
extraPacks['Brioche Light Square'] = { author:'Brioche'+message, tiles:'h29Pa4P', speedpad:'HCTWYrI', speedpadRed:'PnFxbGc', speedpadBlue:'BxhPCj6', portal:'8hUe7G0', splats:'kbkOC6x' };
extraPacks['Brioche Light None'] = { author:'Brioche'+message, tiles:'Z7aauqp', speedpad:'HCTWYrI', speedpadRed:'PnFxbGc', speedpadBlue:'BxhPCj6', portal:'8hUe7G0', splats:'kbkOC6x' };
extraPacks['Candyland'] = { author:'-salt- (e:nabby)'+message, tiles:'EHCbMS0', speedpad:'hPpsrSI', speedpadRed:'EXqQbpF', speedpadBlue:'if3qEp0', portal:'lfczV8G', splats:'M5TMzBO' };
extraPacks['Catalyst'] = { author:'Catalyst'+message, tiles:'Jpx6FP1', speedpad:'5Z5KC2x', speedpadRed:'kwn7wLk', speedpadBlue:'Z8YlL8e', portal:'hr1zffY', splats:'mGxI0zl' };
extraPacks['Derezzed'] = { author:'-salt- (e:nabby)'+message, tiles:'L0V5dx8', speedpad:'/textures/sparkle/speedpad.png', speedpadRed:'/textures/sparkle/speedpadred.png', speedpadBlue:'if3qEp0', portal:'vJDZam9', splats:'WXHAA3I' };
extraPacks['Doodle'] = { author:'turtlemansam'+message, tiles:'W0anL7u', speedpad:'aLs3qyH', speedpadRed:'uObyeQ2', speedpadBlue:'Ko9Rea2', portal:'bFYUxzA', splats:'KillvgL' };
extraPacks['Doodle Dark'] = { author:'turtlemansam (e:nabby)'+message, tiles:'UeAOeLb', speedpad:'22t8hoV', speedpadRed:'EfQFr4G', speedpadBlue:'hPMDhD5', portal:'H1cHH5w', splats:'KillvgL' };
extraPacks['Dyslexia'] = { author:'MagicPigeon'+message, tiles:'bhNV6LS', speedpad:'nUakHFN', speedpadRed:'3I745gq', speedpadBlue:'LEB9Wfw', portal:'5Z5Yrhu', splats:'u5kzgws' };
extraPacks['Glow'] = { author:'MagicPigeon'+message, tiles:'ciiB8Pw', speedpad:'IB95nd5', speedpadRed:'8RgHd1Y', speedpadBlue:'E3gqIdZ', portal:'H1e5f5X', splats:'yMbLHLT' };
extraPacks['Halloween'] = { author:'TagPro'+message, tiles:'DqpxNyk', speedpad:'/images/events/halloween/speedpad.png', speedpadRed:'/images/events/halloween/speedpadred.png', speedpadBlue:'/images/events/halloween/speedpadblue.png', portal:'/images/events/halloween/portal.png', splats:'/images/events/halloween/splats.png' };
extraPacks['Jar Jar Pinks'] = { author:'Borgen'+message, tiles:'OMvtZnn', speedpad:'/textures/electric/speedpad.png', speedpadRed:'/textures/electric/speedpadred.png', speedpadBlue:'/textures/electric/speedpadblue.png', portal:'/textures/electric/portal.png', splats:'wxJ2ImS' };
extraPacks['Jar Jar R/B'] = { author:'Borgen (e:nabby)'+message, tiles:'auGwfdD', speedpad:'/textures/crystal/speedpad.png', speedpadRed:'/textures/crystal/speedpadred.png', speedpadBlue:'/textures/crystal/speedpadblue.png', portal:'BHltUAU', splats:'/textures/sparkle/splats.png' };
extraPacks['Kindergarten'] = { author:'Clydas'+message, tiles:'Zr1881o', speedpad:'UEpX1wb', speedpadRed:'tUC9CMG', speedpadBlue:'5yA3IOx', portal:'6Lbd9Aw', splats:'ZGSTp2s' };
extraPacks['Mario'] = { author:'MagicPigeon'+message, tiles:'0ErN4Be', speedpad:'zImnW1i', speedpadRed:'AXEDaAv', speedpadBlue:'mH8Qww0', portal:'BLIVace', splats:'9dAtpMy' };
extraPacks['Minima'] = { author:'Canvas'+message, tiles:'KAk9TN9', speedpad:'pJEZKnh', speedpadRed:'OlDPpdM', speedpadBlue:'HgmJ9yg', portal:'DeevRGe', splats:'ytIIuQS' };
extraPacks['Next Classic'] = { author:'TagPro (e:MagicPigeon)'+message, tiles:'ulQFpn7', speedpad:'w7pW8SC', speedpadRed:'FHjSv04', speedpadBlue:'SSK4Hno', portal:'gdJfGV9', splats:'GObCQoT' };
extraPacks['Nilla'] = { author:'Dotsarecool'+message, tiles:'kuPdAXV', speedpad:'39zXNPL', speedpadRed:'bo4m727', speedpadBlue:'EFk5IgL', portal:'KdEHGtf', splats:'kHUlTwP' };
extraPacks['Pixelated'] = { author:'iso'+message, tiles:'vmnTlEK', speedpad:'ZfS3vb1', speedpadRed:'Ao8vGcn', speedpadBlue:'MW7K5PV', portal:'JXTmmen', splats:'LFoPM44' };
extraPacks['Seaweed G/B'] = { author:'Borgen'+message, tiles:'Kh4jUfE', speedpad:'ONxlcFL', speedpadRed:'y3MZi7c', speedpadBlue:'DpJS96w', portal:'44fPSBq', splats:'ipV54ze' };
extraPacks['Seaweed R/B'] = { author:'Borgen'+message, tiles:'RslLcen', speedpad:'A6cNVb3', speedpadRed:'DwUHM2I', speedpadBlue:'DpJS96w', portal:'44fPSBq', splats:'ZrimG2x' };
extraPacks['Starlight R/B'] = { author:'MagicPigeon (e:nabby)'+message, tiles:'j0el5Tn', speedpad:'22t8hoV', speedpadRed:'EfQFr4G', speedpadBlue:'hPMDhD5', portal:'rGEEQ2s', splats:'IIFG2nS' };
extraPacks['Star Wars'] = { author:'Moosen'+message, tiles:'1GQnONe', speedpad:'WgeuDEz', speedpadRed:'cqY1LTe', speedpadBlue:'bCUoqXq', portal:'FtLHfuz', splats:'XIndyGS' };
extraPacks['TagPro Ultra'] = { author:'MuscleCups'+message, tiles:'qTjavFh', speedpad:'dLPehvN', speedpadRed:'U9eQnIa', speedpadBlue:'CtRmTaF', portal:'yiLdTR9', splats:'TTuhrS5' };
extraPacks['Tranquility Dark'] = { author:'R e t r o'+message, tiles:'fb8ueHE', speedpad:'tZE7l6b', speedpadRed:'AGMgt6S', speedpadBlue:'nokGBIr', portal:'gFC1dUu', splats:'tDsbgPv' };
extraPacks['Ultra Smooth'] = { author:'ProfessorTag'+message, tiles:'Nw0EqWH', speedpad:'zxubWbQ', speedpadRed:'yJGhLPt', speedpadBlue:'K02G9jE', portal:'hffUZ2J', splats:'xMMkRce' };
extraPacks['Vanilla Pro'] = { author:'ProfessorTag'+message, tiles:'ZKAwVRG', speedpad:'6h2Fna8', speedpadRed:'pF4l9SO', speedpadBlue:'NlepAuW', portal:'qpg0wCt', splats:'ABTYq4t' };
extraPacks['Vortex'] = { author:'MagicPigeon'+message, tiles:'CLgkyxU', speedpad:'hL1YlFu', speedpadRed:'gxQeYTw', speedpadBlue:'pbXh4b1', portal:'H1cHH5w', splats:'36fUJG2' };
extraPacks['Whix Grey'] = { author:'Nabby'+message, tiles:'E9Qjdw6', speedpad:'22t8hoV', speedpadRed:'EfQFr4G', speedpadBlue:'hPMDhD5', portal:'lfczV8G', splats:'F799BFp' };
extraPacks['Whix Light'] = { author:'Nabby'+message, tiles:'Z05ydSW', speedpad:'22t8hoV', speedpadRed:'EfQFr4G', speedpadBlue:'hPMDhD5', portal:'lfczV8G', splats:'F799BFp' };
extraPacks['Whix Dark'] = { author:'Nabby'+message, tiles:'xw3lN2o', speedpad:'22t8hoV', speedpadRed:'EfQFr4G', speedpadBlue:'hPMDhD5', portal:'lfczV8G', splats:'F799BFp' };
extraPacks['Yin-Yang'] = { author:'Browncoat'+message, tiles:'kTVchxk', speedpad:'NVPIQ1y', speedpadRed:'e18kH49', speedpadBlue:'lv8pcWF', portal:'DZried3', splats:'0GTWyyW' };
extraPacks['YYRB'] = { author:'Browncoat (e:nabby)'+message, tiles:'nDW1Tip', speedpad:'sTqwM4n', speedpadRed:'7tZjFli', speedpadBlue:'pF3xUlZ', portal:'Qb4iyjY', splats:'TqJKyQR' };
extraPacks['YYRB Light'] = { author:'Browncoat (e:nabby)'+message, tiles:'qkaeirQ', speedpad:'sTqwM4n', speedpadRed:'7tZjFli', speedpadBlue:'pF3xUlZ', portal:'Qb4iyjY', splats:'TqJKyQR' };
extraPacks['YYRB Dark'] = { author:'Browncoat (e:nabby)'+message, tiles:'4RMaqMn', speedpad:'sTqwM4n', speedpadRed:'7tZjFli', speedpadBlue:'pF3xUlZ', portal:'Qb4iyjY', splats:'TqJKyQR' };
$('#TTM_Textures').append('<optgroup label="Default Packs..." style="color:#d00; text-decoration:underline; font-weight:bold;">');
$.each(texturePacks, function(key, value) {
$('#TTM_Textures').append(' <option value="'+value.tiles+'"'+(value.author?' title="Created by '+value.author+'"':'')+'>'+value.name+'</option>');
});
$('#TTM_Textures').append('</optgroup>');
$('#TTM_Textures').append('<optgroup label="Extra Packs..." style="color:#d00; text-decoration:underline; font-weight:bold;">');
$.each(extraPacks, function(key, value) {
let url = value.tiles.startsWith('/') ? value.tiles : 'https://i.imgur.com/' + value.tiles + '.png';
$('#TTM_Textures').append('<option value="' + url + '"' + (value.author ? ' title="Created by ' + value.author + '"' : '') + '>' + key + '</option>');
});
$('#TTM_Textures').append('</optgroup>');
$('#TTM_Textures').append('<optgroup id="TTM_OptGroup_CustomTilesLink" label="Custom Tiles Link..." style="color:#d00; text-decoration:underline; font-weight:bold;">');
$('#TTM_Textures').append(' <option value="customtileslink" title="This is the link from &quot;Tiles&quot; on the &quot;Import Custom&quot; tab">Custom Tiles Link</option>');
$('#TTM_Textures').append('</optgroup>');
//my quick saved...
$.each(savedTemps, function(key, value) {
createNewIcon(key, '#TTM_QuickSaves');
});
//my imgur uploads...
$.each(myImgurs, function(key, value) {
createNewIcon(myImgurs[key].title, '#TTM_Imgur_MenuInner', myImgurs[key]);
});
}
function loadImage(newCtxDataUrl, isDragged=false) {
tilesImg.onload = function() {
let width = tilesImg.naturalWidth;
let height = tilesImg.naturalHeight;
if ((width !== 640) || (height !== 440)) {
$('#TTM_FreeMove').prop('checked', true);
$('#TTM_FreeMove').parent().show();
freeMove = true;
} else {
$('#TTM_FreeMove').prop('checked', false);
$('#TTM_FreeMove').parent().hide();
freeMove = false;
}
tilesCtx = $("#TTM_Tiles_Canvas").get(0).getContext("2d");
tilesCtx.canvas.width = width;
tilesCtx.canvas.height = height;
tilesCtx.clearRect(0, 0, width, height);
tilesCtx.drawImage(tilesImg, 0,0,width,height, 0,0,width,height);
if (width > 640) $("#TTM_Tiles").css({ 'overflow-x':'auto' });
else $("#TTM_Tiles").css({ 'overflow':'hidden' });
if (height > 440) $("#TTM_Tiles").css({ 'overflow-y':'auto' });
else $("#TTM_Tiles").css({ 'overflow':'hidden' });
$("#TTM_Tiles_Cover").css({ 'width':width+'px', 'height':height+'px' });
if (isDragged) {
if (!$('#TTM_OptGroup_Dragged').length) $('#TTM_Textures').append('<optgroup id="TTM_OptGroup_Dragged" label="Drag\'n\'Dropped..." style="color:#d00; text-decoration:underline; font-weight:bold;"></optgroup>');
$('#TTM_Option_Dragged').remove();
$('#TTM_OptGroup_Dragged').after('<option id="TTM_Option_Dragged" value="dragged" title="Dragged: '+isDragged+'">Drag\'n\'Dropped</option>');
$('#TTM_Textures').val('dragged');
$('#TTM_UpdateCTL').hide();
}
tilesImg.onload = null;
};
tilesImg.onerror = function() {
alert('Could not load the image at...\n\n ' + newCtxDataUrl + '\n\nCross-origin access may have been denied by the server?\n\n\n');
};
tilesImg.crossOrigin = 'Anonymous';
tilesImg.src = newCtxDataUrl;
}
function createNewIcon(name, element, imgurData) {
let loadTitle = 'LOAD these saved tiles';
let dataName = name;
if (imgurData) {
if (!name) name = imgurData.id;
dataName = imgurData.id;
let date = new Date(imgurData.datetime*1000);
loadTitle = (imgurData.title ? imgurData.title + ' (' + imgurData.id + ')' : imgurData.id) +
'\n - ' + date.toDateString() + ' (' + date.toLocaleTimeString() + ')' +
'\n - ' + imgurData.width + 'x' + imgurData.height + 'px (' + (imgurData.size / 1024).toFixed(0) + 'KB)';
}
$(element).append('<div class="TTM_Saved" data-name="'+dataName+'" style="" title="'+loadTitle+'">' + name +
(!imgurData ? '<div class="TTM_DeleteSaved" style="" title="DELETE these saved tiles">x</div>' : '') +
'</div>');
}
function updateModifyTilePreviews(updateSource=true) {
let sourceCtx = $('#TTM_ModifySourceTilePreview').get(0).getContext('2d');
if (updateSource) sourceCtx.clearRect(0, 0, 40, 40);
if (fixedTarget) {
let x = parseInt( newHoverFixed.css('left') );
let y = parseInt( newHoverFixed.css('top') );
$('#TTM_Modify_Message').hide();
if (updateSource) sourceCtx.drawImage($('#TTM_Modify_CopySource').is(':checked') ? tilesCtx.canvas : newCtx.canvas, x,y,40,40, 0,0,40,40);
if (x < 480) {
tintTiles(0, 0, 480, 440, false, true);
} else {
tintTiles(x, y, 40, 40, false, false);
}
} else {
$('#TTM_Modify_Message').show();
}
}
function tintTiles(sx, sy, sw=40, sh=40, updateNew=false, isWalls=false) {
let tintedCanvas = new OffscreenCanvas(sw, sh);
let tintedCtx = tintedCanvas.getContext('2d');
let tempCtx = tempCanvas.getContext('2d');
let destCtx = $('#TTM_ModifyDestTilePreview').get(0).getContext('2d');
let applyFilters = function() {
let filters = '';
filters += 'hue-rotate(' + $('#TTM_TileHue').val() + 'deg) ';
if ($('#TTM_Sepia').val() > 0) filters += 'sepia('+$('#TTM_Sepia').val()+'%) ';
if (($('#TTM_Brightness').val() !== '100')) filters += 'brightness('+$('#TTM_Brightness').val()+'%) ';
if (($('#TTM_Contrast').val() != '100')) filters += 'contrast('+$('#TTM_Contrast').val()+'%) ';
if (($('#TTM_Saturation').val() !== '100')) filters += 'saturate('+$('#TTM_Saturation').val()+'%) ';
if ($('#TTM_Add_Checkered').is(':checked')) addCheckered(tintedCtx);
if ($('#TTM_Add_Pattern').is(':checked')) addPattern(tintedCtx);
if ($('#TTM_Add_Stripes').is(':checked')) addStripes(tintedCtx);
if ($('#TTM_Add_Specks').is(':checked')) addSpecks(tintedCtx);
if ($('#TTM_Add_Shine').is(':checked')) addShine(tintedCtx);
if ($('#TTM_Add_Border').is(':checked')) addBorder(tintedCtx);
destCtx.clearRect(0, 0, 40, 40);
destCtx.filter = filters;
destCtx.drawImage(tintedCanvas, 0,0,sw,sh, 0,0,sw,sh);
if (updateNew) {
newCtx.clearRect(sx, sy, sw, sh);
newCtx.filter = filters;
newCtx.drawImage(tintedCanvas, 0,0,sw,sh, sx,sy,sw,sh);
newCtx.filter = 'none';
}
tintedCanvas = null;
};
let px = 0;
let py = 0;
if (!updateNew) {
if (isWalls) {
px = parseInt( newHoverFixed.css('left') );
py = parseInt( newHoverFixed.css('top') );
}
}
tintedCtx.drawImage(tempCtx.canvas, px,py,sw,sh, 0,0,sw,sh);
if ($('#TTM_Tint').is(':checked')) {
let method = $('#TTM_Tint_Group').find(':selected').val();
if (method === 'simple') {
setTint(tintedCanvas, $('#TTM_Tint_Color').val(), 0.5);
applyFilters();
} else {
generateTintedImage(tintedCtx, $('#TTM_Tint_Color').val(), method);
applyFilters();
}
} else {
applyFilters();
}
}
function copyTiles(sx, sy, sw=40, sh=40, dx=sx, dy=sy, dw=sw, dh=sh, isCircle=false) {
let size = selectorSize;
let xOffset = 0;
let yOffset = 0;
if (freeMove && !fixedTarget) {
alert('You need to first select a target tile...');
return;
}
if (size < 40) {
xOffset = 20-(size/2);
yOffset = 20-(size/2);
}
if ((dw > 40) || (dh > 40)) {
newCtx.clearRect(dx, dy, dw, dh);
newCtx.drawImage(tilesCtx.canvas, sx,sy,sw,sh, dx,dy,dw,dh);
} else {
let canvas = new OffscreenCanvas(size, size);
let ctx = canvas.getContext('2d');
ctx.beginPath();
if (isCircle) {
ctx.arc(size/2, size/2, sw/2, 0, Math.PI*2);
} else {
ctx.rect(0, 0, sw, sh);
}
ctx.clip();
ctx.drawImage(tilesCtx.canvas, sx,sy,size,size, 0,0,size,size);
if (fixedTarget) {
newCtx.clearRect(dx, dy, 40, 40);
newCtx.drawImage(ctx.canvas, 0,0,sw,sh, dx+xOffset,dy+yOffset,dw,dh);
} else {
if (!freeMove) newCtx.clearRect(dx-xOffset, dy-yOffset, 40, 40);
newCtx.drawImage(ctx.canvas, 0,0,sw,sh, dx,dy,dw,dh);
}
canvas = null;
}
}
function trySideBySide() {
if ($('body').width() > 1410) {
$('#TTM_Container').css({ 'width':'1400px', 'margin-left':'-130px' }); //try for side-by-side if enough room
} else {
$('#TTM_Container').css({ 'width':'', 'margin-left':'' });
}
}
function setTint(targetCanvas, color, opacity) {
let tintCanvas = new OffscreenCanvas(targetCanvas.width, targetCanvas.height);
let ctintCtxtx = tintCanvas.getContext('2d');
tintCtx.globalCompositeOperation = "destination-atop";
tintCtx.fillStyle = hexToRgbA(color || "#000000", opacity);
tintCtx.fillRect(0, 0, tintCanvas.width, tintCanvas.height);
tintCtx.drawImage(targetCanvas, 0, 0);
let imageCtx = targetCanvas.getContext("2d");
imageCtx.drawImage(tintCanvas, 0, 0);
tintCanvas = null;
}
//From: http://www.playmycode.com/blog/2011/06/realtime-image-tinting-on-html5-canvas/
function generateRGBKs(ctx, method) {
let width = ctx.canvas.width;
let height = ctx.canvas.height;
let rgbks = [];
let pixels = ctx.getImageData(0, 0, width, height).data;
let to = ctx.getImageData(0, 0, width, height);
let toData = to.data;
let gray;
for (let rgbI=0; rgbI<4; rgbI++) {
for (let i=0, len=pixels.length; i<len; i+=4) {
if (method === 'desaturation') {
gray = ( Math.max(pixels[i], pixels[i+1], pixels[i+2]) + Math.min(pixels[i], pixels[i+1], pixels[i+2]) ) / 2; //simple desaturation
} else if (method === 'decomposition') {
gray = Math.max(pixels[i], pixels[i+1], pixels[i+2]); //simple decomposition
} else {
gray = (0.3 * pixels[i] + 0.59 * pixels[i + 1] + 0.11 * pixels[i + 2]); //simple brightness
}
pixels[i ] = gray;
pixels[i + 1] = gray;
pixels[i + 2] = gray;
toData[i ] = (rgbI === 0) ? pixels[i ] : 0;
toData[i+1] = (rgbI === 1) ? pixels[i+1] : 0;
toData[i+2] = (rgbI === 2) ? pixels[i+2] : 0;
toData[i+3] = pixels[i+3] ;
}
ctx.putImageData(to, 0, 0);
let imgComp = document.createElement('img');
imgComp.src = ctx.canvas.toDataURL();
rgbks.push(imgComp);
imgComp = null;
}
return rgbks;
}
function generateTintedImage(ctx, color, method) {
let rgbks = generateRGBKs(ctx, method);
let tintRgbs = hexToRgb(color);
let red = tintRgbs[0];
let green = tintRgbs[1];
let blue = tintRgbs[2];
ctx.globalAlpha = 1;
ctx.globalCompositeOperation = 'copy';
ctx.drawImage(rgbks[3], 0, 0);
ctx.globalCompositeOperation = 'lighter';
if (red > 0) {
ctx.globalAlpha = red / 255.0;
ctx.drawImage( rgbks[0], 0, 0 );
}
if (green > 0) {
ctx.globalAlpha = green / 255.0;
ctx.drawImage( rgbks[1], 0, 0 );
}
if (blue > 0) {
ctx.globalAlpha = blue / 255.0;
ctx.drawImage( rgbks[2], 0, 0 );
}
ctx.globalAlpha = 1;
ctx.globalCompositeOperation = 'source-over';
}
function createPreview(url, canvas) {
let map = {"info":{"width":16,"height":11},"data":{"0_5":{"id":9.1,"x":0,"y":5,"tx":520,"ty":120},"0_6":{"id":9.1,"x":0,"y":6,"tx":520,"ty":120},"1_1":{"id":2,"x":1,"y":1,"tx":520,"ty":160},"1_2":{"id":2,"x":1,"y":2,"tx":520,"ty":160},"1_3":{"id":2,"x":1,"y":3,"tx":520,"ty":160},"1_4":{"id":2,"x":1,"y":4,"tx":520,"ty":160},"1_5":{"id":2,"x":1,"y":5,"tx":520,"ty":160},"1_6":{"id":2,"x":1,"y":6,"tx":520,"ty":160},"1_7":{"id":2,"x":1,"y":7,"tx":520,"ty":160},"1_8":{"id":2,"x":1,"y":8,"tx":520,"ty":160},"1_9":{"id":2,"x":1,"y":9,"tx":520,"ty":160},"1_10":{"id":2,"x":1,"y":10,"tx":520,"ty":160},"2_1":{"id":2,"x":2,"y":1,"tx":520,"ty":160},"2.2":{"id":2,"x":2,"y":2,"tx":520,"ty":160},"2_3":{"id":2,"x":2,"y":3,"tx":520,"ty":160},"2_4":{"id":23,"x":2,"y":4,"tx":520,"ty":200},"2_5":{"id":23,"x":2,"y":5,"tx":520,"ty":200},"2_6":{"id":23,"x":2,"y":6,"tx":520,"ty":200},"2_7":{"id":23,"x":2,"y":7,"tx":520,"ty":200},"2_8":{"id":2,"x":2,"y":8,"tx":520,"ty":160},"2.9":{"id":2,"x":2,"y":9,"tx":520,"ty":160},"2_10":{"id":2,"x":2,"y":10,"tx":520,"ty":160},"3_0":{"id":9.2,"x":3,"y":0,"tx":560,"ty":120},"3_1":{"id":2,"x":3,"y":1,"tx":520,"ty":160},"3_2":{"id":2,"x":3,"y":2,"tx":520,"ty":160},"3_3":{"id":2,"x":3,"y":3,"tx":520,"ty":160},"3_4":{"id":2,"x":3,"y":4,"tx":520,"ty":160},"3_5":{"id":2,"x":3,"y":5,"tx":520,"ty":160},"3_6":{"id":2,"x":3,"y":6,"tx":520,"ty":160},"3_7":{"id":2,"x":3,"y":7,"tx":520,"ty":160},"3_8":{"id":2,"x":3,"y":8,"tx":520,"ty":160},"3_9":{"id":2,"x":3,"y":9,"tx":520,"ty":160},"3_10":{"id":2,"x":3,"y":10,"tx":520,"ty":160},"4_0":{"id":9.2,"x":4,"y":0,"tx":560,"ty":120},"4_1":{"id":2,"x":4,"y":1,"tx":520,"ty":160},"4_2":{"id":2,"x":4,"y":2,"tx":520,"ty":160},"4_3":{"id":2,"x":4,"y":3,"tx":520,"ty":160},"4_4":{"id":2,"x":4,"y":4,"tx":520,"ty":160},"4_5":{"id":2,"x":4,"y":5,"tx":520,"ty":160},"4_6":{"id":2,"x":4,"y":6,"tx":520,"ty":160},"4_7":{"id":2,"x":4,"y":7,"tx":520,"ty":160},"4_8":{"id":2,"x":4,"y":8,"tx":520,"ty":160},"4_9":{"id":2,"x":4,"y":9,"tx":520,"ty":160},"4_10":{"id":2,"x":4,"y":10,"tx":520,"ty":160},"5_1":{"id":2,"x":5,"y":1,"tx":520,"ty":160},"5_2":{"id":2,"x":5,"y":2,"tx":520,"ty":160},"5_3":{"id":2,"x":5,"y":3,"tx":520,"ty":160},"5_4":{"id":2,"x":5,"y":4,"tx":520,"ty":160},"5_5":{"id":2,"x":5,"y":5,"tx":520,"ty":160},"5_6":{"id":2,"x":5,"y":6,"tx":520,"ty":160},"5_7":{"id":2,"x":5,"y":7,"tx":520,"ty":160},"5_8":{"id":2,"x":5,"y":8,"tx":520,"ty":160},"5_9":{"id":2,"x":5,"y":9,"tx":520,"ty":160},"5_10":{"id":2,"x":5,"y":10,"tx":520,"ty":160},"6_1":{"id":2,"x":6,"y":1,"tx":520,"ty":160},"6_2":{"id":2,"x":6,"y":2,"tx":520,"ty":160},"6_3":{"id":2,"x":6,"y":3,"tx":520,"ty":160},"6_4":{"id":2,"x":6,"y":4,"tx":520,"ty":160},"6.5":{"id":2,"x":6,"y":5,"tx":520,"ty":160},"6_5":{"id":7,"x":6,"y":5,"tx":480,"ty":0},"6.6":{"id":2,"x":6,"y":6,"tx":520,"ty":160},"6_6":{"id":7,"x":6,"y":6,"tx":480,"ty":0},"6_7":{"id":2,"x":6,"y":7,"tx":520,"ty":160},"6_8":{"id":2,"x":6,"y":8,"tx":520,"ty":160},"6_9":{"id":2,"x":6,"y":9,"tx":520,"ty":160},"6_10":{"id":2,"x":6,"y":10,"tx":520,"ty":160},"7_0":{"id":2,"x":7,"y":0,"tx":520,"ty":160},"7_1":{"id":2,"x":7,"y":1,"tx":520,"ty":160},"7_2":{"id":2,"x":7,"y":2,"tx":520,"ty":160},"7.3":{"id":2,"x":7,"y":3,"tx":520,"ty":160},"7_3":{"id":8,"x":7,"y":3,"tx":520,"ty":240},"7_4":{"id":2,"x":7,"y":4,"tx":520,"ty":160},"7_6":{"id":11,"x":7,"y":6,"tx":560,"ty":160},"7_7":{"id":11,"x":7,"y":7,"tx":560,"ty":160},"7_8":{"id":2,"x":7,"y":8,"tx":520,"ty":160},"7_9":{"id":2,"x":7,"y":9,"tx":520,"ty":160},"7_10":{"id":2,"x":7,"y":10,"tx":520,"ty":160},"8_0":{"id":2,"x":8,"y":0,"tx":520,"ty":160},"8_1":{"id":2,"x":8,"y":1,"tx":520,"ty":160},"8_2":{"id":9,"x":8,"y":2,"tx":480,"ty":120},"8_3":{"id":9,"x":8,"y":3,"tx":480,"ty":120},"8_4":{"id":9,"x":8,"y":4,"tx":480,"ty":120},"8_6":{"id":11,"x":8,"y":6,"tx":560,"ty":160},"8_7":{"id":11,"x":8,"y":7,"tx":560,"ty":160},"8_8":{"id":11,"x":8,"y":8,"tx":560,"ty":160},"8_9":{"id":2,"x":8,"y":9,"tx":520,"ty":160},"8_10":{"id":2,"x":8,"y":10,"tx":520,"ty":160},"9_0":{"id":2,"x":9,"y":0,"tx":520,"ty":160},"9_1":{"id":2,"x":9,"y":1,"tx":520,"ty":160},"9_2":{"id":12,"x":9,"y":2,"tx":600,"ty":160},"9_3":{"id":9,"x":9,"y":3,"tx":480,"ty":120},"9_4":{"id":9,"x":9,"y":4,"tx":480,"ty":120},"9_6":{"id":18,"x":9,"y":6,"tx":600,"ty":200},"9_7":{"id":11,"x":9,"y":7,"tx":560,"ty":160},"9_8":{"id":11,"x":9,"y":8,"tx":560,"ty":160},"9_9":{"id":11,"x":9,"y":9,"tx":560,"ty":160},"9_10":{"id":2,"x":9,"y":10,"tx":520,"ty":160},"10_0":{"id":2,"x":10,"y":0,"tx":520,"ty":160},"10_1":{"id":2,"x":10,"y":1,"tx":520,"ty":160},"10_2":{"id":12,"x":10,"y":2,"tx":600,"ty":160},"10_3":{"id":12,"x":10,"y":3,"tx":600,"ty":160},"10_4":{"id":9,"x":10,"y":4,"tx":480,"ty":120},"10_6":{"id":18,"x":10,"y":6,"tx":600,"ty":200},"10_7":{"id":18,"x":10,"y":7,"tx":600,"ty":200},"10_8":{"id":11,"x":10,"y":8,"tx":560,"ty":160},"10_9":{"id":11,"x":10,"y":9,"tx":560,"ty":160},"10_10":{"id":11,"x":10,"y":10,"tx":560,"ty":160},"11_0":{"id":2,"x":11,"y":0,"tx":520,"ty":160},"11_1":{"id":2,"x":11,"y":1,"tx":520,"ty":160},"11_2":{"id":2,"x":11,"y":2,"tx":520,"ty":160},"11_3":{"id":12,"x":11,"y":3,"tx":600,"ty":160},"11_4":{"id":12,"x":11,"y":4,"tx":600,"ty":160},"11_7":{"id":18,"x":11,"y":7,"tx":600,"ty":200},"11_8":{"id":18,"x":11,"y":8,"tx":600,"ty":200},"11_9":{"id":11,"x":11,"y":9,"tx":560,"ty":160},"11_10":{"id":11,"x":11,"y":10,"tx":560,"ty":160},"12_0":{"id":2,"x":12,"y":0,"tx":520,"ty":160},"12_1":{"id":2,"x":12,"y":1,"tx":520,"ty":160},"12_2":{"id":2,"x":12,"y":2,"tx":520,"ty":160},"12_3":{"id":2,"x":12,"y":3,"tx":520,"ty":160},"12_4":{"id":2,"x":12,"y":4,"tx":520,"ty":160},"12.5":{"id":2,"x":12,"y":5,"tx":520,"ty":160},"12_5":{"id":10,"x":12,"y":5,"tx":480,"ty":40},"12_7":{"id":18,"x":12,"y":7,"tx":600,"ty":200},"12_8":{"id":18,"x":12,"y":8,"tx":600,"ty":200},"12_9":{"id":18,"x":12,"y":9,"tx":600,"ty":200},"12_10":{"id":18,"x":12,"y":10,"tx":600,"ty":200},"13_0":{"id":2,"x":13,"y":0,"tx":520,"ty":160},"13_1":{"id":2,"x":13,"y":1,"tx":520,"ty":160},"13_2":{"id":2,"x":13,"y":2,"tx":520,"ty":160},"13_3":{"id":2,"x":13,"y":3,"tx":520,"ty":160},"13_4":{"id":2,"x":13,"y":4,"tx":520,"ty":160},"13_5":{"id":2,"x":13,"y":5,"tx":520,"ty":160},"13.6":{"id":2,"x":13,"y":6,"tx":520,"ty":160},"13_6":{"id":10.1,"x":13,"y":6,"tx":480,"ty":80},"13_8":{"id":18,"x":13,"y":8,"tx":600,"ty":200},"13_9":{"id":18,"x":13,"y":9,"tx":600,"ty":200},"13_10":{"id":18,"x":13,"y":10,"tx":600,"ty":200},"14.0":{"id":2,"x":14,"y":0,"tx":520,"ty":160},"14_0":{"id":7,"x":14,"y":0,"tx":480,"ty":0},"14.1":{"id":2,"x":14,"y":1,"tx":520,"ty":160},"14_2":{"id":2,"x":14,"y":2,"tx":520,"ty":160},"14_3":{"id":2,"x":14,"y":3,"tx":520,"ty":160},"14_4":{"id":2,"x":14,"y":4,"tx":520,"ty":160},"14_5":{"id":2,"x":14,"y":5,"tx":520,"ty":160},"14_6":{"id":2,"x":14,"y":6,"tx":520,"ty":160},"14_8":{"id":9.3,"x":14,"y":8,"tx":600,"ty":120},"14_9":{"id":9.3,"x":14,"y":9,"tx":600,"ty":120},"14_10":{"id":9.3,"x":14,"y":10,"tx":600,"ty":120},"15.0":{"id":2,"x":15,"y":0,"tx":520,"ty":160},"15.1":{"id":2,"x":15,"y":1,"tx":520,"ty":160},"15_1":{"id":7,"x":15,"y":1,"tx":480,"ty":0},"15_2":{"id":2,"x":15,"y":2,"tx":520,"ty":160},"15_3":{"id":17,"x":15,"y":3,"tx":560,"ty":200},"15_4":{"id":17,"x":15,"y":4,"tx":560,"ty":200},"15_5":{"id":17,"x":15,"y":5,"tx":560,"ty":200},"15_6":{"id":2,"x":15,"y":6,"tx":520,"ty":160},"15_8":{"id":2,"x":15,"y":8,"tx":520,"ty":160},"15_9":{"id":2,"x":15,"y":9,"tx":520,"ty":160},"15_10":{"id":2,"x":15,"y":10,"tx":520,"ty":160}}};
let pups = {"jukejuice":{"id":6.1,"x":14,"y":1,"tx":480,"ty":160}, "rollingbomb":{"id":6.2,"x":2,"y":2,"tx":480,"ty":200}, "tagpro":{"id":6.3,"x":15,"y":0,"tx":480,"ty":240}, "placeholder":{"id":6,"x":2,"y":9,"tx":480,"ty":320} };
let walls = {"0":{"q":0,"x":0,"y":0,"tx":0,"ty":280},"1":{"q":1,"x":0,"y":0,"tx":220,"ty":200},"2":{"q":2,"x":0,"y":0,"tx":220,"ty":220},"3":{"q":3,"x":0,"y":0,"tx":0,"ty":220},"4":{"q":0,"x":0,"y":1,"tx":0,"ty":200},"5":{"q":1,"x":0,"y":1,"tx":220,"ty":240},"6":{"q":2,"x":0,"y":1,"tx":300,"ty":340},"7":{"q":3,"x":0,"y":1,"tx":0,"ty":220},"8":{"q":0,"x":0,"y":2,"tx":0,"ty":200},"9":{"q":1,"x":0,"y":2,"tx":300,"ty":360},"10":{"q":2,"x":0,"y":2,"tx":460,"ty":220},"11":{"q":3,"x":0,"y":2,"tx":0,"ty":220},"12":{"q":0,"x":0,"y":3,"tx":0,"ty":200},"13":{"q":1,"x":0,"y":3,"tx":460,"ty":200},"14":{"q":2,"x":0,"y":3,"tx":460,"ty":220},"15":{"q":3,"x":0,"y":3,"tx":0,"ty":220},"16":{"q":0,"x":0,"y":4,"tx":0,"ty":200},"17":{"q":1,"x":0,"y":4,"tx":460,"ty":200},"18":{"q":2,"x":0,"y":4,"tx":460,"ty":300},"19":{"q":3,"x":0,"y":4,"tx":0,"ty":300},"20":{"q":0,"x":0,"y":7,"tx":0,"ty":280},"21":{"q":1,"x":0,"y":7,"tx":460,"ty":280},"22":{"q":2,"x":0,"y":7,"tx":460,"ty":220},"23":{"q":3,"x":0,"y":7,"tx":0,"ty":220},"24":{"q":0,"x":0,"y":8,"tx":0,"ty":200},"25":{"q":1,"x":0,"y":8,"tx":460,"ty":200},"26":{"q":2,"x":0,"y":8,"tx":460,"ty":220},"27":{"q":3,"x":0,"y":8,"tx":0,"ty":220},"28":{"q":0,"x":0,"y":9,"tx":0,"ty":200},"29":{"q":1,"x":0,"y":9,"tx":460,"ty":200},"30":{"q":2,"x":0,"y":9,"tx":60,"ty":340},"31":{"q":3,"x":0,"y":9,"tx":0,"ty":220},"32":{"q":0,"x":0,"y":10,"tx":0,"ty":200},"33":{"q":1,"x":0,"y":10,"tx":60,"ty":360},"34":{"q":2,"x":0,"y":10,"tx":220,"ty":220},"35":{"q":3,"x":0,"y":10,"tx":0,"ty":220},"36":{"q":0,"x":0,"y":11,"tx":0,"ty":200},"37":{"q":1,"x":0,"y":11,"tx":220,"ty":240},"38":{"q":2,"x":0,"y":11,"tx":340,"ty":420},"39":{"q":3,"x":0,"y":11,"tx":0,"ty":300},"40":{"q":0,"x":1,"y":0,"tx":240,"ty":200},"41":{"q":1,"x":1,"y":0,"tx":220,"ty":200},"42":{"q":2,"x":1,"y":0,"tx":340,"ty":300},"43":{"q":3,"x":1,"y":0,"tx":240,"ty":220},"44":{"q":0,"x":1,"y":1,"tx":240,"ty":400},"45":{"q":1,"x":1,"y":1,"tx":340,"ty":320},"46":{"q":3,"x":1,"y":1,"tx":320,"ty":340},"47":{"q":0,"x":1,"y":10,"tx":80,"ty":360},"48":{"q":2,"x":1,"y":10,"tx":100,"ty":380},"49":{"q":3,"x":1,"y":10,"tx":240,"ty":340},"50":{"q":0,"x":1,"y":11,"tx":240,"ty":240},"51":{"q":1,"x":1,"y":11,"tx":100,"ty":400},"52":{"q":2,"x":1,"y":11,"tx":340,"ty":420},"53":{"q":3,"x":1,"y":11,"tx":360,"ty":420},"54":{"q":0,"x":2,"y":0,"tx":240,"ty":200},"55":{"q":1,"x":2,"y":0,"tx":460,"ty":280},"56":{"q":2,"x":2,"y":0,"tx":460,"ty":300},"57":{"q":3,"x":2,"y":0,"tx":360,"ty":300},"58":{"q":0,"x":2,"y":11,"tx":120,"ty":400},"59":{"q":1,"x":2,"y":11,"tx":220,"ty":200},"60":{"q":2,"x":2,"y":11,"tx":340,"ty":420},"61":{"q":3,"x":2,"y":11,"tx":360,"ty":420},"62":{"q":0,"x":3,"y":11,"tx":240,"ty":200},"63":{"q":1,"x":3,"y":11,"tx":220,"ty":200},"64":{"q":2,"x":3,"y":11,"tx":340,"ty":420},"65":{"q":3,"x":3,"y":11,"tx":360,"ty":420},"66":{"q":0,"x":4,"y":11,"tx":240,"ty":200},"67":{"q":1,"x":4,"y":11,"tx":220,"ty":200},"68":{"q":2,"x":4,"y":11,"tx":340,"ty":420},"69":{"q":3,"x":4,"y":11,"tx":360,"ty":420},"70":{"q":0,"x":5,"y":0,"tx":0,"ty":280},"71":{"q":1,"x":5,"y":0,"tx":220,"ty":200},"72":{"q":2,"x":5,"y":0,"tx":340,"ty":420},"73":{"q":3,"x":5,"y":0,"tx":0,"ty":300},"74":{"q":0,"x":5,"y":11,"tx":240,"ty":200},"75":{"q":1,"x":5,"y":11,"tx":220,"ty":200},"76":{"q":2,"x":5,"y":11,"tx":340,"ty":420},"77":{"q":3,"x":5,"y":11,"tx":360,"ty":420},"78":{"q":0,"x":6,"y":0,"tx":240,"ty":200},"79":{"q":1,"x":6,"y":0,"tx":220,"ty":200},"80":{"q":2,"x":6,"y":0,"tx":380,"ty":420},"81":{"q":3,"x":6,"y":0,"tx":360,"ty":420},"82":{"q":0,"x":6,"y":11,"tx":240,"ty":200},"83":{"q":1,"x":6,"y":11,"tx":220,"ty":200},"84":{"q":2,"x":6,"y":11,"tx":340,"ty":420},"85":{"q":3,"x":6,"y":11,"tx":360,"ty":420},"86":{"q":0,"x":7,"y":0,"tx":280,"ty":200},"87":{"q":1,"x":7,"y":0,"tx":300,"ty":200},"88":{"q":3,"x":7,"y":0,"tx":400,"ty":420},"89":{"q":0,"x":7,"y":5,"tx":0,"ty":280},"90":{"q":1,"x":7,"y":5,"tx":220,"ty":200},"91":{"q":2,"x":7,"y":5,"tx":340,"ty":300},"92":{"q":3,"x":7,"y":5,"tx":0,"ty":220},"93":{"q":0,"x":7,"y":6,"tx":0,"ty":240},"94":{"q":1,"x":7,"y":6,"tx":340,"ty":320},"95":{"q":3,"x":7,"y":6,"tx":200,"ty":300},"96":{"q":0,"x":7,"y":11,"tx":240,"ty":200},"97":{"q":1,"x":7,"y":11,"tx":220,"ty":200},"98":{"q":2,"x":7,"y":11,"tx":340,"ty":420},"99":{"q":3,"x":7,"y":11,"tx":360,"ty":420},"100":{"q":0,"x":8,"y":5,"tx":240,"ty":200},"101":{"q":1,"x":8,"y":5,"tx":220,"ty":200},"102":{"q":2,"x":8,"y":5,"tx":340,"ty":420},"103":{"q":3,"x":8,"y":5,"tx":360,"ty":300},"104":{"q":0,"x":8,"y":11,"tx":240,"ty":200},"105":{"q":1,"x":8,"y":11,"tx":220,"ty":200},"106":{"q":2,"x":8,"y":11,"tx":340,"ty":420},"107":{"q":3,"x":8,"y":11,"tx":360,"ty":420},"108":{"q":0,"x":9,"y":5,"tx":240,"ty":200},"109":{"q":1,"x":9,"y":5,"tx":220,"ty":200},"110":{"q":2,"x":9,"y":5,"tx":340,"ty":420},"111":{"q":3,"x":9,"y":5,"tx":360,"ty":420},"112":{"q":0,"x":9,"y":11,"tx":240,"ty":200},"113":{"q":1,"x":9,"y":11,"tx":220,"ty":200},"114":{"q":2,"x":9,"y":11,"tx":340,"ty":420},"115":{"q":3,"x":9,"y":11,"tx":360,"ty":420},"116":{"q":0,"x":10,"y":5,"tx":240,"ty":200},"117":{"q":1,"x":10,"y":5,"tx":220,"ty":200},"118":{"q":2,"x":10,"y":5,"tx":380,"ty":300},"119":{"q":3,"x":10,"y":5,"tx":360,"ty":420},"120":{"q":0,"x":10,"y":11,"tx":240,"ty":200},"121":{"q":1,"x":10,"y":11,"tx":220,"ty":200},"122":{"q":2,"x":10,"y":11,"tx":340,"ty":420},"123":{"q":3,"x":10,"y":11,"tx":360,"ty":420},"124":{"q":0,"x":11,"y":5,"tx":240,"ty":200},"125":{"q":1,"x":11,"y":5,"tx":460,"ty":280},"126":{"q":2,"x":11,"y":5,"tx":300,"ty":380},"127":{"q":3,"x":11,"y":5,"tx":400,"ty":300},"128":{"q":0,"x":11,"y":6,"tx":400,"ty":320},"129":{"q":1,"x":11,"y":6,"tx":300,"ty":400},"130":{"q":2,"x":11,"y":6,"tx":100,"ty":300},"131":{"q":3,"x":11,"y":6,"tx":0,"ty":300},"132":{"q":0,"x":11,"y":11,"tx":240,"ty":200},"133":{"q":1,"x":11,"y":11,"tx":220,"ty":200},"134":{"q":2,"x":11,"y":11,"tx":340,"ty":420},"135":{"q":3,"x":11,"y":11,"tx":360,"ty":420},"136":{"q":0,"x":12,"y":6,"tx":320,"ty":400},"137":{"q":1,"x":12,"y":6,"tx":460,"ty":280},"138":{"q":2,"x":12,"y":6,"tx":300,"ty":380},"139":{"q":3,"x":12,"y":6,"tx":120,"ty":300},"140":{"q":0,"x":12,"y":7,"tx":120,"ty":320},"141":{"q":1,"x":12,"y":7,"tx":380,"ty":160},"142":{"q":2,"x":12,"y":7,"tx":60,"ty":420},"143":{"q":0,"x":12,"y":11,"tx":240,"ty":200},"144":{"q":1,"x":12,"y":11,"tx":220,"ty":200},"145":{"q":2,"x":12,"y":11,"tx":340,"ty":420},"146":{"q":3,"x":12,"y":11,"tx":360,"ty":420},"147":{"q":0,"x":13,"y":7,"tx":320,"ty":400},"148":{"q":1,"x":13,"y":7,"tx":220,"ty":200},"149":{"q":2,"x":13,"y":7,"tx":340,"ty":420},"150":{"q":3,"x":13,"y":7,"tx":80,"ty":420},"151":{"q":0,"x":13,"y":11,"tx":240,"ty":200},"152":{"q":1,"x":13,"y":11,"tx":220,"ty":200},"153":{"q":2,"x":13,"y":11,"tx":340,"ty":420},"154":{"q":3,"x":13,"y":11,"tx":360,"ty":420},"155":{"q":0,"x":14,"y":7,"tx":240,"ty":200},"156":{"q":1,"x":14,"y":7,"tx":220,"ty":200},"157":{"q":2,"x":14,"y":7,"tx":340,"ty":420},"158":{"q":3,"x":14,"y":7,"tx":360,"ty":420},"159":{"q":0,"x":14,"y":11,"tx":240,"ty":200},"160":{"q":1,"x":14,"y":11,"tx":220,"ty":200},"161":{"q":2,"x":14,"y":11,"tx":340,"ty":420},"162":{"q":3,"x":14,"y":11,"tx":360,"ty":420},"163":{"q":0,"x":15,"y":7,"tx":240,"ty":200},"164":{"q":1,"x":15,"y":7,"tx":220,"ty":200},"165":{"q":2,"x":15,"y":7,"tx":380,"ty":300},"166":{"q":3,"x":15,"y":7,"tx":360,"ty":420},"167":{"q":0,"x":15,"y":11,"tx":240,"ty":200},"168":{"q":1,"x":15,"y":11,"tx":140,"ty":400},"169":{"q":2,"x":15,"y":11,"tx":340,"ty":420},"170":{"q":3,"x":15,"y":11,"tx":360,"ty":420},"171":{"q":0,"x":16,"y":7,"tx":240,"ty":200},"172":{"q":1,"x":16,"y":7,"tx":460,"ty":280},"173":{"q":2,"x":16,"y":7,"tx":460,"ty":220},"174":{"q":3,"x":16,"y":7,"tx":400,"ty":300},"175":{"q":0,"x":16,"y":8,"tx":400,"ty":320},"176":{"q":1,"x":16,"y":8,"tx":460,"ty":200},"177":{"q":2,"x":16,"y":8,"tx":460,"ty":220},"178":{"q":3,"x":16,"y":8,"tx":0,"ty":220},"179":{"q":0,"x":16,"y":9,"tx":0,"ty":200},"180":{"q":1,"x":16,"y":9,"tx":460,"ty":200},"181":{"q":2,"x":16,"y":9,"tx":460,"ty":220},"182":{"q":3,"x":16,"y":9,"tx":0,"ty":220},"183":{"q":0,"x":16,"y":10,"tx":0,"ty":200},"184":{"q":1,"x":16,"y":10,"tx":460,"ty":200},"185":{"q":2,"x":16,"y":10,"tx":460,"ty":220},"186":{"q":3,"x":16,"y":10,"tx":160,"ty":380},"187":{"q":0,"x":16,"y":11,"tx":160,"ty":400},"188":{"q":1,"x":16,"y":11,"tx":460,"ty":200},"189":{"q":2,"x":16,"y":11,"tx":460,"ty":300},"190":{"q":3,"x":16,"y":11,"tx":360,"ty":420}};
canvas.width = map.info.width * 40;
canvas.height = map.info.height * 40;
let ctx = canvas.getContext("2d");
let img = document.createElement('img');
img.crossOrigin = 'Anonymous';
img.src = url;
//floor, objects..
$.each(map.data, function(key, value) {
ctx.drawImage(img, value.tx, value.ty, 40, 40, value.x*40, value.y*40, 40, 40);
});
//pups..
$.each(pups, function(key, value) {
ctx.drawImage(img, value.tx, value.ty, 40, 40, value.x*40, value.y*40, 40, 40);
});
//walls...
$.each(walls, function(key, value) {
if (value.q >= 0) {
let xoffset = 0, yoffset = 0;
if ((value.q === 1) || (value.q === 2)) xoffset = 20;
if ((value.q === 0) || (value.q === 1)) yoffset = -20;
ctx.drawImage(img, value.tx, value.ty, 20, 20, value.x*40+xoffset, value.y*40+yoffset+20, 20, 20);
}
});
img = null;
return canvas;
}
// Drag/Drop events...
$(document).on('dragover', function(e) {
e.stopPropagation();
e.preventDefault();
$('#TTM_Tiles').css({ 'border':'2px dashed red' });
$('#TTM_Tiles').css({ 'box-shadow':'0 0 10px 4px red' });
}).on('dragleave', function(e) {
e.stopPropagation();
e.preventDefault();
$('#TTM_Tiles').css({ 'border':'2px solid transparent' });
$('#TTM_Tiles').css({ 'box-shadow':'' });
});
$('#TTM_Tiles').on('dragover', function(e) {
e.stopPropagation();
e.preventDefault();
$(this).css({ 'border':'2px dashed chartreuse' });
$(this).css({ 'box-shadow':'0 0 10px 4px chartreuse' });
}).on('dragleave', function(e) {
e.stopPropagation();
e.preventDefault();
$(this).css({ 'border':'2px dashed red' });
$(this).css({ 'box-shadow':'0 0 10px 4px red' });
}).on('drop', function(e) {
e.stopPropagation();
e.preventDefault();
$(this).css({ 'border':'' });
$(this).css({ 'box-shadow':'' });
handleDrop(e);
});
function handleDrop(e) {
let data = e.originalEvent.dataTransfer;
if (data.files[0]) { // Handle as a file...
let reader = new FileReader();
let filename = data.files[0].name;
reader.onload = function(file) {
draggedData = file.target.result;
setTimeout(function() {
loadImage(draggedData, filename);
}, 100);
};
reader.readAsDataURL(data.files[0]);
} else { // Handle as a URL...
data.items[0].getAsString(function(url) {
if (!url.startsWith('http')) url = 'http://' + url;
setTimeout(function() {
loadImage(url, url);
}, 100);
});
}
}
const presets = {
'W1':{
title: 'Good for: Walls (apply over existing tile)',
data: {
'shine':false,'border':false,'checkered':false,'pattern':false,
'specks':true, 'specks_color':'#00ccaa', 'specks_opacity':18, 'specks_length':20, 'specks_count':10, 'specks_angle':0,
'stripes':true, 'stripes_color':'#ffffff', 'stripes_opacity':6, 'stripes_size':5, 'stripes_linewidth':1, 'stripes_direction':'diagonal'
}
},
'T1':{
title: 'Good for: TeamTiles (apply over existing tile)',
data: {
'shine':false,'border':false,'checkered':false,'stripes':false,
'specks':true, 'specks_color':'#ffffff', 'specks_opacity':30, 'specks_length':15, 'specks_count':15, 'specks_angle':315,
'pattern':true, 'pattern_shape':'circle', 'pattern_color':'#ff0000', 'pattern_opacity':40, 'pattern_size':10, 'pattern_margin':5, 'pattern_stroke':true, 'pattern_fill':true
}
},
'T2':{
title: 'Good for: TeamTiles (new tile - change base color accordingly)',
data: {
'specks':false,'border':false,
'checkered':true, 'checkered_size':20, 'checkered_color':'#bb0000', 'checkered_alt':14,
'pattern':true, 'pattern_shape':'square', 'pattern_color':'#ffffff', 'pattern_opacity':12, 'pattern_size':20, 'pattern_margin':8, 'pattern_stroke':false, 'pattern_fill':true,
'stripes':true, 'stripes_direction':'plus', 'stripes_color':'#000000', 'stripes_opacity':16, 'stripes_size':40, 'stripes_linewidth':21,
'shine':true, 'shine_x':20, 'shine_y':20, 'shine_radius':24, 'shine_color_inner':'#ffffff', 'shine_color_outer':'#000000', 'shine_opacity_inner':14, 'shine_opacity_outer':1, 'shine_behind':false
}
},
'T3':{
title: 'Good for: TeamTiles or EndZones (apply over existing tile)',
data: {
'stripes':false,'border':false,'checkered':false,'pattern':false,
'specks':true, 'specks_color':'#ffffff', 'specks_opacity':20, 'specks_length':16, 'specks_count':16, 'specks_angle':315,
'shine':true, 'shine_x':10, 'shine_y':10, 'shine_radius':50, 'shine_color_inner':'#ffffff', 'shine_color_outer':'#ffffff', 'shine_opacity_inner':40, 'shine_opacity_outer':1, 'shine_behind':false
}
},
'E1':{
title: 'Good for: EndZones (new tile - change base color accordingly)',
data: {
'shine':false,'border':false,'specks':false,'pattern':false,
'checkered':true, 'checkered_size':10, 'checkered_color':'#0067ce', 'checkered_alt':-50,
'stripes':true, 'stripes_direction':'cross', 'stripes_color':'#ffffff', 'stripes_opacity':7, 'stripes_size':5, 'stripes_linewidth':1
}
},
'G1':{
title: 'Good for: Gates (new tile - change base color accordingly)',
data: {
'shine':false,'border':false,'specks':false,'stripes':false,
'checkered':true, 'checkered_size':40, 'checkered_color':'#00ee00', 'checkered_alt':0, //plain green base tile
'pattern':true, 'pattern_shape':'corner', 'pattern_color':'#009900', 'pattern_opacity':100, 'pattern_size':10, 'pattern_margin':8, 'pattern_stroke':true, 'pattern_fill':false
}
},
'G2':{
title: 'Good for: Gates (new tile - change base color accordingly)',
data: {
'specks':false,
'checkered':true, 'checkered_size':40, 'checkered_color':'#00ee00', 'checkered_alt':0, //plain blue base tile
'stripes':true, 'stripes_direction':'cross', 'stripes_color':'#000000', 'stripes_opacity':20, 'stripes_size':40, 'stripes_linewidth':7,
'pattern':true, 'pattern_shape':'pyramid', 'pattern_color':'#00ee00', 'pattern_opacity':40, 'pattern_size':5, 'pattern_margin':40, 'pattern_stroke':true, 'pattern_fill':true,
'border':true, 'border_color':'#000000', 'border_opacity':50, 'border_circle':false, 'border_size':37, 'border_width':1, 'border_dash':1,
'shine':true, 'shine_x':20, 'shine_y':20, 'shine_radius':30, 'shine_color_inner':'#ffffff', 'shine_color_outer':'#000000', 'shine_opacity_inner':30, 'shine_opacity_outer':10, 'shine_behind':false
}
},
'G3':{
title: 'Good for: Gates (new tile - change base color accordingly)',
data: {
'shine':false,'border':false,'stripes':false,'specks':false,
'checkered':true, 'checkered_size':40, 'checkered_color':'#000000', 'checkered_alt':0, //plain black base tile
'pattern':true, 'pattern_shape':'pyramid', 'pattern_color':'#77ff00', 'pattern_opacity':100, 'pattern_size':20, 'pattern_margin':18, 'pattern_stroke':false, 'pattern_fill':true
}
},
'G4':{
title: 'Good for: Gates (apply over existing tile)',
data: {
'checkered':false,'stripes':false,'specks':false,
'shine':true, 'shine_x':10, 'shine_y':10, 'shine_radius':24, 'shine_color_inner':'#ffffff', 'shine_color_outer':'#000000', 'shine_opacity_inner':20, 'shine_opacity_outer':1, 'shine_behind':false,
'border':true, 'border_color':'#000000', 'border_opacity':100, 'border_circle':false, 'border_size':32, 'border_width':1, 'border_dash':1,
'pattern':true, 'pattern_shape':'corner', 'pattern_color':'#ffffff', 'pattern_opacity':100, 'pattern_size':40, 'pattern_margin':30, 'pattern_stroke':false, 'pattern_fill':true
}
},
'F1':{
title: 'Good for: Floors (new tile)',
data: {
'shine':false,'border':false,'stripes':false,'pattern':false,
'checkered':true, 'checkered_size':40, 'checkered_color':'#000000', 'checkered_alt':0, //plain black base tile
'specks':true, 'specks_color':'#ffffff', 'specks_opacity':15, 'specks_length':1, 'specks_count':75, 'specks_angle':360,
}
},
'F2':{
title: 'Good for: Floors (new tile)',
data: {
'shine':false,'stripes':false,'specks':false,
'checkered':true, 'checkered_size':40, 'checkered_color':'#000000', 'checkered_alt':0, //plain black base tile
'border':true, 'border_color':'#777777', 'border_opacity':10, 'border_circle':false, 'border_size':39, 'border_width':1, 'border_dash':1,
'pattern':true, 'pattern_shape':'corner', 'pattern_color':'#ffffff', 'pattern_opacity':15, 'pattern_size':13, 'pattern_margin':10, 'pattern_stroke':false, 'pattern_fill':true
}
},
};
$.each(presets, function(key, value) {
$('#TTM_Presets').append('<div class="TTM_Preset" data-preset="'+key+'" title="'+value.title+'">'+key+'</div>');
});
let loadPreset = function(preset) {
if (!preset || !presets.hasOwnProperty(preset)) return;
$.each(presets[preset].data, function(k, v) {
let element = $('#TTM_ModifyMenu_Inner').find('[data-saveto="'+k+'"]');
if ((v === true) || (v === false)) {
element.prop('checked', v);
} else {
element.val(v);
}
let group = $(element).data('group');
if (group) {
if ((v === true) || (v > 0)) $('.' + group).slideDown(400);
else $('.' + group).slideUp(400);
}
});
updateModifyTilePreviews();
};
$('.TTM_Preset').on('click', function() {
loadPreset(this.dataset.preset);
});
function addCheckered(ctx) {
if (!ctx) return;
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
let size = $('div.TTM_Group_Add_Checkered').find('input[data-saveto="checkered_size"]').val();
let color = $('div.TTM_Group_Add_Checkered').find('input[data-saveto="checkered_color"]').val();
let opacity = $('div.TTM_Group_Add_Checkered').find('input[data-saveto="checkered_opacity"]').val() / 100;
let altColor = colorLuminance(color, $('div.TTM_Group_Add_Checkered').find('input[data-saveto="checkered_alt"]').val() / 100);
ctx.globalCompositeOperation = 'source-atop';
let pattern = new OffscreenCanvas(size * 2, size * 2);
let pctx = pattern.getContext('2d');
pctx.globalAlpha = opacity;
pctx.beginPath();
pctx.fillStyle = color;
pctx.fillRect(0, 0, size, size);
pctx.fillStyle = altColor;
pctx.fillRect(size, 0, size, size);
pctx.fillStyle = altColor;
pctx.fillRect(0, size, size, size);
pctx.fillStyle = color;
pctx.fillRect(size, size, size, size);
pctx.closePath();
let patt = ctx.createPattern(pattern, "repeat");
ctx.fillStyle = patt;
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
ctx.globalCompositeOperation = "source-over";
pattern = null;
}
function addSpecks(ctx) { //, count, color, opacity, specks, lines, circles, width=1
if (!ctx) return;
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
let color = $('div.TTM_Group_Add_Specks').find('input[data-saveto="specks_color"]').val();
let opacity = $('div.TTM_Group_Add_Specks').find('input[data-saveto="specks_opacity"]').val() / 100;
let count = $('div.TTM_Group_Add_Specks').find('input[data-saveto="specks_count"]').val();
if (canvasWidth > 40) count = count * 132; //walls
let length = $('div.TTM_Group_Add_Specks').find('input[data-saveto="specks_length"]').val();
let angle = $('div.TTM_Group_Add_Specks').find('input[data-saveto="specks_angle"]').val() * Math.PI / 180;
let a = angle;
ctx.globalCompositeOperation = 'source-atop';
ctx.fillStyle = hexToRgbA(color, opacity);
ctx.strokeStyle = hexToRgbA(color, opacity);
for (let i=0; i<count; i++) {
if (angle === 0) a = Math.random() * Math.PI * 2;
let sx = Math.random()*canvasWidth;
let sy = Math.random()*canvasHeight;
let d = Math.random()*length;
let dx = sx + Math.cos(a) * d;
let dy = sy + Math.sin(a) * d;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(sx, sy);
ctx.lineTo(dx, dy);
ctx.closePath();
ctx.stroke();
}
ctx.globalCompositeOperation = "source-over";
}
function addPattern(ctx) {
if (!ctx) return;
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
let color = $('div.TTM_Group_Add_Pattern').find('input[data-saveto="pattern_color"]').val();
let opacity = $('div.TTM_Group_Add_Pattern').find('input[data-saveto="pattern_opacity"]').val() / 100;
let size = $('div.TTM_Group_Add_Pattern').find('input[data-saveto="pattern_size"]').val() || 20;
let margin = $('div.TTM_Group_Add_Pattern').find('input[data-saveto="pattern_margin"]').val();
let shape = $('div.TTM_Group_Add_Pattern').find('select[data-saveto="pattern_shape"]').val();
let stroke = $('div.TTM_Group_Add_Pattern').find('input[data-saveto="pattern_stroke"]').is(':checked');
let fill = $('div.TTM_Group_Add_Pattern').find('input[data-saveto="pattern_fill"]').is(':checked');
ctx.globalCompositeOperation = 'source-atop';
let pattern = new OffscreenCanvas(size, size);
let pctx = pattern.getContext('2d');
pctx.lineWidth = 1;
//pctx.translate(-0.5, -0.5);
if (shape === 'corner') {
let p1 = size / 2 - margin / 2;
let p2 = size / 2 + margin / 2;
let width = margin;
pctx.beginPath();
pctx.moveTo(p2, p1);
pctx.lineTo(p2, p2);
pctx.lineTo(p1, p2);
pctx.moveTo(p1, p2);
pctx.closePath();
if (stroke) {
pctx.strokeStyle = hexToRgbA(color, opacity);
pctx.stroke();
}
if (fill) {
pctx.beginPath();
pctx.moveTo(p1, p2);
pctx.lineTo(p1, p1);
pctx.lineTo(p2, p1);
pctx.moveTo(p2, p1);
pctx.closePath();
pctx.strokeStyle = hexToRgbA(colorLuminance(color, -0.35), opacity);
pctx.stroke();
}
} else if (shape === 'rightangle') {
let p1 = size / 2 - margin / 2;
let p2 = size / 2 + margin / 2;
let width = margin;
pctx.beginPath();
pctx.moveTo(p1, p2);
pctx.lineTo(p1, p1);
pctx.lineTo(p2, p1);
pctx.closePath();
if (stroke) {
pctx.strokeStyle = hexToRgbA(color, opacity);
pctx.stroke();
}
if (fill) {
pctx.fillStyle = hexToRgbA(color, opacity);
pctx.fill();
}
} else if (shape === 'pyramid') {
let p1 = size / 2 - margin / 2;
let p2 = size / 2 + margin / 2;
let c = size / 2;
let width = margin;
//1--------------------
pctx.beginPath();
pctx.strokeStyle = hexToRgbA(colorLuminance(color, 0.2), opacity);
pctx.fillStyle = hexToRgbA(colorLuminance(color, 0.3), opacity);
pctx.moveTo(p1, p1);
pctx.lineTo(p2, p1);
pctx.lineTo(c, c);
pctx.lineTo(p1, p1);
pctx.moveTo(p1, p1);
if (stroke) pctx.stroke();
if (fill) pctx.fill();
pctx.closePath();
//2--------------------
pctx.beginPath();
pctx.strokeStyle = hexToRgbA(color, opacity);
pctx.fillStyle = hexToRgbA(colorLuminance(color, 0.1), opacity);
pctx.moveTo(p2, p1);
pctx.lineTo(p2, p2);
pctx.lineTo(c, c);
pctx.lineTo(p2, p1);
pctx.moveTo(p2, p1);
if (stroke) pctx.stroke();
if (fill) pctx.fill();
pctx.closePath();
//3--------------------
pctx.beginPath();
pctx.strokeStyle = hexToRgbA(colorLuminance(color, -0.1), opacity);
pctx.fillStyle = hexToRgbA(colorLuminance(color, -0.2), opacity);
pctx.moveTo(p2, p2);
pctx.lineTo(p1, p2);
pctx.lineTo(c, c);
pctx.lineTo(p2, p2);
pctx.moveTo(p2, p2);
if (stroke) pctx.stroke();
if (fill) pctx.fill();
pctx.closePath();
//4--------------------
pctx.beginPath();
pctx.strokeStyle = hexToRgbA(colorLuminance(color, -0.2), opacity);
pctx.fillStyle = hexToRgbA(colorLuminance(color, -0.3), opacity);
pctx.moveTo(p1, p2);
pctx.lineTo(p1, p1);
pctx.lineTo(c, c);
pctx.lineTo(p1, p2);
pctx.moveTo(p1, p2);
if (stroke) pctx.stroke();
if (fill) pctx.fill();
pctx.closePath();
} else if (shape === 'square') {
let p1 = size / 2 - margin / 2;
let p2 = size / 2 + margin / 2;
let width = margin;
if (stroke) {
pctx.strokeStyle = hexToRgbA(color, opacity);
pctx.rect(p1, p1, width, width);
pctx.stroke();
}
if (fill) {
pctx.fillStyle = hexToRgbA(color, opacity);
pctx.fillRect(p1, p1, width, width);
}
} else if (shape === 'circle') {
let radius = margin/2;
if (stroke) {
pctx.strokeStyle = hexToRgbA(color, opacity);
pctx.arc(size/2, size/2, radius, 0, Math.PI*2);
pctx.stroke();
}
if (fill) {
pctx.fillStyle = hexToRgbA(color, opacity);
pctx.arc(size/2, size/2, radius, 0, Math.PI*2);
pctx.fill();
}
}
let patt = ctx.createPattern(pattern, "repeat");
ctx.fillStyle = patt;
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
ctx.globalCompositeOperation = "source-over";
pattern = null;
}
function addStripes(ctx) {
if (!ctx) return;
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
let color = $('div.TTM_Group_Add_Stripes').find('input[data-saveto="stripes_color"]').val();
let opacity = $('div.TTM_Group_Add_Stripes').find('input[data-saveto="stripes_opacity"]').val() / 100;
let direction = $('div.TTM_Group_Add_Stripes').find('select[data-saveto="stripes_direction"]').val();
let size = $('div.TTM_Group_Add_Stripes').find('input[data-saveto="stripes_size"]').val();
let lineWidth = $('div.TTM_Group_Add_Stripes').find('input[data-saveto="stripes_linewidth"]').val();
let dashed = false;
let translate = false;
ctx.globalCompositeOperation = 'source-atop';
let startX = 0;
let startY = 0;
let endX = 0;
let endY = 0;
if (direction === 'horizontal') {
endX = size;
endY = 0;
} else if (direction === 'vertical') {
endX = 0;
endY = size;
} else if (direction === 'diagonal') {
endX = size;
endY = size;
} else if (direction === 'diagonalback') {
startX = size;
startY = 0;
endX = 0;
endY = size;
} else if (direction === 'plus') {
startX = size/2;
endX = size/2;
endY = size;
} else if (direction === 'cross') {
endX = size;
endY = size;
}
let pattern = new OffscreenCanvas(size, size);
let pctx = pattern.getContext('2d');
pctx.lineWidth = lineWidth;
pctx.strokeStyle = hexToRgbA(color, opacity);
if (dashed) pctx.setLineDash([2, 2]);
if (translate) pctx.translate(-0.5, -0.5);
pctx.beginPath();
pctx.moveTo(startX, startY);
pctx.lineTo(endX, endY);
if (direction === 'plus') {
pctx.moveTo(startY, startX);
pctx.lineTo(endY, endX);
} else if (direction === 'cross') {
pctx.moveTo(endX, startY);
pctx.lineTo(startX, endY);
}
pctx.closePath();
pctx.stroke();
let patt = ctx.createPattern(pattern, "repeat");
ctx.fillStyle = patt;
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
pattern = null;
ctx.globalCompositeOperation = "source-over";
}
function addShine(ctx) {
if (!ctx) return;
let x = $('div.TTM_Group_Add_Shine').find('input[data-saveto="shine_x"]').val();
let y = $('div.TTM_Group_Add_Shine').find('input[data-saveto="shine_y"]').val();
let size = $('div.TTM_Group_Add_Shine').find('input[data-saveto="shine_radius"]').val();
let c1 = $('div.TTM_Group_Add_Shine').find('input[data-saveto="shine_color_inner"]').val();
let c2 = $('div.TTM_Group_Add_Shine').find('input[data-saveto="shine_color_outer"]').val();
let o1 = $('div.TTM_Group_Add_Shine').find('input[data-saveto="shine_opacity_inner"]').val() / 100;
let o2 = $('div.TTM_Group_Add_Shine').find('input[data-saveto="shine_opacity_outer"]').val() / 100;
let gco = $('div.TTM_Group_Add_Shine').find('input[data-saveto="shine_behind"]').is(':checked') ? 'destination-over' : 'source-atop';
ctx.globalCompositeOperation = gco;
let pattern = new OffscreenCanvas(40, 40);
let pctx = pattern.getContext('2d');
let gradient = pctx.createRadialGradient(x,y,0, x,y,size);
gradient.addColorStop(0, hexToRgbA(c1, o1));
gradient.addColorStop(1, hexToRgbA(c2, o2));
pctx.fillStyle = gradient;
pctx.beginPath();
pctx.arc(x, y, size, 0, 2*Math.PI);
pctx.fill();
pctx.closePath();
let patt = ctx.createPattern(pattern, "repeat");
ctx.fillStyle = patt;
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.globalCompositeOperation = "source-over";
pattern = null;
}
function addBorder(ctx) {
if (!ctx) return;
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
let color = $('div.TTM_Group_Add_Border').find('input[data-saveto="border_color"]').val();
let opacity = $('div.TTM_Group_Add_Border').find('input[data-saveto="border_opacity"]').val() / 100;
let linewidth = $('div.TTM_Group_Add_Border').find('input[data-saveto="border_linewidth"]').val();
let size = $('div.TTM_Group_Add_Border').find('input[data-saveto="border_size"]').val();
let circle = $('div.TTM_Group_Add_Border').find('input[data-saveto="border_circle"]').is(':checked');
let dash = $('div.TTM_Group_Add_Border').find('input[data-saveto="border_dash"]').val();
//ctx.globalCompositeOperation = 'source-over';
ctx.lineWidth = linewidth;
ctx.strokeStyle = hexToRgbA(color, opacity);
if (dash > 1) ctx.setLineDash([dash, dash]);
ctx.beginPath();
if (circle) {
ctx.arc(20,20,size/2,0,Math.PI*2, false);
} else {
let p1 = 20 - size / 2;
ctx.rect(p1, p1, size, size);
}
ctx.closePath();
ctx.stroke();
ctx.setLineDash([]);
//ctx.globalCompositeOperation = "source-over";
}
//helpers...
const hexToRgb = hex =>
hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (m, r, g, b) => '#' + r + r + g + g + b + b)
.substring(1).match(/.{2}/g)
.map(x => parseInt(x, 16));
function hexToRgbA(hex, alpha=1){
if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
let c = hex.substring(1).split('');
if (c.length === 3) c = [c[0], c[0], c[1], c[1], c[2], c[2]];
c = '0x' + c.join('');
if (!$.isNumeric(alpha) || (alpha < 0) || (alpha > 1)) alpha = 1;
return 'rgba(' + [(c>>16)&255, (c>>8)&255, c&255].join(', ') + ', ' + alpha + ')';
}
}
function colorLuminance(hex, lum) {
hex = String(hex).replace(/[^0-9a-f]/gi, '');
if (hex.length < 6) {
hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
}
lum = lum || 0;
let rgb = "#", c, i;
for (i = 0; i < 3; i++) {
c = parseInt(hex.substr(i*2,2), 16);
c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
rgb += ("00"+c).substr(c.length);
}
return rgb;
}
function calcBezierPoint(t, p0, p1, p2, p3) {
let data = [p0, p1, p2, p3];
let at = 1 - t;
for (let i = 1; i < data.length; i++) {
for (let k = 0; k < data.length - i; k++) {
data[k] = {
x: data[k].x * at + data[k + 1].x * t,
y: data[k].y * at + data[k + 1].y * t
};
}
}
return data[0];
}
function addStyle(css) {
let s = document.createElement('style');
s.appendChild(document.createTextNode(css));
document.getElementsByTagName('head')[0].appendChild(s);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment