Skip to content

Instantly share code, notes, and snippets.

@nabbynz
Last active July 5, 2019 00:55
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/3aaa3cf32b971b17ca79a96325671b3e to your computer and use it in GitHub Desktop.
Save nabbynz/3aaa3cf32b971b17ca79a96325671b3e to your computer and use it in GitHub Desktop.
TagPro Textures LIVE
// ==UserScript==
// @name Textures LIVE
// @description Apply preset mods to your texture pack to make it look nicee.
// @version 0.0.8
// @include *://tagpro*.koalabeast.com/game
// @include *://tagpro-maptest.koalabeast.com:*
// @updateURL https://gist.github.com/nabbynz/3aaa3cf32b971b17ca79a96325671b3e/raw/Textures_LIVE.user.js
// @downloadURL https://gist.github.com/nabbynz/3aaa3cf32b971b17ca79a96325671b3e/raw/Textures_LIVE.user.js
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_addStyle
// @author nabby
// ==/UserScript==
console.log('START: ' + GM_info.script.name + ' (v' + GM_info.script.version + ' by ' + GM_info.script.author + ')');
//GM_deleteValue('savedOptions');
/************* NOTE: THIS SCRIPT IS ALWAYS IN BETA (SOME THINGS MIGHT BE BROKEN OR CHANGE WITHOUT NOTICE) *************/
tagpro.ready(function() {
let defaultValues = { //you can change the values here if you really want
team_margin_size: 1,
team_opacity: 100,
endzone_margin_size: 1,
endzone_opacity: 100,
gates_margin_size: 1,
gates_opacity: 100,
checkered_size: 40,
checkered_margin: 0,
checkered_random: false,
checkered_opacity: 5,
gradient_color1: 5,
gradient_color2: 5,
gradient_opacity1: 5,
gradient_opacity2: 5,
grids_square_blur: 0,
grids_square_margin: 0,
grids_square_opacity: 25,
grids_square_linewidth: 1,
grids_diagonal_opacity: 15,
gravityWell_linewidth: 50,
gravityWell_color: '#00bb00',
gravityWell_opacity: 40,
gravityWell_gradient: true,
flagline_opacity: 60,
flagline_width: 1,
flagline_dashsize: [8, 10],
centerline_opacity: 60,
centerline_width: 2,
centerline_dashsize: [5, 5],
bumps_floor: { //
//'value-bf1': { url:'https://i.imgur.com/UEdyHac.png', filter:'opacity(10%) saturate(0%)', size:0.75 },
'value-bf2': { url:'https://i.imgur.com/ds4Geee.png', filter:'opacity(30%) saturate(0%)', size:0.25 },
'value-bf3': { url:'https://i.imgur.com/QTcoDNU.png', filter:'opacity(35%) saturate(0%)', size:0.25 }, //circles
'value-bf4': { url:'https://i.imgur.com/dmG3wCE.png', filter:'opacity(16%) saturate(0%)', size:0.5 }, //
'value-bf5': { url:'https://i.imgur.com/r6s6KSQ.png', filter:'opacity(20%) saturate(0%)', size:2 }, //cracks/rock
'value-bf6': { url:'https://i.imgur.com/iVBA4Mh.png', filter:'opacity(35%) saturate(0%)', size:0.75 }, //cracks
'value-bf7': { url:'https://i.imgur.com/HWsz7ws.png', filter:'opacity(25%) saturate(0%)', size:1 }, //rock
'value-bf8': { url:'https://i.imgur.com/7ZYs6Kr.png', filter:'opacity(25%) saturate(30%)', size:1 }, //parquet
'value-bf9': { url:'https://i.imgur.com/nmuo0MA.png', filter:'opacity(25%) saturate(0%)', size:1 }, //moon
'value-bf10': { url:'https://i.imgur.com/yjxCUnM.png', filter:'opacity(70%) saturate(0%)', size:1 }, //small swirls
'value-bf11': { url:'https://i.imgur.com/FzsRS82.png', filter:'opacity(25%) saturate(0%)', size:1 }, //swirls
'value-bf12': { url:'https://i.imgur.com/ESSRqxr.png', filter:'opacity(60%) saturate(100%)', size:1 }, //rainbow
//'value-bf13': { url:'https://i.imgur.com/y0oXbDr.png', filter:'opacity(40%) saturate(100%)', size:1 },
'value-bf14': { url:'https://i.imgur.com/h8ZZBar.png', filter:'opacity(30%) saturate(0%)', size:0.75 }, //hexes 0.75
'value-bf15': { url:'https://i.imgur.com/HX9icFx.png', filter:'opacity(25%) saturate(0%)', size:1 }, //noise
},
bumps_team: { //
'value-bt1': { url:'https://i.imgur.com/4mAoi3N.png', filter:'opacity(20%) saturate(0%)', size:1 },
'value-bt2': { url:'https://i.imgur.com/Svphszd.png', filter:'opacity(20%) saturate(0%)', size:0.25 },
'value-bt4': { url:'https://i.imgur.com/A75wfny.png', filter:'opacity(15%) saturate(0%)', size:1 },
'value-bt5': { url:'https://i.imgur.com/rRzVufi.png', filter:'opacity(25%) saturate(0%)', size:0.5 },
'value-bt6': { url:'https://i.imgur.com/4zC6wuP.png', filter:'opacity(40%) saturate(0%)', size:0.125 },
//'value-bt7': { url:'https://i.imgur.com/2WNFRhl.png', filter:'opacity(40%) saturate(0%)', size:1 },
'value-bt8': { url:'https://i.imgur.com/mv1F2dp.png', filter:'opacity(20%) saturate(0%)', size:0.8 },
'value-bt9': { url:'https://i.imgur.com/d8jbPp1.png', filter:'opacity(40%) saturate(0%)', size:1 },
'value-bt10': { url:'https://i.imgur.com/I0TdkMF.png', filter:'opacity(25%) saturate(0%)', size:1 },
'value-bt11': { url:'https://i.imgur.com/Mt2bZKl.png', filter:'opacity(40%) saturate(0%)', size:1 },
'value-bt12': { url:'https://i.imgur.com/Z5TLBKq.png', filter:'opacity(15%) saturate(0%)', size:1 },
},
bumps_endzone: {
'value-be1': { url:'https://i.imgur.com/5sWY3nV.png', filter:'opacity(25%) saturate(0%)', size:1 },
'value-be2': { url:'https://i.imgur.com/fmCFpbT.png', filter:'opacity(25%) saturate(0%)', size:1 },
//'value-be3': { url:'https://i.imgur.com/K8rqfyH.png', filter:'opacity(60%) saturate(0%)', size:0.4 },
'value-be4': { url:'https://i.imgur.com/3DPyEdr.png', filter:'opacity(25%) saturate(0%)', size:1 },
'value-be5': { url:'https://i.imgur.com/2QgKUaf.png', filter:'opacity(25%) saturate(0%)', size:0.5 },
'value-be6': { url:'https://i.imgur.com/VOqzUP3.png', filter:'opacity(100%) saturate(0%)', size:1 },
'value-be7': { url:'https://i.imgur.com/Eyn93az.png', filter:'opacity(100%) saturate(0%)', size:1 },
'value-be8': { url:'https://i.imgur.com/mMK6rd5.png', filter:'opacity(20%) saturate(0%)', size:1 },
'value-be9': { url:'https://i.imgur.com/kZhBodk.png', filter:'opacity(60%) saturate(0%)', size:1 },
'value-be10': { url:'https://i.imgur.com/Zd0mJK7.png', filter:'opacity(40%) saturate(0%)', size:1 },
'value-be11': { url:'https://i.imgur.com/mSyGafG.png', filter:'opacity(20%) saturate(0%)', size:1 },
'value-be12': { url:'https://i.imgur.com/k0kGc9P.png', filter:'opacity(25%) saturate(0%)', size:0.5 },
'value-be13': { url:'https://i.imgur.com/eQhKaA0.png', filter:'opacity(25%) saturate(0%)', size:1 },
'value-be15': { url:'https://i.imgur.com/py1AYki.png', filter:'opacity(25%) saturate(0%)', size:1 },
'value-be16': { url:'https://i.imgur.com/aTdxbHQ.png', filter:'opacity(25%) saturate(0%)', size:1 },
//'value-be17': { url:'https://i.imgur.com/EhBEV5i.png', filter:'opacity(25%) saturate(0%)', size:1 },
},
bumps_walls: { //
'value-bw1': { url:'https://i.imgur.com/17uQvef.png', filter:'opacity(30%) saturate(0%)', size:1 },
'value-bw2': { url:'https://i.imgur.com/T295R0M.png', filter:'opacity(30%) saturate(0%)', size:0.5 },
'value-bw3': { url:'https://i.imgur.com/7rEw1gi.png', filter:'opacity(40%) saturate(0%)', size:1 },
'value-bw4': { url:'https://i.imgur.com/bUT3z02.png', filter:'opacity(40%) saturate(0%)', size:0.5 },
'value-bw5': { url:'https://i.imgur.com/NfViyHL.png', filter:'opacity(40%) saturate(100%)', size:0.5 },
'value-bw6': { url:'https://i.imgur.com/okIAKS5.png', filter:'opacity(80%) saturate(80%)', size:0.5 },
'value-bw7': { url:'https://i.imgur.com/tdWd8mV.png', filter:'opacity(35%) saturate(0%)', size:0.5 },
'value-bw8': { url:'https://i.imgur.com/QzO4Grd.png', filter:'opacity(25%) saturate(0%)', size:1 },
'value-bw9': { url:'https://i.imgur.com/y0oXbDr.png', filter:'opacity(70%) saturate(100%)', size:1 },
'value-bw10': { url:'https://i.imgur.com/H506yGi.png', filter:'opacity(25%) saturate(0%)', size:0.5 },
'value-bw11': { url:'https://i.imgur.com/ESSRqxr.png', filter:'opacity(100%) saturate(100%)', size:1 }, //colorful
'value-bf12': { url:'https://i.imgur.com/IVMe6tW.png', filter:'opacity(50%) saturate(0%)', size:2 },
'value-bw13': { url:'https://i.imgur.com/dU8e1iL.png', filter:'opacity(100%) saturate(100%)', size:1 }, //From: http://www.grsites.com/generate/category/4/
'value-bw14': { url:'https://i.imgur.com/on2jv1W.png', filter:'opacity(100%) saturate(100%)', size:1 },
'value-bw15': { url:'https://i.imgur.com/el4VKoM.png', filter:'opacity(80%) saturate(80%)', size:1 },
'value-bw16': { url:'https://i.imgur.com/I0TdkMF.png', filter:'opacity(35%) saturate(0%)', size:1 },
'value-bw17': { url:'https://i.imgur.com/P8NQUGr.png', filter:'opacity(80%) saturate(100%)', size:1 },
},
bumps_base: { //base circle images should be red (will be changed to blue/yellow) or greyscale
'value-bc2': { url:'https://i.imgur.com/593TSmM.png', filter:'opacity(40%)', size:1 },
'value-bc4': { url:'https://i.imgur.com/fRggjtO.png', filter:'opacity(25%) blur(2px)', size:1.25 },
'value-bc5': { url:'https://i.imgur.com/6SyICNF.png', filter:'opacity(25%)', size:0.8 },
'value-bc6': { url:'https://i.imgur.com/jzE7u1M.png', filter:'opacity(60%)', size:1 },
'value-bc7': { url:'https://i.imgur.com/QZeByH6.png', filter:'opacity(40%)', size:1 },
'value-bc9': { url:'https://i.imgur.com/lb2gwNR.png', filter:'opacity(20%) saturate(0%)', size:1 },
'value-bcb': { url:'https://i.imgur.com/ZDw7Nsx.png', filter:'opacity(20%)', size:0.6 },
'value-bce': { url:'https://i.imgur.com/zHzOPME.png', filter:'opacity(30%)', size:1 },
},
background: { //add links here to use your own background images (change name to 'value-image4' etc)...
'value-image1': 'https://i.imgur.com/frr4yGb.png',
'value-image2': 'https://i.imgur.com/XVRglCB.png',
'value-image3': 'https://i.imgur.com/ry2JdWR.png',
},
transparent_viewport: true, //set to 'false' to have the black square background
enableExport: true, //used to create presets
showAdvanced: true, //set to 'true' to show all the options
};
let defaultOptions = { //will get updated/overwritten by the script
floor: 'value-normal',
plainfloor: false,
plainteam: false,
plainendzone: false,
floor_brightness: 'value-normal',
team_margin: false,
endzone_margin: false,
gates_margin: false,
grids_square_20: false,
grids_square_40: false,
grids_square_120: false,
grids_rect_80: false,
grids_lines_160: false,
grids_diagonal_40: false,
grids_diagonal_120: false,
grids_maze_1: false,
grids_maze_2: false,
grids_maze_3: false,
grids_maze_4: false,
grids_maze_5: false,
grids_maze_6: false,
grids_maze_7: false,
grids_maze_8: false,
checkered: 'value-none',
floor_gradient: 'value-none',
floor_gradient_color: '#000000',
floor_gradient_bright: false,
wall_gradient: 'value-none',
wall_gradient_color: '#000000',
wall_gradient_bright: false,
teamtile_gradient: false,
teamtile_opacity60: false,
basecircle: false,
basecirclefill: false,
centerline: false,
flagline: false,
elements_floor: false,
plainwalls: false,
plainwalls_color: '#000000',
wallshadow_size: 'value-none',
wallshadow_type: 'value-centered',
wallshadow_color: 'value-black',
wallshadow_inner: false,
wallshadow_outer: false,
wallshadow_bright: false,
walloutline_size: 'value-none',
walloutline_color: 'value-white',
walloutline_dashed: false,
bumps_floor: 'value-none',
bumps_team: 'value-none',
bumps_endzone: 'value-none',
bumps_walls: 'value-none',
bumps_base: 'value-none',
background_color1: '#000000',
background_color2: '#000000',
background_size: '50',
background_useballcolors: false,
background: 'value-none',
brightness: '100',
contrast: '100',
saturation: '100',
kblogo: false,
showmenu: true,
showall: true,
preset: 'value-default',
};
let savedOptions = Object.assign({}, defaultOptions, GM_getValue('savedOptions'));
tagpro.TMIN_ImageCache = {};
var clickTimer = window.performance.now();
//ToDo: Make into Promise
function loadImage(url, callback) {
let img = document.createElement('img');
img.onload = (function(url, callback) {
return function() {
tagpro.TMIN_ImageCache[url] = img;
callback();
};
})(url, callback);
img.crossOrigin = 'Anonymous';
img.src = url;
}
function updateBumpTextures(target, callback) {
let all_targets = ['bumps_floor', 'bumps_team', 'bumps_walls', 'bumps_endzone', 'bumps_base'];
let load_count = target === 'all' ? all_targets.length : 1;
all_targets.forEach(function(value) {
if ((target === 'all' || target === value)) {
if (savedOptions[value] !== 'value-none' && defaultValues[value].hasOwnProperty(savedOptions[value])) {
let url = defaultValues[value][savedOptions[value]].url; //eg: defaultValues.bumps_floor.value-bf1.url
if (tagpro.TMIN_ImageCache[url]) {
if (target === value && callback) callback();
return false;
} else {
loadImage(url, function() {
load_count--;
if (load_count === 0) {
if (callback) callback();
}
});
}
} else {
load_count--;
}
}
});
if (target === 'all' && callback) callback();
}
updateBumpTextures('all');
let colorPickerColors = [
'#000000', '#333333', '#666666', '#999999', '#cccccc', '#ffffff',
'#600000', '#FF0000', '#FF6666', '#663300', '#FF8000', '#FFB266',
'#666600', '#FFFF00', '#FFFF66', '#336600', '#80FF00', '#B2FF66',
'#006600', '#00FF00', '#66FF66', '#006633', '#00FF80', '#66FFB2',
'#006666', '#00FFFF', '#66FFFF', '#003366', '#0080FF', '#66B2FF',
'#000066', '#0000FF', '#6666FF', '#330066', '#7F00FF', '#B266FF',
'#660066', '#FF00FF', '#FF66FF', '#660033', '#FF007F', '#FF66B2',
];
function loadBumpImagesIntoMenu(title, name, saveto, update) {
let string = '<div class="TMIN_InputContainer">';
if (update === 'bumps') {
string += '<span class="TMIN_InputContainerLabel">' + title.slice(0, 1) + ':</span><input type="radio" name="' + name + '" class="TMIN_Input" data-saveto="' + saveto + '" data-savevalue="value-none" data-update="' + update + '" title="No ' + title + '">';
}
Object.keys(defaultValues[saveto]).forEach(key => {
string += '<input type="radio" name="' + name + '" class="TMIN_Input" data-saveto="' + saveto + '" data-savevalue="' + key + '" data-update="' + update + '" title="' + key.slice(6) + '">'; //title + ' #' + count + '">';
});
return string + '</div>';
}
$('body').append('<div id="TMIN_Options" style="position:absolute; top:300px; right:0px; background:rgba(0,0,0,0.5); border-radius:5px; /* padding:3px; min-width:10px; min-height:18px; */"></div>');
$('#TMIN_Options').append('<div id="TMIN_ShowMenu" data-vstatus="shown" style="position:absolute; right:0px; color:chartreuse; font-size:10px; cursor:pointer; margin:3px; width:14px; height:12px; border-radius:5px; background:rgba(0,0,0,0.5); text-align:center;" title="Hide/Show Menu">&#8286;</div>');
$('#TMIN_Options').append('<div id="TMIN_Options_Inner" style="display:none; min-width:160px; margin:3px; text-align:center;"></div></div>');
$('#TMIN_Options_Inner').append('<div class="TMIN_Title">Presets</div>');
$('#TMIN_Options_Inner').append('<div><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-default" data-update="preset" title="Clear All"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-1" data-update="preset" title="Preset #1"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-2" data-update="preset" title="Preset #2"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-3" data-update="preset" title="Preset #3"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-4" data-update="preset" title="Preset #4"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-5" data-update="preset" title="Preset #5"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-6" data-update="preset" title="Preset #6"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-7" data-update="preset" title="Preset #7"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-8" data-update="preset" title="Preset #8"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-9" data-update="preset" title="Preset #9"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-a" data-update="preset" title="Preset #A"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-b" data-update="preset" title="Preset #B"><input type="radio" name="TMIN_PS_Type" class="TMIN_Input" data-saveto="preset" data-savevalue="value-c" data-update="preset" title="Preset #C"></div>');
if (defaultValues.showAdvanced) {
$('#TMIN_Options_Inner').append('<div id="TMIN_ShowAll" class="TMIN_Title" style="margin: 1px 0px 3px; background:rgba(0,0,0,0.5); cursor:pointer;">Advanced</div>');
$('#TMIN_Options_Inner').append('<div id="TMIN_Advanced" style="border:1px dashed #999;"></div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">Background</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="color" class="TMIN_Input" data-saveto="background_color1" data-update="css"><input type="color" class="TMIN_Input" data-saveto="background_color2" data-update="css"><input type="number" class="TMIN_Input" max="100" data-saveto="background_size" data-update="css" title="Only Used for Linear, Corner & Ellipse Gradients"><input type="checkbox" class="TMIN_Input" data-saveto="background_useballcolors" title="Use Ball Colors" data-update="css"></div>');
//$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-none" title="TagPro Default Image" data-update="css"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-linear" title="Horizontal Gradient" data-update="css"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-corner" title="Diagonal Gradient" data-update="css"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-ellipse" title="Ellipse Gradient" data-update="css"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-conic" title="Conic Gradient" data-update="css"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-rainbow" title="Use Rainbow Gradient (RGB)" data-update="css"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-image1" title="Use Imgur Image #1" data-update="css"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-image2" title="Use Imgur Image #2" data-update="css"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-image3" title="Use Imgur Image #3" data-update="css"></div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-none" title="TagPro Default Image" data-update="css"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-linear" title="Horizontal Gradient" data-update="css"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-corner" title="Diagonal Gradient" data-update="css"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-ellipse" title="Ellipse Gradient" data-update="css"><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-conic" title="Conic Gradient" data-update="css"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="radio" name="TMIN_BG_Type" class="TMIN_Input" data-saveto="background" data-savevalue="value-rainbow" title="Use Rainbow Gradient (RGB)" data-update="css">' + loadBumpImagesIntoMenu('Background Images', 'TMIN_BG_Type', 'background', 'css') + '</div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">B/C/S</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="number" class="TMIN_Input" data-saveto="brightness" title="Brightness" data-update="css"><input type="number" class="TMIN_Input" data-saveto="contrast" title="Contrast" data-update="css"><input type="number" class="TMIN_Input" data-saveto="saturation" title="Saturation" data-update="css"></div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">Floor</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="checkbox" class="TMIN_Input" data-saveto="plainfloor" data-update="background" title="Plain Floor"><input type="checkbox" class="TMIN_Input" data-saveto="plainteam" data-update="background" title="Plain Team Tiles"><input type="checkbox" class="TMIN_Input" data-saveto="plainendzone" data-update="background" title="Plain Endzones"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="radio" name="TMIN_Floor_Type" class="TMIN_Input" data-saveto="floor_brightness" data-savevalue="value-d60" data-update="background" title="60% Darker"><input type="radio" name="TMIN_Floor_Type" class="TMIN_Input" data-saveto="floor_brightness" data-savevalue="value-d40" data-update="background" title="40% Darker"><input type="radio" name="TMIN_Floor_Type" class="TMIN_Input" data-saveto="floor_brightness" data-savevalue="value-d20" data-update="background" title="20% Darker"><input type="radio" name="TMIN_Floor_Type" class="TMIN_Input" data-saveto="floor_brightness" data-savevalue="value-d10" data-update="background" title="10% Darker"><input type="radio" name="TMIN_Floor_Type" class="TMIN_Input" data-saveto="floor_brightness" data-savevalue="value-normal" data-update="background" title="Normal"><input type="radio" name="TMIN_Floor_Type" class="TMIN_Input" data-saveto="floor_brightness" data-savevalue="value-l10" data-update="background" title="10% Lighter"><input type="radio" name="TMIN_Floor_Type" class="TMIN_Input" data-saveto="floor_brightness" data-savevalue="value-l20" data-update="background" title="20% Lighter"><input type="radio" name="TMIN_Floor_Type" class="TMIN_Input" data-saveto="floor_brightness" data-savevalue="value-l40" data-update="background" title="40% Lighter"><input type="radio" name="TMIN_Floor_Type" class="TMIN_Input" data-saveto="floor_brightness" data-savevalue="value-l60" data-update="background" title="60% Lighter"></div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">Grids</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="checkbox" class="TMIN_Input" data-saveto="grids_square_20" data-update="background" title="Square Grid 20"><input type="checkbox" class="TMIN_Input" data-saveto="grids_square_40" data-update="background" title="Square Grid 40"><input type="checkbox" class="TMIN_Input" data-saveto="grids_square_120" data-update="background" title="Square Grid 120"><input type="checkbox" class="TMIN_Input" data-saveto="grids_rect_80" data-update="background" title="Rectangle Grid 80"><input type="checkbox" class="TMIN_Input" data-saveto="grids_lines_160" data-update="background" title="Horizontal Lines 160"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="checkbox" class="TMIN_Input" data-saveto="grids_diagonal_40" data-update="background" title="Diagonal Grid 40"><input type="checkbox" class="TMIN_Input" data-saveto="grids_diagonal_120" data-update="background" title="Diagonal Grid 120"></div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">Patterns</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="checkbox" class="TMIN_Input" data-saveto="grids_maze_1" data-update="background" title="10px Random Square Maze"><input type="checkbox" class="TMIN_Input" data-saveto="grids_maze_2" data-update="background" title="40px Random Lines"><input type="checkbox" class="TMIN_Input" data-saveto="grids_maze_3" data-update="background" title="20px Random Angled Maze"><input type="checkbox" class="TMIN_Input" data-saveto="grids_maze_4" data-update="background" title="80px Random Square Maze"><input type="checkbox" class="TMIN_Input" data-saveto="grids_maze_5" data-update="background" title="80px Random Diagonal Maze"><input type="checkbox" class="TMIN_Input" data-saveto="grids_maze_6" data-update="background" title="60px Random Grid"><input type="checkbox" class="TMIN_Input" data-saveto="grids_maze_7" data-update="background" title="60px Random Grid"><input type="checkbox" class="TMIN_Input" data-saveto="grids_maze_8" data-update="background" title="60px Random Grid"></div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">Checkers</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-none" data-update="background" title="No Checker"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkered1" data-update="background" title="20px Checker"><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkered2" data-update="background" title="40px Checker"><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkered5" data-update="background" title="40px Margin Checker"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkered9" data-update="background" title="20px Stripes"><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkereda" data-update="background" title="40px Stripes"><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkeredb" data-update="background" title="120px Stripes"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkered3" data-update="background" title="20px Straight"><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkered4" data-update="background" title="40px Straight"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkered6" data-update="background" title="20px Random Checker"><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkered7" data-update="background" title="40px Random Checker"><input type="radio" class="TMIN_Input" name="TMIN_C_Type" data-saveto="checkered" data-savevalue="value-checkered8" data-update="background" title="40px Random Margin Checker"></div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">Gradients</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="radio" name="TMIN_Floor_Gradient" class="TMIN_Input" data-saveto="floor_gradient" data-savevalue="value-none" data-update="background" title="No Floor Gradient"><input type="radio" name="TMIN_Floor_Gradient" class="TMIN_Input" data-saveto="floor_gradient" data-savevalue="value-gradient1" data-update="background" title="Linear Floor Gradient"><input type="radio" name="TMIN_Floor_Gradient" class="TMIN_Input" data-saveto="floor_gradient" data-savevalue="value-gradient2" data-update="background" title="Radial Floor Gradient"><input type="radio" name="TMIN_Floor_Gradient" class="TMIN_Input" data-saveto="floor_gradient" data-savevalue="value-gradient3" data-update="background" title="Contour Floor Gradient"><button class="TMIN_ChooseColor" data-saveto="floor_gradient_color" title="Floor Gradient Color"></button><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="checkbox" class="TMIN_Input" data-saveto="floor_gradient_bright" data-update="background" title="Use Bright Colors"><span class="TMIN_InputContainerLabel">&nbsp;&nbsp;&nbsp;&nbsp;</span><input type="radio" name="TMIN_Wall_Gradient" class="TMIN_Input" data-saveto="wall_gradient" data-savevalue="value-none" data-update="background" title="No Wall Gradient"><input type="radio" name="TMIN_Wall_Gradient" class="TMIN_Input" data-saveto="wall_gradient" data-savevalue="value-gradient1" data-update="background" title="Diagonal Wall Gradient"><input type="radio" name="TMIN_Wall_Gradient" class="TMIN_Input" data-saveto="wall_gradient" data-savevalue="value-gradient2" data-update="background" title="Radial Wall Gradient"><input type="radio" name="TMIN_Wall_Gradient" class="TMIN_Input" data-saveto="wall_gradient" data-savevalue="value-gradient3" data-update="background" title="Silver Wall Gradient"><input type="radio" name="TMIN_Wall_Gradient" class="TMIN_Input" data-saveto="wall_gradient" data-savevalue="value-gradient4" data-update="background" title="Pattern"><button class="TMIN_ChooseColor" data-saveto="wall_gradient_color" title="Floor Gradient Color"></button><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="checkbox" class="TMIN_Input" data-saveto="wall_gradient_bright" data-update="background" title="Use Bright Colors"></div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">Images</div>');
$('#TMIN_Advanced').append(loadBumpImagesIntoMenu('Floor Bumps', 'TMIN_Bumps_Floor', 'bumps_floor', 'bumps'));
$('#TMIN_Advanced').append(loadBumpImagesIntoMenu('Team Bumps', 'TMIN_Bumps_Team', 'bumps_team', 'bumps'));
$('#TMIN_Advanced').append(loadBumpImagesIntoMenu('Endzone Bumps', 'TMIN_Bumps_Endzone', 'bumps_endzone', 'bumps'));
$('#TMIN_Advanced').append(loadBumpImagesIntoMenu('Wall Bumps', 'TMIN_Bumps_Walls', 'bumps_walls', 'bumps'));
$('#TMIN_Advanced').append(loadBumpImagesIntoMenu('Base Circle Image', 'TMIN_Base_Circle_Image', 'bumps_base', 'bumps'));
$('#TMIN_Advanced').append('<div class="TMIN_Title">Extras</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="checkbox" class="TMIN_Input" data-saveto="basecircle" data-update="background" title="Base Circle"><input type="checkbox" class="TMIN_Input" data-saveto="basecirclefill" data-update="background" title="Base Circle Fill"><input type="checkbox" class="TMIN_Input" data-saveto="centerline" data-update="background" title="Center Line"><input type="checkbox" class="TMIN_Input" data-saveto="flagline" data-update="background" title="Flag Line"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="checkbox" class="TMIN_Input" data-saveto="kblogo" data-update="background" title="Add KoalaBeast"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="checkbox" class="TMIN_Input" data-saveto="teamtile_gradient" data-update="background" title="TeamTile Highlight"><input type="checkbox" class="TMIN_Input" data-saveto="teamtile_opacity60" data-update="background" title="TeamTiles & Endzones @ 60% Opacity"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="checkbox" class="TMIN_Input" data-saveto="elements_floor" data-update="background" title="Draw Circle Under Spikes, Bombs, Boosts etc."></div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">Margins</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="checkbox" class="TMIN_Input" data-saveto="team_margin" data-update="background" title="Team Margin"><input type="checkbox" class="TMIN_Input" data-saveto="endzone_margin" data-update="background" title="Endzone Margin"><input type="checkbox" class="TMIN_Input" data-saveto="gates_margin" data-update="gates" title="Gates Margin"></div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">Wall Shadows</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="radio" class="TMIN_Input" name="TMIN_WS_Size" data-saveto="wallshadow_size" data-savevalue="value-none" data-update="background" title="No Wall Shadow"><input type="radio" class="TMIN_Input" name="TMIN_WS_Size" data-saveto="wallshadow_size" data-savevalue="value-2" data-update="background" title="Small 2px"><input type="radio" name="TMIN_WS_Size" class="TMIN_Input" data-saveto="wallshadow_size" data-savevalue="value-5" data-update="background" title="Medium 5px"><input type="radio" name="TMIN_WS_Size" class="TMIN_Input" data-saveto="wallshadow_size" data-savevalue="value-10" data-update="background" title="Large 10px"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="checkbox" class="TMIN_Input" data-saveto="wallshadow_angled" data-update="background" title="Angled"><span class="TMIN_InputContainerLabel">&nbsp;</span><button class="TMIN_ChooseColor" data-saveto="wallshadow_color" title="Wall Shadow Color"></button><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="checkbox" class="TMIN_Input" data-saveto="wallshadow_inner" data-update="background" title="Inner"><input type="checkbox" class="TMIN_Input" data-saveto="wallshadow_outer" data-update="background" title="Outer"><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="checkbox" class="TMIN_Input" data-saveto="wallshadow_bright" data-update="background" title="Extra Bright"></div>');
$('#TMIN_Advanced').append('<div class="TMIN_Title">Wall Outline</div>');
$('#TMIN_Advanced').append('<div class="TMIN_InputContainer"><input type="radio" name="TMIN_WO_Size" class="TMIN_Input" data-saveto="walloutline_size" data-savevalue="value-none" data-update="background" title="No Wall Outline"><input type="radio" name="TMIN_WO_Size" class="TMIN_Input" data-saveto="walloutline_size" data-savevalue="value-2" data-update="background" title="Wall Outline 1px"><input type="radio" name="TMIN_WO_Size" class="TMIN_Input" data-saveto="walloutline_size" data-savevalue="value-4" data-update="background" title="Wall Outline 2px"><input type="radio" name="TMIN_WO_Size" class="TMIN_Input" data-saveto="walloutline_size" data-savevalue="value-10" data-update="background" title="Wall Outline 10px"><input type="radio" name="TMIN_WO_Size" class="TMIN_Input" data-saveto="walloutline_size" data-savevalue="value-multi" data-update="background" title="Wall Outline Multi"><span class="TMIN_InputContainerLabel">&nbsp;</span><button class="TMIN_ChooseColor" data-saveto="walloutline_color" title="Wall Outline Color"></button><span class="TMIN_InputContainerLabel">&nbsp;</span><input type="checkbox" class="TMIN_Input" data-saveto="walloutline_dashed" data-update="background" title="Dashed"><span class="TMIN_InputContainerLabel">Use Fill:</span><input type="checkbox" class="TMIN_Input" data-saveto="plainwalls" data-update="background" title="Use Plain Walls"><button class="TMIN_ChooseColor" data-saveto="plainwalls_color" title="Plain Walls Color"></button></div>');
$('#TMIN_Advanced').append('<div id="TMIN_ColorPicker" style="position:absolute; display:flex; flex-flow:row wrap; margin:-20px 0 0 0; width:110px; right:10px; background:#222; border:1px dotted white;"></div>'); //bottom:5px; left:5px;
colorPickerColors.forEach(function(value) {
$('#TMIN_ColorPicker').append('<div class="TMIN_Color" data-color="' + value + '"></div>');
});
$('#TMIN_ColorPicker').append('<div id="TMIN_Color_Auto" class="TMIN_Color" data-color="auto" style="background:linear-gradient(#000, #fff);" title="Auto"></div>');
}
$('#TMIN_ColorPicker').hide();
$('.TMIN_Color').each(function(key, value) {
if (this.dataset.color !== 'auto') this.style.background = this.dataset.color;
});
$('#TMIN_ColorPicker').on('click', '.TMIN_Color', function() {
savedOptions[$('#TMIN_ColorPicker').data('saveto')] = this.dataset.color;
GM_setValue('savedOptions', savedOptions);
$('#TMIN_ColorPicker').data('saveto', '');
$('#TMIN_ColorPicker').hide(0);
updateBackground();
});
$('.TMIN_ChooseColor').on('click', function() {
let saveto = this.dataset.saveto;
$(this).after( $('#TMIN_ColorPicker') );
$('#TMIN_ColorPicker').data('saveto', this.dataset.saveto);
$('#TMIN_ColorPicker').fadeIn(100);
$('.TMIN_Color').each(function(key, value) {
if (this.dataset.color === savedOptions[saveto]) this.style.border = '1px dotted #c00;';
else this.style.border = 'none';
});
});
if (defaultValues.enableExport) {
$('#TMIN_Advanced').append('<div><input type="button" id="TMIN_Export" value="Export" title="Export to JSON" style="color:#555; font-size:12px;"></div>');
$('#TMIN_Export').on('click', function() {
let xOptions = {};
$('.TMIN_Input').each(function(index, value) {
if (value.type === 'checkbox') {
xOptions[value.dataset.saveto] = value.checked;
} else if (value.type === 'radio') {
if (value.checked === true) xOptions[value.dataset.saveto] = value.dataset.savevalue;
} else {
xOptions[value.dataset.saveto] = value.value;
}
});
$('.TMIN_ChooseColor').each(function(index, value) {
xOptions[value.dataset.saveto] = savedOptions[value.dataset.saveto];
});
delete xOptions.preset;
console.log(JSON.stringify(xOptions));
});
}
let tr = tagpro.renderer;
let averageTileColors = { floor:'#dddddd', floorAlt:'#444444', floorAlt2:'#888888', redball:'#ff2020', blueball:'#0080ff', /*yellowflag:'#ffff00', redflag:'#ff0000', blueflag:'#0000ff',*/ yellowteam:'#ffff00', redteam:'#ff0000', blueteam:'#0000ff', redendzone:'#ff0000', blueendzone:'#0000ff', wall:'#444444', wallEdge:'#000000' };
let elementPositions = { redflag:[], blueflag:[], yellowflag:[], ezred:{locs:[], x:null, y:null}, ezblue:{locs:[], x:null, y:null}, teamred:[], teamblue:[], teamyellow:[], halfway:{x:null, y:null}, bombs:[], spikes:[], pups:[], boosts:{ yellow:[], red:[], blue:[] }, buttons:[], portals:[], gates:[], gravityWells:[] };
function loadOptions() {
Object.keys(savedOptions).forEach(key => {
if (savedOptions[key] === true || savedOptions[key] === false) $('input.TMIN_Input[data-saveto="' + key + '"]').prop('checked', savedOptions[key]);
else if (savedOptions[key].startsWith('value-')) $('input.TMIN_Input[data-saveto="' + key + '"][data-savevalue="' + savedOptions[key] + '"]').prop('checked', true);
else $('input.TMIN_Input[data-saveto="' + key + '"]').val(savedOptions[key]);
});
if (savedOptions.showmenu) {
$('#TMIN_Options_Inner').show();
} else {
$('#TMIN_Options_Inner').hide();
}
if (savedOptions.showall) {
$('#TMIN_Advanced').show();
} else {
$('#TMIN_Advanced').hide();
}
}
function updateCSS() {
let brightness = savedOptions.brightness === '100' ? '' : ' brightness(' + savedOptions.brightness + '%)';
let contrast = savedOptions.contrast === '100' ? '' : ' contrast(' + savedOptions.contrast + '%)';
let saturation = savedOptions.saturation === '100' ? '' : ' saturate(' + savedOptions.saturation + '%)';
let color1 = (savedOptions.background_useballcolors ? hexToRgbA(averageTileColors.redball, 1.85) : savedOptions.background_color1);
let color2 = (savedOptions.background_useballcolors ? hexToRgbA(averageTileColors.blueball, 1.85) : savedOptions.background_color2);
let size = savedOptions.background_size / 2;
if (savedOptions.background === 'value-conic') {
$('body').css('background', 'conic-gradient(' + color1 + ', ' + color2 + ', ' + color1 + ', ' + color2 + ', ' + color1 + ', ' + color2 + ', ' + color1 + ', ' + color2 + ', ' + color1);
} else if (savedOptions.background === 'value-linear') {
let angle = elementPositions.halfway.x ? 90 : 0;
$('body').css('background', 'linear-gradient(' + angle + 'deg, ' + color1 + ' ' + size + '%, ' + color2 + ' ' + (100 - size) + '%)');
} else if (savedOptions.background === 'value-ellipse') {
$('body').css('background', 'radial-gradient(ellipse, ' + color1 + ', ' + color1 + ', ' + savedOptions.background_size + '%, ' + color2 + ', ' + color2 + ')');
} else if (savedOptions.background === 'value-corner') {
$('body').css('background', 'linear-gradient(to bottom right, ' + color1 + ' ' + size + '%, ' + color2 + ' ' + (100 - size) + '%)');
} else if (savedOptions.background === 'value-rainbow') {
$('body').css('background', 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%), linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%), linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)');
} else if (savedOptions.background.startsWith('value-image')) {
$('body.game-page').css({ 'background':'url("' + defaultValues.background[savedOptions.background] + '")', 'background-size':'cover' });
} else {
$('body').css('background', '');
}
$('#viewport').css('filter', brightness + contrast + saturation);
}
let gate_margin = savedOptions.gates_margin ? 1 : 0;
let gate_width = savedOptions.gates_margin ? 38 : 40;
let gate_opacity = defaultValues.gates_opacity < 100 ? defaultValues.gates_opacity / 100 : 1;
function changePreset(preset) {
Object.assign(savedOptions, defaultOptions);
if (preset === 'value-default') {
//
} else if (preset === 'value-1') {
Object.assign(savedOptions, {"background_color1":"#00ffff","background_color2":"#1e003c","background_size":"50","background_useballcolors":false,"background":"value-ellipse","brightness":"100","contrast":"100","saturation":"100","plainfloor":true,"floor_brightness":"value-normal","grids_square_20":false,"grids_square_40":true,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":false,"grids_maze_2":false,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"checkered":"value-checkered2","floor_gradient":"value-none","floor_gradient_bright":false,"wall_gradient":"value-none","wall_gradient_bright":false,"basecircle":true,"basecirclefill":false,"centerline":true,"flagline":true,"kblogo":false,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":false,"team_margin":true,"endzone_margin":true,"gates_margin":true,"wallshadow_size":"value-2","wallshadow_inner":false,"wallshadow_outer":true,"wallshadow_angled":true,"wallshadow_bright":false,"walloutline_size":"value-2","walloutline_dashed":false,"plainwalls":false,"floor_gradient_color":"#000000","wall_gradient_color":"#000000","wallshadow_color":"#000000","walloutline_color":"auto","plainwalls_color":"#000000"});
} else if (preset === 'value-2') {
Object.assign(savedOptions, {"background_color1":"#c0c0c0","background_color2":"#000000","background_size":"50","background_useballcolors":false,"background":"value-ellipse","brightness":"100","contrast":"100","saturation":"100","plainfloor":true,"floor_brightness":"value-normal","grids_square_20":false,"grids_square_40":false,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":true,"grids_maze_1":false,"grids_maze_2":false,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"checkered":"value-none","floor_gradient":"value-none","floor_gradient_bright":false,"wall_gradient":"value-none","wall_gradient_bright":false,"basecircle":false,"basecirclefill":true,"centerline":false,"flagline":false,"kblogo":false,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":false,"team_margin":false,"endzone_margin":false,"gates_margin":false,"wallshadow_size":"value-5","wallshadow_inner":false,"wallshadow_outer":true,"wallshadow_angled":true,"wallshadow_bright":false,"walloutline_size":"value-2","walloutline_dashed":false,"plainwalls":false,"floor_gradient_color":"#000000","wall_gradient_color":"#000000","wallshadow_color":"#000000","walloutline_color":"auto","plainwalls_color":"#000000"});
} else if (preset === 'value-3') {
Object.assign(savedOptions, {"background_color1":"#00ffff","background_color2":"#ff00ff","background_size":"75","background_useballcolors":true,"background":"value-ellipse","brightness":"100","contrast":"100","saturation":"100","plainfloor":true,"floor_brightness":"value-normal","grids_square_20":false,"grids_square_40":false,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":false,"grids_maze_2":true,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"checkered":"value-none","floor_gradient":"value-none","floor_gradient_bright":false,"wall_gradient":"value-gradient1","wall_gradient_bright":false,"basecircle":true,"basecirclefill":false,"centerline":false,"flagline":true,"kblogo":false,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":false,"team_margin":false,"endzone_margin":false,"gates_margin":false,"wallshadow_size":"value-5","wallshadow_inner":false,"wallshadow_outer":true,"wallshadow_angled":true,"wallshadow_bright":false,"walloutline_size":"value-2","walloutline_dashed":false,"plainwalls":false,"floor_gradient_color":"#000000","wall_gradient_color":"#1d2730","wallshadow_color":"#000000","walloutline_color":"auto","plainwalls_color":"#ffffff"});
} else if (preset === 'value-4') {
Object.assign(savedOptions, {"background_color1":"#ff8000","background_color2":"#0c0017","background_size":"-35","background_useballcolors":false,"background":"value-rainbow","brightness":"100","contrast":"100","saturation":"100","plainfloor":true,"floor_brightness":"value-normal","grids_square_20":false,"grids_square_40":false,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":false,"grids_maze_2":false,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"checkered":"value-checkeredb","floor_gradient":"value-gradient1","floor_gradient_bright":false,"wall_gradient":"value-none","wall_gradient_bright":false,"basecircle":false,"basecirclefill":false,"centerline":false,"flagline":false,"kblogo":false,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":false,"team_margin":true,"endzone_margin":true,"gates_margin":true,"wallshadow_size":"value-5","wallshadow_inner":false,"wallshadow_outer":true,"wallshadow_angled":true,"wallshadow_bright":false,"walloutline_size":"value-2","walloutline_dashed":false,"plainwalls":false,"floor_gradient_color":"#000000","wall_gradient_color":"#000000","wallshadow_color":"#000000","walloutline_color":"auto","plainwalls_color":"#000000"});
} else if (preset === 'value-5') {
Object.assign(savedOptions, {"background_color1":"#000000","background_color2":"#8080ff","background_size":"85","background_useballcolors":false,"background":"value-ellipse","brightness":"100","contrast":"100","saturation":"100","plainfloor":true,"floor_brightness":"value-normal","grids_square_20":false,"grids_square_40":false,"grids_square_120":false,"grids_rect_80":true,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":false,"grids_maze_2":false,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"checkered":"value-checkered8","floor_gradient":"value-none","floor_gradient_bright":false,"wall_gradient":"value-gradient2","wall_gradient_bright":false,"basecircle":true,"basecirclefill":true,"centerline":false,"flagline":false,"kblogo":false,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":false,"team_margin":false,"endzone_margin":false,"gates_margin":false,"wallshadow_size":"value-5","wallshadow_inner":false,"wallshadow_outer":true,"wallshadow_angled":true,"wallshadow_bright":false,"walloutline_size":"value-2","walloutline_dashed":false,"plainwalls":false,"floor_gradient_color":"#000000","wall_gradient_color":"#000000","wallshadow_color":"#000000","walloutline_color":"#ffffff","plainwalls_color":"#000000"});
} else if (preset === 'value-6') {
Object.assign(savedOptions, {"background_color1":"#3a3a45","background_color2":"#0f0f11","background_size":"30","background_useballcolors":false,"background":"value-conic","brightness":"100","contrast":"100","saturation":"100","plainfloor":true,"floor_brightness":"value-l20","grids_square_20":false,"grids_square_40":false,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":true,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":false,"grids_maze_2":false,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"checkered":"value-none","floor_gradient":"value-gradient3","floor_gradient_bright":false,"wall_gradient":"value-gradient1","wall_gradient_bright":false,"basecircle":false,"basecirclefill":false,"centerline":false,"flagline":false,"kblogo":true,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":false,"team_margin":true,"endzone_margin":true,"gates_margin":true,"wallshadow_size":"value-2","wallshadow_angled":true,"wallshadow_inner":false,"wallshadow_outer":true,"wallshadow_bright":false,"walloutline_size":"value-2","walloutline_dashed":false,"plainwalls":false,"floor_gradient_color":"#1C2A39","wall_gradient_color":"#9CAAB9","wallshadow_color":"#000000","walloutline_color":"auto","plainwalls_color":"#1C2A39"});
} else if (preset === 'value-7') {
Object.assign(savedOptions, {"background_color1":"#6f6f6f","background_color2":"#404040","background_size":"83","background_useballcolors":false,"background":"value-image1","brightness":"100","contrast":"100","saturation":"125","plainfloor":true,"plainteam":true,"plainendzone":true,"floor_brightness":"value-d60","grids_square_20":false,"grids_square_40":false,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":false,"grids_maze_2":false,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"grids_maze_6":false,"grids_maze_7":false,"grids_maze_8":false,"checkered":"value-none","floor_gradient":"value-none","floor_gradient_bright":true,"wall_gradient":"value-none","wall_gradient_bright":false,"bumps_floor":"value-none","bumps_team":"value-none","bumps_endzone":"value-none","bumps_walls":"value-none","bumps_base":"value-none","basecircle":false,"basecirclefill":false,"centerline":true,"flagline":true,"kblogo":false,"teamtile_gradient":true,"teamtile_opacity60":true,"elements_floor":false,"team_margin":false,"endzone_margin":false,"gates_margin":false,"wallshadow_size":"value-2","wallshadow_angled":false,"wallshadow_inner":true,"wallshadow_outer":true,"wallshadow_bright":true,"walloutline_size":"value-4","walloutline_dashed":false,"plainwalls":true,"floor_gradient_color":"#000000","wall_gradient_color":"#222f5b","wallshadow_color":"#6514ec","walloutline_color":"#ffffff","plainwalls_color":"#000000"});
} else if (preset === 'value-8') {
Object.assign(savedOptions, {"background_color1":"#6f6f6f","background_color2":"#404040","background_size":"83","background_useballcolors":false,"background":"value-image2","brightness":"100","contrast":"100","saturation":"140","plainfloor":true,"floor_brightness":"value-normal","grids_square_20":false,"grids_square_40":false,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":false,"grids_maze_2":false,"grids_maze_3":true,"grids_maze_4":false,"grids_maze_5":false,"checkered":"value-none","floor_gradient":"value-none","floor_gradient_bright":false,"wall_gradient":"value-none","wall_gradient_bright":false,"basecircle":false,"basecirclefill":false,"centerline":true,"flagline":false,"kblogo":false,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":false,"team_margin":true,"endzone_margin":true,"gates_margin":true,"wallshadow_size":"value-5","wallshadow_inner":true,"wallshadow_outer":true,"wallshadow_angled":false,"wallshadow_bright":false,"walloutline_size":"value-10","walloutline_dashed":false,"plainwalls":true,"floor_gradient_color":"#000000","wall_gradient_color":"#000000","wallshadow_color":"#555555","walloutline_color":"#ffffff","plainwalls_color":"#ffffff"});
} else if (preset === 'value-9') {
Object.assign(savedOptions, {"background_color1":"#ff8000","background_color2":"#0c0017","background_size":"-35","background_useballcolors":false,"background":"value-rainbow","brightness":"100","contrast":"100","saturation":"100","plainfloor":false,"plainteam":false,"plainendzone":true,"floor_brightness":"value-normal","grids_square_20":false,"grids_square_40":false,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":false,"grids_maze_2":false,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"grids_maze_6":false,"grids_maze_7":false,"grids_maze_8":false,"checkered":"value-none","floor_gradient":"value-none","floor_gradient_bright":false,"wall_gradient":"value-none","wall_gradient_bright":false,"bumps_floor":"value-bf2","bumps_team":"value-bt6","bumps_endzone":"value-be4","bumps_walls":"value-bw2","bumps_base":"value-bc7","basecircle":false,"basecirclefill":false,"centerline":false,"flagline":false,"kblogo":false,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":false,"team_margin":true,"endzone_margin":true,"gates_margin":true,"wallshadow_size":"value-10","wallshadow_angled":false,"wallshadow_inner":true,"wallshadow_outer":false,"wallshadow_bright":true,"walloutline_size":"value-multi","walloutline_dashed":true,"plainwalls":false,"floor_gradient_color":"#000000","wall_gradient_color":"#000000","wallshadow_color":"#333333","walloutline_color":"#000000","plainwalls_color":"#000000"});
} else if (preset === 'value-a') {
Object.assign(savedOptions, {"background_color1":"#000000","background_color2":"#c0c0c0","background_size":"52","background_useballcolors":false,"background":"value-conic","brightness":"100","contrast":"100","saturation":"100","plainfloor":true,"plainteam":true,"plainendzone":true,"floor_brightness":"value-d60","grids_square_20":false,"grids_square_40":true,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":false,"grids_maze_2":false,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"grids_maze_6":false,"grids_maze_7":false,"grids_maze_8":false,"checkered":"value-none","floor_gradient":"value-none","floor_gradient_bright":true,"wall_gradient":"value-gradient3","wall_gradient_bright":true,"bumps_floor":"value-bf14","bumps_team":"value-bt10","bumps_endzone":"value-be7","bumps_walls":"value-bw15","bumps_base":"value-bce","basecircle":false,"basecirclefill":false,"centerline":true,"flagline":true,"kblogo":false,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":false,"team_margin":false,"endzone_margin":false,"gates_margin":false,"wallshadow_size":"value-5","wallshadow_angled":false,"wallshadow_inner":true,"wallshadow_outer":false,"wallshadow_bright":false,"walloutline_size":"value-multi","walloutline_dashed":false,"plainwalls":true,"floor_gradient_color":"#1C2A39","wall_gradient_color":"#ffffff","wallshadow_color":"#333333","walloutline_color":"#000000","plainwalls_color":"#999999"});
} else if (preset === 'value-b') {
Object.assign(savedOptions, {"background_color1":"#4f716f","background_color2":"#9fa5b3","background_size":"83","background_useballcolors":false,"background":"value-linear","brightness":"100","contrast":"100","saturation":"120","plainfloor":true,"plainteam":false,"plainendzone":true,"floor_brightness":"value-normal","grids_square_20":false,"grids_square_40":false,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":true,"grids_maze_2":false,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"grids_maze_6":false,"grids_maze_7":false,"grids_maze_8":false,"checkered":"value-none","floor_gradient":"value-gradient1","floor_gradient_bright":false,"wall_gradient":"value-gradient1","wall_gradient_bright":true,"bumps_floor":"value-none","bumps_team":"value-none","bumps_endzone":"value-be10","bumps_walls":"value-bw17","bumps_base":"value-none","basecircle":false,"basecirclefill":false,"centerline":true,"flagline":false,"kblogo":true,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":true,"team_margin":true,"endzone_margin":true,"gates_margin":true,"wallshadow_size":"value-5","wallshadow_angled":true,"wallshadow_inner":true,"wallshadow_outer":false,"wallshadow_bright":false,"walloutline_size":"value-4","walloutline_dashed":false,"plainwalls":false,"floor_gradient_color":"#444444","wall_gradient_color":"#564836","wallshadow_color":"#000000","walloutline_color":"#ffffff","plainwalls_color":"#ffffff"});
} else if (preset === 'value-c') {
Object.assign(savedOptions, {"background_color1":"#00ffff","background_color2":"#1e003c","background_size":"50","background_useballcolors":false,"background":"value-image3","brightness":"100","contrast":"100","saturation":"100","plainfloor":true,"floor_brightness":"value-d60","grids_square_20":false,"grids_square_40":true,"grids_square_120":false,"grids_rect_80":false,"grids_lines_160":false,"grids_diagonal_40":false,"grids_diagonal_120":false,"grids_maze_1":false,"grids_maze_2":false,"grids_maze_3":false,"grids_maze_4":false,"grids_maze_5":false,"checkered":"value-none","floor_gradient":"value-gradient2","floor_gradient_bright":true,"wall_gradient":"value-gradient2","wall_gradient_bright":true,"basecircle":true,"basecirclefill":false,"centerline":true,"flagline":true,"kblogo":false,"teamtile_gradient":true,"teamtile_opacity60":false,"elements_floor":true,"team_margin":true,"endzone_margin":true,"gates_margin":true,"wallshadow_size":"value-5","wallshadow_inner":true,"wallshadow_outer":false,"wallshadow_angled":false,"wallshadow_bright":false,"walloutline_size":"value-2","walloutline_dashed":true,"plainwalls":true,"floor_gradient_color":"#1C2A39","wall_gradient_color":"#102770","wallshadow_color":"#37DBD0","walloutline_color":"#ffffff","plainwalls_color":"#000000"});
} else {
return;
}
savedOptions.preset = preset;
GM_setValue('savedOptions', savedOptions);
loadOptions();
updateViewport();
}
function updateBackground() {
for (let i=0; i<tr.layers.background.children.length; i++) {
tr.layers.background.children[i].destroy(true);
};
tr.backgroundChunks.length = 0;
tr.createBackgroundTexture();
}
function updateGates() {
gate_margin = savedOptions.gates_margin ? 1 : 0;
gate_width = savedOptions.gates_margin ? 38 : 40;
for (let x in tr.dynamicSprites) {
for (let y in tr.dynamicSprites[x]) {
if (tr.dynamicSprites[x][y].hasOwnProperty('isGate')) {
let sprite = tr.dynamicSprites[x][y];
sprite.x = sprite.original_x + gate_margin;
sprite.y = sprite.original_y + gate_margin;
sprite.width = gate_width;
sprite.height = gate_width;
}
}
}
}
function updateViewport() {
updateCSS();
//updateBackground();
updateBumpTextures('all', function() {
updateBackground();
updateGates();
});
}
let doAll = true, doEndzone = false, doTeam = false, doExtras = false, doWalls = false;
let lastClick = Date.now();
document.getElementById('TMIN_Options_Inner').addEventListener('input', function(input) {
let target = input.target;
target.blur();
if (target.className !== 'TMIN_Input') return;
if (target.dataset.update !== 'css' && Date.now() < lastClick + 400) {
e.preventDefault();
target.checked = !target.checked;
return false;
}
lastClick = Date.now();
if (target.type === 'checkbox') {
savedOptions[target.dataset.saveto] = target.checked;
} else if (target.type === 'radio') {
if (target.dataset.savevalue) {
savedOptions[target.dataset.saveto] = target.dataset.savevalue;
} else {
const radioButtons = document.getElementsByName(target.name);
radioButtons.forEach(function(button) {
if (button.checked) savedOptions[button.dataset.saveto] = true;
else savedOptions[button.dataset.saveto] = false;
});
}
} else {
savedOptions[target.dataset.saveto] = target.value;
}
GM_setValue('savedOptions', savedOptions);
clickTimer = window.performance.now();
doAll = doEndzone = doTeam = doExtras = doWalls = false;
//this is so we can skip drawing certain layers if they haven't changed (heaps faster)...
if (['plainteam', 'team_margin', 'teamtile_gradient', 'teamtile_opacity60', 'bumps_team'].indexOf(target.dataset.saveto) >= 0) {
doTeam = true;
} else if (['plainendzone', 'endzone_margin', 'teamtile_opacity60', 'bumps_endzone'].indexOf(target.dataset.saveto) >= 0) {
doEndzone = true;
} else if (['wall_gradient', 'wall_gradient_color', 'wall_gradient_bright', 'plainwalls', 'plainwalls_color', 'bumps_walls', 'wallshadow_size', 'wallshadow_type', 'wallshadow_color', 'wallshadow_inner', 'wallshadow_outer', 'wallshadow_bright', 'walloutline_size', 'walloutline_color', 'walloutline_dashed'].indexOf(target.dataset.saveto) >= 0) {
doWalls = true;
} else if (['checkered', 'basecircle', 'basecirclefill', 'centerline', 'flagline', 'kblogo', 'bumps_base'].indexOf(target.dataset.saveto) >= 0 || target.dataset.saveto.startsWith('grids')) {
doExtras = true;
}
if (target.dataset.update === 'css') {
updateCSS();
} else if (target.dataset.update === 'gates') {
updateGates();
} else if (target.dataset.update === 'background') {
updateBackground();
} else if (target.dataset.update === 'preset') {
doAll = true;
changePreset(target.dataset.savevalue);
} else if (target.dataset.update === 'bumps') {
if (target.dataset.savevalue === 'value-none') {
updateBackground();
} else {
updateBumpTextures(target.dataset.saveto, updateBackground);
}
}
});
$('#TMIN_ShowMenu').on('click', function() {
if (savedOptions.showmenu) {
savedOptions.showmenu = false;
$('#TMIN_Options_Inner').hide();
} else {
savedOptions.showmenu = true;
$('#TMIN_Options_Inner').show();
}
GM_setValue('savedOptions', savedOptions);
});
$('#TMIN_ShowAll').on('click', function() {
if (savedOptions.showall) {
savedOptions.showall = false;
$('#TMIN_Advanced').slideUp();
} else {
savedOptions.showall = true;
$('#TMIN_Advanced').slideDown();
}
GM_setValue('savedOptions', savedOptions);
});
GM_addStyle('.TMIN_Input { color:black; font-size:11px; max-width:40px; margin:0 2px 0 0 !important; }');
GM_addStyle('.TMIN_Title { font-size:10px; margin:5px 0 1px 0; }');
GM_addStyle('.TMIN_InputContainer { display:flex; flex-flow:row wrap; align-items:center; justify-content:center; padding:2px 0 0 0; }');
GM_addStyle('.TMIN_InputContainerLabel { font-size:10px; margin:0 2px 2px 0px; }');
GM_addStyle('.TMIN_Color { width:14px; height:14px; margin:2px; border:1px outset #999; }');
GM_addStyle('.TMIN_ChooseColor { width:12px; height:13px; background:linear-gradient(#a00, #0a0, #00a); border:none; padding:0px; }');
let tilesImage = tagpro.tiles.image;
let tilesCanvas = new OffscreenCanvas(640, 440);
let tilesCtx = tilesCanvas.getContext("2d");
let wallEdgePath, wallEdgePath2, wallEdgePath3;
let makeWallEdgePath = function() {
let margin = 4;
let margin2 = margin * 2.5;
wallEdgePath = new Path2D();
wallEdgePath2 = new Path2D();
wallEdgePath3 = new Path2D();
for (let x=0; x<tagpro.map.length; x++) {
for (let y=0; y<tagpro.map[0].length; y++) {
let mapTileId = Math.floor(tagpro.map[x][y]);
if (mapTileId === 1) {
if (tagpro.map[x][y] === 1) {
if (x === 0 || (x > 0 && (!tagpro.wallMap[x-1][y].some(el => el !== 0) || tagpro.map[x-1][y] === 1.1 || tagpro.map[x-1][y] === 1.2) ) ) { //left edge
wallEdgePath.moveTo(x*40, y*40);
wallEdgePath.lineTo(x*40, y*40+40);
wallEdgePath2.moveTo(x*40, y*40);
wallEdgePath2.lineTo(x*40, y*40+40);
}
if (y === 0 || (y > 0 && (!tagpro.wallMap[x][y-1].some(el => el !== 0) || tagpro.map[x][y-1] === 1.2 || tagpro.map[x][y-1] === 1.3) ) ) { //top edge
wallEdgePath.moveTo(x*40, y*40);
wallEdgePath.lineTo(x*40+40, y*40);
wallEdgePath2.moveTo(x*40, y*40);
wallEdgePath2.lineTo(x*40+40, y*40);
}
if (x === tagpro.map.length-1 || (x < tagpro.map.length-1 && (!tagpro.wallMap[x+1][y].some(el => el !== 0) || tagpro.map[x+1][y] === 1.3 || tagpro.map[x+1][y] === 1.4))) { //right edge
wallEdgePath.moveTo(x*40+40, y*40);
wallEdgePath.lineTo(x*40+40, y*40+40);
wallEdgePath3.moveTo(x*40+40, y*40);
wallEdgePath3.lineTo(x*40+40, y*40+40);
}
if (y === tagpro.map[0].length-1 || (y < tagpro.map[0].length-1 && (!tagpro.wallMap[x][y+1].some(el => el !== 0) || tagpro.map[x][y+1] === 1.1 || tagpro.map[x][y+1] === 1.4))) { //bottom edge
wallEdgePath.moveTo(x*40+40, y*40+40);
wallEdgePath.lineTo(x*40, y*40+40);
wallEdgePath3.moveTo(x*40+40, y*40+40);
wallEdgePath3.lineTo(x*40, y*40+40);
}
} else if (tagpro.map[x][y] === 1.1) { //corner = sw
if (x === 0 || (x > 0 && !tagpro.wallMap[x-1][y].some(el => el !== 0))) { //left edge
wallEdgePath.moveTo(x*40, y*40);
wallEdgePath.lineTo(x*40, y*40+40);
wallEdgePath2.moveTo(x*40, y*40);
wallEdgePath2.lineTo(x*40, y*40+40);
}
if (y === tagpro.map[0].length-1 || (y < tagpro.map[0].length-1 && !tagpro.wallMap[x][y+1].some(el => el !== 0))) { //bottom edge
wallEdgePath.moveTo(x*40, y*40+40);
wallEdgePath.lineTo(x*40+40, y*40+40);
wallEdgePath3.moveTo(x*40, y*40+40);
wallEdgePath3.lineTo(x*40+40, y*40+40);
}
wallEdgePath.moveTo(x*40+40, y*40+40); //diagonal \
wallEdgePath.lineTo(x*40, y*40);
wallEdgePath3.moveTo(x*40+40, y*40+40); //diagonal \
wallEdgePath3.lineTo(x*40, y*40);
} else if (tagpro.map[x][y] === 1.2) { //nw
if (y === 0 || (y > 0 && !tagpro.wallMap[x][y-1].some(el => el !== 0))) { //top edge
wallEdgePath.moveTo(x*40, y*40);
wallEdgePath.lineTo(x*40+40, y*40);
wallEdgePath2.moveTo(x*40, y*40);
wallEdgePath2.lineTo(x*40+40, y*40);
}
wallEdgePath.moveTo(x*40+40, y*40); //diagonal /
wallEdgePath.lineTo(x*40, y*40+40);
wallEdgePath3.moveTo(x*40+40, y*40); //diagonal /
wallEdgePath3.lineTo(x*40, y*40+40);
if (x === 0 || (x > 0 && !tagpro.wallMap[x-1][y].some(el => el !== 0))) { //left edge
wallEdgePath.moveTo(x*40, y*40);
wallEdgePath.lineTo(x*40, y*40+40);
wallEdgePath2.moveTo(x*40, y*40);
wallEdgePath2.lineTo(x*40, y*40+40);
}
} else if (tagpro.map[x][y] === 1.3) { //ne
if (y === 0 || (y > 0 && !tagpro.wallMap[x][y-1].some(el => el !== 0))) { //top edge
wallEdgePath.moveTo(x*40, y*40);
wallEdgePath.lineTo(x*40+40, y*40);
wallEdgePath2.moveTo(x*40, y*40);
wallEdgePath2.lineTo(x*40+40, y*40);
}
if (x === tagpro.map.length-1 || (x < tagpro.map.length-1 && !tagpro.wallMap[x+1][y].some(el => el !== 0))) { //right edge
wallEdgePath.moveTo(x*40+40, y*40);
wallEdgePath.lineTo(x*40+40, y*40+40);
wallEdgePath3.moveTo(x*40+40, y*40);
wallEdgePath3.lineTo(x*40+40, y*40+40);
}
wallEdgePath.moveTo(x*40+40, y*40+40); //diagonal \
wallEdgePath.lineTo(x*40, y*40);
wallEdgePath2.moveTo(x*40+40, y*40+40); //diagonal \
wallEdgePath2.lineTo(x*40, y*40);
} else if (tagpro.map[x][y] === 1.4) { //se
if (x === tagpro.map.length-1 || (x < tagpro.map.length-1 && !tagpro.wallMap[x+1][y].some(el => el !== 0))) { //right edge
wallEdgePath.moveTo(x*40+40, y*40);
wallEdgePath.lineTo(x*40+40, y*40+40);
wallEdgePath3.moveTo(x*40+40, y*40);
wallEdgePath3.lineTo(x*40+40, y*40+40);
}
if (y === tagpro.map[0].length-1 || (y < tagpro.map[0].length-1 && !tagpro.wallMap[x][y+1].some(el => el !== 0))) { //bottom edge
wallEdgePath.moveTo(x*40+40, y*40+40);
wallEdgePath.lineTo(x*40, y*40+40);
wallEdgePath3.moveTo(x*40+40, y*40+40);
wallEdgePath3.lineTo(x*40, y*40+40);
}
wallEdgePath.moveTo(x*40+40, y*40); //diagonal /
wallEdgePath.lineTo(x*40, y*40+40);
wallEdgePath2.moveTo(x*40+40, y*40); //diagonal /
wallEdgePath2.lineTo(x*40, y*40+40);
}
}
}
}
};
let applyBumpTexture = function(ctx, target) { //bumpTexture, target, filter='opacity(25%) saturate(0%)', scale=1) {
if (target && defaultValues[target].hasOwnProperty(savedOptions[target])) {
let url = defaultValues[target][savedOptions[target]].url; //e.g. target = 'bumps_floor'
let image = tagpro.TMIN_ImageCache[url];
if (!image) return;
let scale = defaultValues[target][savedOptions[target]].size;
let width = Math.floor(image.naturalWidth) * scale;
let height = Math.floor(image.naturalHeight) * scale;
if (!image.naturalWidth || !image.naturalHeight) return;
if (!tagpro.TMIN_ImageCache[url + '_canvas']) {
let bumpCanvas = new OffscreenCanvas(width, height);
let bumpCtx = bumpCanvas.getContext("2d");
let filter = defaultValues[target][savedOptions[target]].filter;
bumpCtx.filter = filter;
bumpCtx.drawImage(image, 0, 0, width, height);
tagpro.TMIN_ImageCache[url + '_canvas'] = bumpCanvas;
bumpCanvas = null;
}
ctx.globalCompositeOperation = 'source-atop';
for (let x=0; x<mapWidth; x+=width) {
for (let y=0; y<mapHeight; y+=height) {
ctx.drawImage(tagpro.TMIN_ImageCache[url + '_canvas'], x, y);
}
}
ctx.globalCompositeOperation = 'source-over';
}
};
let floorCanvas;
let mapWidth, mapHeight;
let teamTileCanvas, teamTileCtx;
let endzoneCanvas, endzoneCtx;
let spikeCanvas, spikeCtx;
let wallCanvas, wallCtx;
let extrasCanvas, extrasCtx;
let fwCanvas, fwCtx;
let initBackgroundTexture = function(floorCtx) {
floorCanvas = floorCtx.canvas;
mapWidth = floorCtx.canvas.width;
mapHeight = floorCtx.canvas.height;
teamTileCanvas = new OffscreenCanvas(mapWidth, mapHeight);
teamTileCtx = teamTileCanvas.getContext('2d');
teamTileCtx.imageSmoothingEnabled = false;
endzoneCanvas = new OffscreenCanvas(mapWidth, mapHeight);
endzoneCtx = endzoneCanvas.getContext('2d');
endzoneCtx.imageSmoothingEnabled = false;
spikeCanvas = new OffscreenCanvas(mapWidth, mapHeight);
spikeCtx = spikeCanvas.getContext('2d');
spikeCtx.imageSmoothingEnabled = false;
spikeCtx.doneFirstDraw = false;
wallCanvas = new OffscreenCanvas(mapWidth, mapHeight);
wallCtx = wallCanvas.getContext('2d');
wallCtx.imageSmoothingEnabled = false;
extrasCanvas = new OffscreenCanvas(mapWidth, mapHeight);
extrasCtx = extrasCanvas.getContext('2d');
extrasCtx.imageSmoothingEnabled = false;
fwCanvas = new OffscreenCanvas(mapWidth, mapHeight);
fwCtx = fwCanvas.getContext('2d');
fwCtx.imageSmoothingEnabled = false;
tilesCtx.drawImage(tilesImage, 0, 0);
let pixelData;
pixelData = tilesCtx.getImageData(530, 170, 20, 20).data; //floor
averageTileColors.floor = getAverageColor(pixelData, true);
let floorcolor = tinycolor(averageTileColors.floor);
let floorcolor2 = floorcolor.clone();
let floorcolor_brightness = floorcolor.getBrightness();
averageTileColors.floorAlt = floorcolor_brightness > 30 ? floorcolor.darken(60).toString() : floorcolor.lighten(70).toString();
averageTileColors.floorAlt2 = floorcolor_brightness < 60 ? floorcolor2.lighten(50).toString() : floorcolor2.darken(50).toString();
averageTileColors.floorAlt3 = floorcolor_brightness < 127 ? '#ffffff' : '#000000';
pixelData = tilesCtx.getImageData(565, 5, 30, 30).data; //redball
averageTileColors.redball = getAverageColor(pixelData, true);
pixelData = tilesCtx.getImageData(605, 5, 30, 30).data; //blueball
averageTileColors.blueball = getAverageColor(pixelData, true);
pixelData = tilesCtx.getImageData(530, 210, 20, 20).data; //yellow team
averageTileColors.yellowteam = getAverageColor(pixelData, true);
pixelData = tilesCtx.getImageData(570, 170, 20, 20).data; //red team
averageTileColors.redteam = getAverageColor(pixelData, true);
pixelData = tilesCtx.getImageData(610, 170, 20, 20).data; //blue team
averageTileColors.blueteam = getAverageColor(pixelData, true);
pixelData = tilesCtx.getImageData(570, 210, 20, 20).data; //red endzone
averageTileColors.redendzone = getAverageColor(pixelData, true, true);
averageTileColors.redendzone2 = getAverageColor(pixelData, true, false);
pixelData = tilesCtx.getImageData(610, 210, 20, 20).data; //blue endzone
averageTileColors.blueendzone = getAverageColor(pixelData, true, true);
averageTileColors.blueendzone2 = getAverageColor(pixelData, true, false);
pixelData = tilesCtx.getImageData(490, 10, 20, 20).data; //spike
averageTileColors.spike = getAverageColor(pixelData, true);
pixelData = tilesCtx.getImageData(470, 0, 10, 10).data; //wall
averageTileColors.wall = getAverageColor(pixelData, true);
pixelData = tilesCtx.getImageData(479, 39, 1, 1).data; //wall edge
averageTileColors.wallEdge = getAverageColor(pixelData, true);
let wallcolor = tinycolor(averageTileColors.wallEdge);
let wallcolor2 = wallcolor.clone();
let wallcolor3 = wallcolor.clone();
let wallcolor_brightness = wallcolor.getBrightness();
averageTileColors.floorAlt4 = wallcolor_brightness > 200 ? wallcolor2.darken(40).toString() : (wallcolor_brightness < 60 ? wallcolor2.lighten(50).toString() : wallcolor2.darken(60).toString());
let fw_ave_brightness = (floorcolor_brightness + wallcolor_brightness) / 2;
averageTileColors.floorAlt5 = fw_ave_brightness < 60 ? wallcolor3.lighten(40).toString() : (wallcolor_brightness > 200 ? wallcolor3.darken(40).toString() : wallcolor3.lighten(50).toString());
};
let resetCanvases = function(floorCtx) {
floorCtx.filter = 'none';
teamTileCtx.filter = 'none';
endzoneCtx.filter = 'none';
wallCtx.filter = 'none';
extrasCtx.filter = 'none';
fwCtx.filter = 'none';
floorCtx.globalCompositeOperation = 'source-over';
teamTileCtx.globalCompositeOperation = 'source-over';
endzoneCtx.globalCompositeOperation = 'source-over';
wallCtx.globalCompositeOperation = 'source-over';
extrasCtx.globalCompositeOperation = 'source-over';
fwCtx.globalCompositeOperation = 'source-over';
floorCtx.clearRect(0, 0, mapWidth, mapHeight);
if (doAll || doTeam) teamTileCtx.clearRect(0, 0, mapWidth, mapHeight);
if (doAll || doEndzone) endzoneCtx.clearRect(0, 0, mapWidth, mapHeight);
if (doAll || doWalls) wallCtx.clearRect(0, 0, mapWidth, mapHeight);
if (doAll || doExtras) extrasCtx.clearRect(0, 0, mapWidth, mapHeight);
fwCtx.clearRect(0, 0, mapWidth, mapHeight);
};
let modifyBackgroundTexture = function(floorCtx) {
let team_opacity = savedOptions.teamtile_opacity60 ? 0.6 : defaultValues.team_opacity / 100;
let team_margin_start = savedOptions.team_margin ? defaultValues.team_margin_size : 0;
let team_margin_length = 40 - team_margin_start * 2;
let endzone_opacity = savedOptions.teamtile_opacity60 ? 0.6 : defaultValues.endzone_opacity / 100;
let endzone_margin_start = savedOptions.endzone_margin ? defaultValues.endzone_margin_size : 0;
let endzone_margin_length = 40 - endzone_margin_start * 2;
if (!mapWidth) {
initBackgroundTexture(floorCtx);
} else {
resetCanvases(floorCtx);
}
if (savedOptions.plainfloor) {
let floorcolor2 = tinycolor(averageTileColors.floor);
if (savedOptions.floor_brightness === 'value-d60') {
floorCtx.fillStyle = floorcolor2.darken(100).toString();
} else if (savedOptions.floor_brightness === 'value-d40') {
floorCtx.fillStyle = floorcolor2.darken(60).toString();
} else if (savedOptions.floor_brightness === 'value-d20') {
floorCtx.fillStyle = floorcolor2.darken(40).toString();
} else if (savedOptions.floor_brightness === 'value-d10') {
floorCtx.fillStyle = floorcolor2.darken(20).toString();
} else if (savedOptions.floor_brightness === 'value-normal') {
floorCtx.fillStyle = averageTileColors.floor; //normal
} else if (savedOptions.floor_brightness === 'value-l10') {
floorCtx.fillStyle = floorcolor2.lighten(20).toString();
} else if (savedOptions.floor_brightness === 'value-l20') {
floorCtx.fillStyle = floorcolor2.lighten(40).toString();
} else if (savedOptions.floor_brightness === 'value-l40') {
floorCtx.fillStyle = floorcolor2.lighten(60).toString();
} else if (savedOptions.floor_brightness === 'value-l60') {
floorCtx.fillStyle = floorcolor2.lighten(100).toString();
}
}
if (!savedOptions.plainfloor && savedOptions.floor_brightness !== 'value-normal') {
if (savedOptions.floor_brightness === 'value-d60') {
tilesCtx.filter = 'brightness(10%)';
} else if (savedOptions.floor_brightness === 'value-d40') {
tilesCtx.filter = 'brightness(30%)';
} else if (savedOptions.floor_brightness === 'value-d20') {
tilesCtx.filter = 'brightness(60%)';
} else if (savedOptions.floor_brightness === 'value-d10') {
tilesCtx.filter = 'brightness(80%)';
} else if (savedOptions.floor_brightness === 'value-l10') {
tilesCtx.filter = 'brightness(120%)';
} else if (savedOptions.floor_brightness === 'value-l20') {
tilesCtx.filter = 'brightness(140%)';
} else if (savedOptions.floor_brightness === 'value-l40') {
tilesCtx.filter = 'brightness(160%)';
} else if (savedOptions.floor_brightness === 'value-l60') {
tilesCtx.filter = 'brightness(200%)';
}
tilesCtx.drawImage(tilesImage, 520, 160, 40, 40, 520, 160, 40, 40);
tilesCtx.filter = 'none';
}
//Draw all the tiles...
for (let x=0; x<tagpro.map.length; x++) {
for (let y=0; y<tagpro.map[0].length; y++) {
let mapTileId = Math.floor(tagpro.map[x][y]);
let floorMapTileId = tagpro.floorMap[x][y];
//Draw a floor tile...
if (mapTileId >= 2 || floorMapTileId >= 2) {
if (savedOptions.plainfloor) {
floorCtx.fillRect(x*40, y*40, 40, 40);
} else {
floorCtx.drawImage(tilesCanvas, 520,160,40,40, x*40,y*40,40,40);
}
}
//Draw any floorMap team or endzone tiles (under dynamic sprites & diagonal walls)...
if (floorMapTileId > 2) {
if (floorMapTileId === 11 || floorMapTileId === 12 || floorMapTileId === 23) {
if (doAll || doTeam) {
teamTileCtx.globalAlpha = team_opacity;
if (savedOptions.plainteam) {
teamTileCtx.fillStyle = floorMapTileId === 11 ? averageTileColors.redteam : (floorMapTileId === 12 ? averageTileColors.blueteam : averageTileColors.yellowteam); //'#cc0000' : (floorMapTileId === 12 ? '#0040ff' : '#ffcc00');
teamTileCtx.fillRect(x*40+team_margin_start, y*40+team_margin_start, team_margin_length, team_margin_length);
} else {
teamTileCtx.drawImage(tilesImage, tagpro.tiles[floorMapTileId].x*40, tagpro.tiles[floorMapTileId].y*40, 40, 40, x*40+team_margin_start, y*40+team_margin_start, team_margin_length, team_margin_length);
}
teamTileCtx.globalAlpha = 1;
}
} else if (floorMapTileId === 17 || floorMapTileId === 18) {
if (doAll || doEndzone) {
endzoneCtx.globalAlpha = endzone_opacity;
if (savedOptions.plainendzone) {
endzoneCtx.fillStyle = floorMapTileId === 17 ? averageTileColors.redendzone : averageTileColors.blueendzone; //'#880000' : '#0040aa';
endzoneCtx.fillRect(x*40, y*40, 40, 40);
} else {
endzoneCtx.drawImage(tilesImage, tagpro.tiles[floorMapTileId].x*40, tagpro.tiles[floorMapTileId].y*40, 40, 40, x*40+endzone_margin_start, y*40+endzone_margin_start, endzone_margin_length, endzone_margin_length);
}
endzoneCtx.globalAlpha = 1;
}
}
}
//Draw other map tiles...
if (mapTileId > 2) {
if (mapTileId === 7) { //spike
if (!spikeCtx.doneFirstDraw) spikeCtx.drawImage(tilesImage, tagpro.tiles[mapTileId].x*40, tagpro.tiles[mapTileId].y*40, 40, 40, x*40, y*40, 40, 40);
} else if (mapTileId === 11 || mapTileId === 12 || mapTileId === 23) { //team
if (doAll || doTeam) {
teamTileCtx.globalAlpha = team_opacity;
if (savedOptions.plainteam) {
teamTileCtx.fillStyle = mapTileId === 11 ? averageTileColors.redteam : (mapTileId === 12 ? averageTileColors.blueteam : averageTileColors.yellowteam); //'#cc0000' : (mapTileId === 12 ? '#0040ff' : '#ffcc00');
teamTileCtx.fillRect(x*40+team_margin_start, y*40+team_margin_start, team_margin_length, team_margin_length);
} else {
teamTileCtx.drawImage(tilesImage, tagpro.tiles[mapTileId].x*40, tagpro.tiles[mapTileId].y*40, 40, 40, x*40+team_margin_start, y*40+team_margin_start, team_margin_length, team_margin_length);
}
teamTileCtx.globalAlpha = 1;
}
} else if (mapTileId === 17 || mapTileId === 18) { //endzone
if (doAll || doEndzone) {
endzoneCtx.globalAlpha = endzone_opacity;
if (savedOptions.plainendzone) {
endzoneCtx.fillStyle = mapTileId === 17 ? averageTileColors.redendzone : averageTileColors.blueendzone; //'#880000' : '#0040aa';
endzoneCtx.fillRect(x*40, y*40, 40, 40);
} else {
endzoneCtx.drawImage(tilesImage, tagpro.tiles[mapTileId].x*40, tagpro.tiles[mapTileId].y*40, 40, 40, x*40+endzone_margin_start, y*40+endzone_margin_start, endzone_margin_length, endzone_margin_length);
}
endzoneCtx.globalAlpha = 1;
}
} else if (mapTileId === 8) { //button
if (!spikeCtx.doneFirstDraw) spikeCtx.drawImage(tilesImage, tagpro.tiles[mapTileId].x*40, tagpro.tiles[mapTileId].y*40, 40, 40, x*40, y*40, 40, 40);
} else if (mapTileId === 22) { //gravityWell
if (!spikeCtx.doneFirstDraw) spikeCtx.drawImage(tilesImage, 520, 0, 40, 40, x*40, y*40, 40, 40);
}
}
if (doAll || doWalls) {
if (tagpro.wallMap[x][y].some(el => el !== 0)) {
for (let q=0; q<4; q++) {
let wallTileId = tagpro.wallMap[x][y][q];
if (tagpro.tiles[wallTileId]) {
let xo = 0;
let yo = 0;
if ((q === 1) || (q === 2)) xo = 20;
if ((q === 2) || (q === 3)) yo = 20;
wallCtx.drawImage(tilesImage, tagpro.tiles[wallTileId].x*40, tagpro.tiles[wallTileId].y*40, 20, 20, x*40+xo, y*40+yo, 20, 20);
}
}
}
}
}
}
floorCtx.filter = 'none';
if (doAll || doWalls) {
if (savedOptions.plainwalls) {
wallCtx.globalCompositeOperation = 'source-atop';
wallCtx.fillStyle = savedOptions.plainwalls_color === 'auto' ? averageTileColors.floorAlt4 : savedOptions.plainwalls_color;
wallCtx.fillRect(0, 0, mapWidth, mapHeight);
wallCtx.globalCompositeOperation = 'source-over';
}
}
fwCtx.drawImage(floorCanvas, 0, 0);
fwCtx.drawImage(teamTileCanvas, 0, 0);
fwCtx.drawImage(wallCanvas, 0, 0);
if (savedOptions.bumps_floor !== 'value-none') {
if (defaultValues.bumps_floor.hasOwnProperty(savedOptions.bumps_floor) && defaultValues.bumps_floor[savedOptions.bumps_floor].url) {
applyBumpTexture(floorCtx, 'bumps_floor'); //defaultValues.bumps_floor[savedOptions.bumps_floor].url, savedOptions.bumps_floor, defaultValues.bumps_floor[savedOptions.bumps_floor].filter, defaultValues.bumps_floor[savedOptions.bumps_floor].size);
}
}
//Add Floor Gradient...
if (savedOptions.floor_gradient.startsWith('value-gradient')) {
let color = savedOptions.floor_gradient_color;
let color2 = averageTileColors.floor;
let opacity = 10;
let opacity2 = 50;
if (color === 'auto') color = averageTileColors.floorAlt4;
if (savedOptions.floor_gradient_bright) {
color2 = tinycolor(averageTileColors.floor).darken(10).toHexString()
opacity = 80;
opacity2 = 80;
}
if (savedOptions.floor_gradient === 'value-gradient1') {
addGradient(floorCtx, mapWidth, mapHeight, 'centerline', color2, color , opacity, opacity2, 2);
} else if (savedOptions.floor_gradient === 'value-gradient2') {
addGradient(floorCtx, mapWidth, mapHeight, 'centercircle', color, color2, opacity2, opacity, 4);
} else if (savedOptions.floor_gradient === 'value-gradient3') {
color = hexToRgbA(color, savedOptions.floor_gradient_bright ? 1 : 0.6);
floorCtx.filter = 'drop-shadow(0px 0px 80px ' + color + ') drop-shadow(0px 0px 80px ' + color + ') drop-shadow(0px 0px 80px ' + color + ') drop-shadow(0px 0px 80px ' + color + ')';
floorCtx.drawImage(wallCanvas, 0, 0);
floorCtx.filter = 'none';
}
}
if (doAll || doExtras) {
//Add Checkered...
if (savedOptions.checkered.startsWith('value-checkered')) {
if (savedOptions.checkered === 'value-checkered1') {
addCheckered(extrasCtx, mapWidth, mapHeight, 20, 0, false, false); //size, margin, random, straight
} else if (savedOptions.checkered === 'value-checkered2') {
addCheckered(extrasCtx, mapWidth, mapHeight, 40, 0, false, false);
} else if (savedOptions.checkered === 'value-checkered3') {
addCheckered(extrasCtx, mapWidth, mapHeight, 20, 0, false, true);
} else if (savedOptions.checkered === 'value-checkered4') {
addCheckered(extrasCtx, mapWidth, mapHeight, 40, 0, false, true);
} else if (savedOptions.checkered === 'value-checkered5') {
addCheckered(extrasCtx, mapWidth, mapHeight, 40, 5, false, false);
} else if (savedOptions.checkered === 'value-checkered6') {
addCheckered(extrasCtx, mapWidth, mapHeight, 20, 0, true, false);
} else if (savedOptions.checkered === 'value-checkered7') {
addCheckered(extrasCtx, mapWidth, mapHeight, 40, 0, true, false);
} else if (savedOptions.checkered === 'value-checkered8') {
addCheckered(extrasCtx, mapWidth, mapHeight, 40, 5, true, false);
} else if (savedOptions.checkered === 'value-checkered9') {
addCheckered(extrasCtx, mapWidth, mapHeight, 20, 0, false, false, true);
} else if (savedOptions.checkered === 'value-checkereda') {
addCheckered(extrasCtx, mapWidth, mapHeight, 40, 0, false, false, true);
} else if (savedOptions.checkered === 'value-checkeredb') {
addCheckered(extrasCtx, mapWidth, mapHeight, 120, 0, false, false, true);
}
}
//Add Grids...
if (savedOptions.grids_diagonal_40) addDiagonalGrid(extrasCtx, mapWidth, mapHeight, 40);
if (savedOptions.grids_diagonal_120) addDiagonalGrid(extrasCtx, mapWidth, mapHeight, 120);
if (savedOptions.grids_maze_1) addPatternGrid(extrasCtx, mapWidth, mapHeight, 10, 1, hexToRgbA(averageTileColors.floorAlt2, 0.10), 0, false, 1, 1, 'square'); //size, lineWidth, color, blur, dashsize, max_random, max_length, type
if (savedOptions.grids_maze_2) addPatternGrid(extrasCtx, mapWidth, mapHeight, 40, 1, hexToRgbA(averageTileColors.floorAlt2, 0.15), 1, false, 4, 8, 'square');
if (savedOptions.grids_maze_3) addPatternGrid(extrasCtx, mapWidth, mapHeight, 20, 1, hexToRgbA(averageTileColors.floorAlt2, 0.15), 1, false, 1, 1, 'both');
if (savedOptions.grids_maze_4) addPatternGrid(extrasCtx, mapWidth, mapHeight, 80, 2, hexToRgbA(averageTileColors.floorAlt2, 0.8), 6, false, 1, 1, 'square');
if (savedOptions.grids_maze_5) addPatternGrid(extrasCtx, mapWidth, mapHeight, 120, 80, hexToRgbA(averageTileColors.floorAlt2, 0.2), 2, false, 1, 1, 'diagonal');
if (savedOptions.grids_maze_6) addPatternGrid(extrasCtx, mapWidth, mapHeight, 60, 1, hexToRgbA(averageTileColors.floorAlt2, 0.75), 3, 20, 2, 6, 'square', 'vertical');
if (savedOptions.grids_maze_7) addPatternGrid(extrasCtx, mapWidth, mapHeight, 10, 3, hexToRgbA(averageTileColors.floorAlt2, 0.10), 0, false, 1, 1, 'square', 'vertical');
if (savedOptions.grids_maze_8) addPatternGrid(extrasCtx, mapWidth, mapHeight, 20, 1, hexToRgbA(averageTileColors.floorAlt2, 0.15), 1, false, 4, 8, 'diagonal', 'vertical');
if (savedOptions.grids_square_20) addSquareGrid(extrasCtx, mapWidth, mapHeight, 20, false);
if (savedOptions.grids_square_40) addSquareGrid(extrasCtx, mapWidth, mapHeight, 40, false);
if (savedOptions.grids_square_120) addSquareGrid(extrasCtx, mapWidth, mapHeight, 120, false);
if (savedOptions.grids_rect_80) addSquareGrid(extrasCtx, mapWidth, mapHeight, 80, false, true);
if (savedOptions.grids_lines_160) addSquareGrid(extrasCtx, mapWidth, mapHeight, 160, false, false, true);
//Add KoalaBeast...
if (savedOptions.kblogo) {
let xPos = (elementPositions.halfway.x ? elementPositions.halfway.x : tagpro.map.length * 40 / 2);
let yPos = (elementPositions.halfway.y ? elementPositions.halfway.y : tagpro.map[0].length * 40 / 2);
addKoalaBeast(extrasCtx, xPos, yPos);
}
//Add Gravity Well circle...
if (elementPositions.gravityWells.length) {
let radius = 260;
if (defaultValues.gravityWell_linewidth > 1) radius = 260 + (defaultValues.gravityWell_linewidth / 2);
for (let i=0; i<elementPositions.gravityWells.length; i++) {
drawCircle(extrasCtx, defaultValues.gravityWell_linewidth, radius, defaultValues.gravityWell_color, defaultValues.gravityWell_opacity/100, defaultValues.gravityWell_gradient, 0, 0, elementPositions.gravityWells[i].x+20, elementPositions.gravityWells[i].y+20, false, '');
}
}
//Add Lines...
if (savedOptions.centerline) {
let x1=0, y1=0, x2=0, y2=0;
if (elementPositions.halfway.x) {
x1 = elementPositions.halfway.x + 0;
x2 = elementPositions.halfway.x + 0;
y2 = mapHeight;
} else if (elementPositions.halfway.y) {
x2 = mapWidth;
y1 = elementPositions.halfway.y + 0;
y2 = elementPositions.halfway.y + 0;
}
drawLine(extrasCtx, x1, y1, x2, y2, hexToRgbA(averageTileColors.wallEdge, defaultValues.centerline_opacity / 100), defaultValues.centerline_width, defaultValues.centerline_dashsize);
}
if (savedOptions.flagline) {
if (elementPositions.yellowflag.length) {
//drawLine(extrasCtx, elementPositions.ezred.x + 20, elementPositions.ezred.y + 20, elementPositions.ezblue.x + 20, elementPositions.ezblue.y + 20, '#ff7700', 2, 0);
} else {
for (let i=0; i<elementPositions.redflag.length; i++) {
for (let j=0; j<elementPositions.blueflag.length; j++) {
drawLine(extrasCtx, elementPositions.redflag[i].x + 20, elementPositions.redflag[i].y + 20, elementPositions.blueflag[j].x + 20, elementPositions.blueflag[j].y + 20, hexToRgbA(averageTileColors.wallEdge, defaultValues.flagline_opacity / 100), defaultValues.flagline_width, defaultValues.flagline_dashsize);
}
}
}
}
//Add Base Circles...
if (savedOptions.basecircle || savedOptions.basecirclefill || savedOptions.bumps_base !== 'value-none') {
let ox, oy;
let url = defaultValues.bumps_base.hasOwnProperty(savedOptions.bumps_base) ? defaultValues.bumps_base[savedOptions.bumps_base].url : '';
if (savedOptions.bumps_base !== 'value-none' && tagpro.TMIN_ImageCache[url]) {
ox = tagpro.TMIN_ImageCache[url].naturalWidth * defaultValues.bumps_base[savedOptions.bumps_base].size;
oy = tagpro.TMIN_ImageCache[url].naturalHeight * defaultValues.bumps_base[savedOptions.bumps_base].size;
url = defaultValues.bumps_base[savedOptions.bumps_base].url;
}
//yellow flags...
if (elementPositions.yellowflag.length) {
for (let i=0; i<elementPositions.yellowflag.length; i++) {
if (savedOptions.bumps_base !== 'value-none' && tagpro.TMIN_ImageCache[url]) {
extrasCtx.filter = defaultValues.bumps_base[savedOptions.bumps_base].filter + ' hue-rotate(65deg) saturate(200%)';
extrasCtx.drawImage(tagpro.TMIN_ImageCache[url], elementPositions.yellowflag[i].x + 20 - ox/2, elementPositions.yellowflag[i].y + 20 - oy/2, ox, oy);
extrasCtx.filter = 'none';
}
if (savedOptions.basecirclefill) {
//drawCircle(extrasCtx, 0, 290, '', 0, false, 0, 2, elementPositions.yellowflag[i].x + 20, elementPositions.yellowflag[i].y + 20, savedOptions.basecirclefill, hexToRgbA(averageTileColors.yellowteam, 0.2));
drawCentreCircle(extrasCtx, elementPositions.yellowflag[i].x + 20, elementPositions.yellowflag[i].y + 20, hexToRgbA(averageTileColors.redball, 0.2), hexToRgbA(averageTileColors.blueball, 0.2));
}
if (savedOptions.basecircle) {
drawCircle(extrasCtx, 12, 300, averageTileColors.yellowteam, 0.75, false, 0, 2, elementPositions.yellowflag[i].x + 20, elementPositions.yellowflag[i].y + 20);
}
}
}
//red flags...
if (elementPositions.redflag.length) {
for (let i=0; i<elementPositions.redflag.length; i++) {
if (savedOptions.bumps_base !== 'value-none' && tagpro.TMIN_ImageCache[url]) {
extrasCtx.filter = defaultValues.bumps_base[savedOptions.bumps_base].filter + '';
extrasCtx.drawImage(tagpro.TMIN_ImageCache[url], elementPositions.redflag[i].x + 20 - ox/2, elementPositions.redflag[i].y + 20 - oy/2, ox, oy);
extrasCtx.filter = 'none';
}
if (savedOptions.basecirclefill) {
drawCircle(extrasCtx, 0, 290, '', 0, false, 0, 2, elementPositions.redflag[i].x + 20, elementPositions.redflag[i].y + 20, savedOptions.basecirclefill, hexToRgbA(averageTileColors.redball, 0.1));
}
if (savedOptions.basecircle) {
drawCircle(extrasCtx, 12, 300, averageTileColors.redball, 0.5, false, 0, 2, elementPositions.redflag[i].x + 20, elementPositions.redflag[i].y + 20);
}
}
}
//blue flags...
if (elementPositions.blueflag.length) {
for (let i=0; i<elementPositions.blueflag.length; i++) {
if (savedOptions.bumps_base !== 'value-none' && tagpro.TMIN_ImageCache[url]) {
extrasCtx.filter = defaultValues.bumps_base[savedOptions.bumps_base].filter + ' hue-rotate(240deg)';
extrasCtx.drawImage(tagpro.TMIN_ImageCache[url], elementPositions.blueflag[i].x + 20 - ox/2, elementPositions.blueflag[i].y + 20 - oy/2, ox, oy);
extrasCtx.filter = 'none';
}
if (savedOptions.basecirclefill) {
drawCircle(extrasCtx, 0, 290, '', 0, false, 0, 2, elementPositions.blueflag[i].x + 20, elementPositions.blueflag[i].y + 20, savedOptions.basecirclefill, hexToRgbA(averageTileColors.blueball, 0.1));
}
if (savedOptions.basecircle) {
drawCircle(extrasCtx, 12, 300, averageTileColors.blueball, 0.5, false, 0, 2, elementPositions.blueflag[i].x + 20, elementPositions.blueflag[i].y + 20);
}
}
}
}
}
//Draw the "extras" layer...
floorCtx.filter = 'none';
floorCtx.globalCompositeOperation = 'source-atop';
floorCtx.drawImage(extrasCanvas, 0, 0);
floorCtx.globalCompositeOperation = 'source-over';
if (savedOptions.elements_floor) {
let c1Canvas = new OffscreenCanvas(40, 40);
let c1Ctx = c1Canvas.getContext("2d");
let c2Canvas = new OffscreenCanvas(40, 40);
let c2Ctx = c2Canvas.getContext("2d");
drawCircle(c1Ctx, 0, 17, averageTileColors.floorAlt, 1, false, 0, 2, 20, 20, true, averageTileColors.floor);
for (let i=0; i<elementPositions.bombs.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.bombs[i].x, elementPositions.bombs[i].y);
}
for (let i=0; i<elementPositions.pups.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.pups[i].x, elementPositions.pups[i].y);
}
c1Ctx.clearRect(0,0,40,40);
drawCircle(c1Ctx, 0, 15, averageTileColors.floorAlt, 1, false, 0, 2, 20, 20, true, averageTileColors.floor);
for (let i=0; i<elementPositions.spikes.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.spikes[i].x, elementPositions.spikes[i].y);
}
c1Ctx.clearRect(0,0,40,40);
drawCircle(c1Ctx, 0, 9, averageTileColors.floorAlt, 1, false, 0, 2, 20, 20, true, averageTileColors.floor);
for (let i=0; i<elementPositions.buttons.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.buttons[i].x, elementPositions.buttons[i].y);
}
c1Ctx.clearRect(0,0,40,40);
drawCircle(c1Ctx, 0, 16, averageTileColors.floorAlt, 1, false, 0, 2, 20, 20, true, averageTileColors.floor);
for (let i=0; i<elementPositions.portals.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.portals[i].x, elementPositions.portals[i].y);
}
for (let i=0; i<elementPositions.boosts.red.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.boosts.red[i].x, elementPositions.boosts.red[i].y);
}
for (let i=0; i<elementPositions.boosts.blue.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.boosts.blue[i].x, elementPositions.boosts.blue[i].y);
}
for (let i=0; i<elementPositions.boosts.yellow.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.boosts.yellow[i].x, elementPositions.boosts.yellow[i].y);
}
drawCircle(c2Ctx, 2, 15, averageTileColors.floorAlt, 1, false, 4, 0, 20, 20);
for (let i=0; i<elementPositions.redflag.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.redflag[i].x, elementPositions.redflag[i].y);
floorCtx.drawImage(c2Canvas, elementPositions.redflag[i].x, elementPositions.redflag[i].y);
}
for (let i=0; i<elementPositions.blueflag.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.blueflag[i].x, elementPositions.blueflag[i].y);
floorCtx.drawImage(c2Canvas, elementPositions.blueflag[i].x, elementPositions.blueflag[i].y);
}
for (let i=0; i<elementPositions.yellowflag.length; i++) {
floorCtx.drawImage(c1Canvas, elementPositions.yellowflag[i].x, elementPositions.yellowflag[i].y);
floorCtx.drawImage(c2Canvas, elementPositions.yellowflag[i].x, elementPositions.yellowflag[i].y);
}
c1Canvas = null;
c2Canvas = null;
}
//Draw the team tiles...
if (doAll || doTeam) {
if (savedOptions.teamtile_gradient) {
addGradientLines(teamTileCtx, mapWidth, mapHeight, 'rdiagonal', 'diagonal', '#222222', '#dddddd', 25, 25, Math.max(mapWidth, mapHeight) / 30, Math.max(mapWidth, mapHeight) / 30);
}
if (savedOptions.bumps_team !== 'value-none') {
if (defaultValues.bumps_team.hasOwnProperty(savedOptions.bumps_team) && defaultValues.bumps_team[savedOptions.bumps_team].url) {
applyBumpTexture(teamTileCtx, 'bumps_team');
}
}
}
floorCtx.drawImage(teamTileCanvas, 0, 0);
//Draw the endzones...
if (doAll || doEndzone) {
if (savedOptions.bumps_endzone !== 'value-none') {
if (defaultValues.bumps_endzone.hasOwnProperty(savedOptions.bumps_endzone) && defaultValues.bumps_endzone[savedOptions.bumps_endzone].url) {
applyBumpTexture(endzoneCtx, 'bumps_endzone');
}
}
}
floorCtx.drawImage(endzoneCanvas, 0, 0);
//Draw the spikes (includes: buttons & gravitywells)...
floorCtx.drawImage(spikeCanvas, 0, 0);
spikeCtx.doneFirstDraw = true;
//Add Wall Gradient...
if (doAll || doWalls) {
if (savedOptions.bumps_walls !== 'value-none') {
if (defaultValues.bumps_walls.hasOwnProperty(savedOptions.bumps_walls) && defaultValues.bumps_walls[savedOptions.bumps_walls].url) {
applyBumpTexture(wallCtx, 'bumps_walls');
}
}
if (savedOptions.wall_gradient.startsWith('value-gradient')) {
let color = savedOptions.wall_gradient_color;
let color2 = averageTileColors.wall;
let opacity = 10; //30,40
let opacity2 = 50;
if (color === 'auto') color = averageTileColors.floorAlt5;
if (savedOptions.wall_gradient_bright) {
color2 = tinycolor(averageTileColors.floorAlt5).darken(10).toHexString()
opacity = 80;
opacity2 = 80;
}
if (savedOptions.plainwalls) {
color2 = savedOptions.plainwalls_color === 'auto' ? averageTileColors.floorAlt4 : savedOptions.plainwalls_color;
}
if (savedOptions.wall_gradient === 'value-gradient1') {
addGradient(wallCtx, mapWidth, mapHeight, 'rdiagonal', color, color2, opacity, opacity2, Math.max(mapWidth, mapHeight) / 40);
} else if (savedOptions.wall_gradient === 'value-gradient2') {
addGradient(wallCtx, mapWidth, mapHeight, 'centercircle', color, color2, opacity, opacity2, 12);
} else if (savedOptions.wall_gradient === 'value-gradient3') {
addGradientLines(wallCtx, mapWidth, mapHeight, 'rdiagonal', 'diagonal', '#222222', '#dddddd', opacity, opacity2, Math.max(mapWidth, mapHeight) / 60, Math.max(mapWidth, mapHeight) / 60);
} else if (savedOptions.wall_gradient === 'value-gradient4') {
let color = savedOptions.wall_gradient_color === 'auto' ? averageTileColors.floorAlt : savedOptions.wall_gradient_color;
let opacity = savedOptions.wall_gradient_bright ? 0.95 : 0.5;
if (!wallEdgePath) makeWallEdgePath();
wallCtx.globalCompositeOperation = 'source-atop';
wallCtx.lineWidth = 2;
wallCtx.fillStyle = hexToRgbA(color, opacity);
wallCtx.fill(wallEdgePath3);
wallCtx.filter = 'none';
wallCtx.globalCompositeOperation = 'source-over';
} else if (savedOptions.wall_gradient === 'value-gradient5') {
let wallCanvas2 = new OffscreenCanvas(mapWidth, mapHeight); //floorCanvas.cloneNode(false);
let wallCtx2 = wallCanvas2.getContext('2d');
let wallEdgeCanvas2 = new OffscreenCanvas(mapWidth, mapHeight); //floorCanvas.cloneNode(false);
let wallEdgeCtx2 = wallEdgeCanvas2.getContext('2d');
let wallshadow_color = savedOptions.wall_gradient_color === 'auto' ? averageTileColors.floorAlt : savedOptions.wall_gradient_color;
let wallshadow_opacity = savedOptions.wall_gradient_bright ? 1 : 0.5;
if (!wallEdgePath) makeWallEdgePath();
wallCtx2.drawImage(wallCanvas, 0, 0); //the lines on wallEdgeCanvas are too thick so we use this to "clip" them inside the original walls
wallEdgeCtx2.lineWidth = 2;
wallEdgeCtx2.lineCap = 'round';
wallEdgeCtx2.strokeStyle = hexToRgbA(wallshadow_color, wallshadow_opacity);
wallEdgeCtx2.stroke(wallEdgePath2);
wallCtx2.drawImage(wallEdgeCanvas2, 0, 0);
wallCtx.globalCompositeOperation = 'source-atop';
wallCtx.drawImage(wallCanvas2, 0, 0);
wallCtx.globalCompositeOperation = 'source-over';
}
}
//Add the Wall Shadows and/or Wall Outline...
if ((savedOptions.wallshadow_size !== 'value-none' && (savedOptions.wallshadow_inner || savedOptions.wallshadow_outer)) || savedOptions.walloutline_size !== 'value-none') {
let wallCanvas2 = new OffscreenCanvas(mapWidth, mapHeight); //floorCanvas.cloneNode(false);
let wallCtx2 = wallCanvas2.getContext('2d');
let wallEdgeCanvas2 = new OffscreenCanvas(mapWidth, mapHeight); //floorCanvas.cloneNode(false);
let wallEdgeCtx2 = wallEdgeCanvas2.getContext('2d');
if (!wallEdgePath) makeWallEdgePath();
wallCtx2.drawImage(wallCanvas, 0, 0); //the lines on wallEdgeCanvas are too thick so we use this to "clip" them inside the original walls
//Wall Shadow...
if (savedOptions.wallshadow_size !== 'value-none' && (savedOptions.wallshadow_inner || savedOptions.wallshadow_outer)) {
let wallshadow_outline = savedOptions.walloutline_size === 'value-2' ? 2 : savedOptions.walloutline_size === 'value-4' ? 4 : 10;
let wallshadow_type = savedOptions.wallshadow_angled ? '1px 1px' : '0px 0px';
let wallshadow_blur = savedOptions.wallshadow_angled ? '1px' : '2px';
let wallshadow_opacity = savedOptions.wallshadow_angled ? 0.5 : 0.6;
let wallshadow_color = savedOptions.wallshadow_color === 'auto' ? averageTileColors.floorAlt : savedOptions.wallshadow_color;
wallEdgeCtx2.lineWidth = savedOptions.walloutline_size === 'value-none' ? 1 : wallshadow_outline;
wallEdgeCtx2.strokeStyle = wallshadow_color; //hexToRgbA(wallshadow_color, wallshadow_opacity);
wallEdgeCtx2.lineCap = 'round';
wallEdgeCtx2.drawImage(wallCanvas2, 0, 0);
wallEdgeCtx2.globalCompositeOperation = 'source-in';
wallEdgeCtx2.stroke(wallEdgePath);
if (savedOptions.wallshadow_size === 'value-5') {
wallshadow_type = savedOptions.wallshadow_angled ? '2px 2px' : '0px 0px';
wallshadow_blur = savedOptions.wallshadow_angled ? '2px' : '3px';
} else if (savedOptions.wallshadow_size === 'value-10') {
wallshadow_type = savedOptions.wallshadow_angled ? '3px 3px' : '0px 0px';
wallshadow_blur = savedOptions.wallshadow_angled ? '3px' : '4px';
}
let wallshadow_color_opacity = hexToRgbA(wallshadow_color, wallshadow_opacity);
let wallshadow = 'drop-shadow(' + wallshadow_type + ' ' + wallshadow_blur + ' ' + wallshadow_color_opacity + ') ';
wallCtx.filter = wallshadow + wallshadow + wallshadow + wallshadow;
if (savedOptions.wallshadow_bright) {
if (savedOptions.walloutline_size === 'value-2') wallCtx.filter += wallshadow;
else if (savedOptions.walloutline_size === 'value-4') wallCtx.filter += ' drop-shadow(0px 0px 2px ' + hexToRgbA(wallshadow_color, 0.9) + ')';
else if (savedOptions.walloutline_size === 'value-10') wallCtx.filter += ' drop-shadow(0px 0px 4px ' + hexToRgbA(wallshadow_color, 1) + ')';
else wallCtx.filter += wallshadow;
}
if (savedOptions.wallshadow_inner) {
wallCtx.globalCompositeOperation = 'source-atop';
wallCtx.drawImage(wallEdgeCanvas2, 0, 0);
}
if (savedOptions.wallshadow_outer) {
wallCtx.globalCompositeOperation = 'destination-over';
wallCtx.drawImage(wallEdgeCanvas2, 0, 0);
}
wallCtx.globalCompositeOperation = 'source-over';
wallCtx.filter = 'none';
}
//Wall Outline...
if (savedOptions.walloutline_size !== 'value-none') {
if (savedOptions.walloutline_size === 'value-2') {
wallEdgeCtx2.lineWidth = 2;
} else if (savedOptions.walloutline_size === 'value-4') {
wallEdgeCtx2.lineWidth = 4;
} else if (savedOptions.walloutline_size === 'value-10') {
wallEdgeCtx2.lineWidth = 10;
} else if (savedOptions.walloutline_size === 'value-multi') {
wallEdgeCtx2.lineWidth = 8;
}
if (savedOptions.walloutline_color.startsWith('#')) {
wallEdgeCtx2.strokeStyle = savedOptions.walloutline_color;
} else {
wallEdgeCtx2.strokeStyle = averageTileColors.floorAlt5;
}
if (savedOptions.walloutline_dashed) {
wallEdgeCtx2.lineCap = 'butt';
if (savedOptions.walloutline_size === 'value-2') {
wallEdgeCtx2.setLineDash([2, 2]);
} else if (savedOptions.walloutline_size === 'value-4') {
wallEdgeCtx2.setLineDash([4, 4]);
} else if (savedOptions.walloutline_size === 'value-10') {
wallEdgeCtx2.setLineDash([8, 4]);
} else if (savedOptions.walloutline_size === 'value-multi') {
wallEdgeCtx2.lineCap = 'round';
//wallEdgeCtx2.setLineDash([4, 8]);
}
} else {
wallEdgeCtx2.lineCap = 'round';
}
wallEdgeCtx2.clearRect(0, 0, wallEdgeCanvas2.width, wallEdgeCanvas2.height);
wallEdgeCtx2.globalCompositeOperation = 'source-over';
wallEdgeCtx2.drawImage(wallCanvas2, 0, 0);
wallEdgeCtx2.globalCompositeOperation = 'source-in';
wallEdgeCtx2.stroke(wallEdgePath);
wallCtx.drawImage(wallEdgeCanvas2, 0, 0);
if (savedOptions.walloutline_size === 'value-multi') {
wallEdgeCtx2.lineCap = 'round';
wallEdgeCtx2.setLineDash([]);
wallEdgeCtx2.strokeStyle = averageTileColors.floorAlt3;
wallEdgeCtx2.lineWidth = 10;
wallEdgeCtx2.stroke(wallEdgePath);
wallCtx.drawImage(wallEdgeCanvas2, 0, 0);
if (savedOptions.walloutline_dashed) {
wallEdgeCtx2.lineCap = 'butt';
wallEdgeCtx2.setLineDash([4, 4]);
//wallEdgeCtx2.filter = 'blur(1px)';
}
wallEdgeCtx2.strokeStyle = savedOptions.walloutline_color === 'auto' ? averageTileColors.floor : savedOptions.walloutline_color;
wallEdgeCtx2.lineWidth = 8;
wallEdgeCtx2.stroke(wallEdgePath);
wallCtx.drawImage(wallEdgeCanvas2, 0, 0);
if (savedOptions.walloutline_dashed) {
wallEdgeCtx2.filter = 'none';
wallEdgeCtx2.lineCap = 'round';
wallEdgeCtx2.setLineDash([]);
}
wallEdgeCtx2.strokeStyle = averageTileColors.floorAlt3;
wallEdgeCtx2.lineWidth = 2;
wallEdgeCtx2.stroke(wallEdgePath);
wallCtx.drawImage(wallEdgeCanvas2, 0, 0);
}
}
wallCanvas2 = null;
wallEdgeCanvas2 = null;
}
}
//Draw the walls...
floorCtx.drawImage(wallCanvas, 0, 0);
//remove any wall shadows that were drawn *outside* the map
floorCtx.globalCompositeOperation = 'destination-in';
floorCtx.drawImage(fwCanvas, 0, 0);
floorCtx.globalCompositeOperation = 'source-over';
};
tr.chunkifyBackground = function (renderTexture) {
tr.backgroundChunks = [];
let baseTexture = renderTexture.baseTexture;
let width = tagpro.map.length * 40;
let height = tagpro.map[0].length * 40;
let chunkSize = 4096; //512 or 1024 (default) or 2048 or 4096
if (tr.renderer.gl) {
let maxSize = tr.renderer.gl.getParameter(tr.renderer.gl.MAX_TEXTURE_SIZE);
if (chunkSize > maxSize) {
chunkSize = Math.pow(2, Math.round(Math.log(maxSize / 2) / Math.log(2)));
console.log("Chunk size was too large. Reducing to closest power of two below gl.MAX_TEXTURE_SIZE, which is " + chunkSize);
}
}
tr.layers.background.removeChildren();
for (let x = 0; x < width; x += chunkSize) {
for (let y = 0; y < height; y += chunkSize) {
let w = x + chunkSize > width ? width - x : chunkSize;
let h = y + chunkSize > height ? height - y : chunkSize;
let newCanvas = new OffscreenCanvas(chunkSize, chunkSize);
let ctx = newCanvas.getContext("2d");
ctx.drawImage(baseTexture.source, x, y, w, h, 0, 0, w, h);
let newTexture = PIXI.Texture.fromCanvas(newCanvas);
let sprite = new PIXI.Sprite(newTexture);
sprite.x = x;
sprite.y = y;
sprite.cacheAsBitmap = true;
tr.layers.background.addChild(sprite);
newCanvas = null;
}
}
};
//Re-draw the background before it gets chunkified...
tr.createBackgroundTexture = function(container) {
let width = tagpro.map.length * 40;
let height = tagpro.map[0].length * 40;
let floorCanvas = new OffscreenCanvas(width, height);
let floorCtx = floorCanvas.getContext('2d');
floorCtx.imageSmoothingEnabled = false;
modifyBackgroundTexture(floorCtx);
//Chunkify the new background...
let newTexture = PIXI.Texture.fromCanvas(floorCanvas);
tr.chunkifyBackground(newTexture);
newTexture.destroy(true);
newTexture = null;
floorCanvas = null;
};
tr.drawBackgroundTiles = function(container) {
let drawPos = {x: 0, y: 0};
for (let x = 0, xl = tagpro.map.length; x !== xl; x++) {
for (let y = 0, yl = tagpro.map[0].length; y !== yl; y++) {
if (tagpro.map[x][y] === 22) {
drawPos.x = x * 40;
drawPos.y = y * 40;
tr.createGravityWellEmitter(drawPos.x + (20), drawPos.y + (20));
tagpro.world.createGravityWell(x * 0.4, y * 0.4);
}
}
}
tr.afterDrawBackground();
};
let skipTileIds = [7, 8, 17, 18, 22];
let gateTileIds = [9, 9.1, 9.2, 9.3];
tagpro.skipTileIds = skipTileIds; //this is so a different script can check if we're doing this
tr.drawDynamicTile = function(x, y, tileId) {
tileId = tileId || tagpro.map[x][y];
let tile = tagpro.tiles[tileId];
if (!tile || tileId <= 2) {
return;
}
if (skipTileIds.indexOf(tileId) >= 0) return;
if (!tr.dynamicSprites[x]) tr.dynamicSprites[x] = {};
let drawPos = { x:x * 40, y:y * 40 };
let sprite;
if (tile instanceof PIXI.extras.AnimatedSprite || tile.frameTiles) { //boosts/portals
sprite = tr.drawAnimation(tile, drawPos);
} else if (tile.dynamic) { //bombs/gates/flags/pups
sprite = tagpro.tiles.draw(tr.layers.midground, tileId, drawPos);
if (gateTileIds.indexOf(tileId) >= 0) {
if (!sprite.isGate) {
sprite.isGate= true;
sprite.original_x = sprite.x;
sprite.original_y = sprite.y;
}
sprite.x = sprite.position.x + gate_margin;
sprite.y = sprite.position.y + gate_margin;
sprite.width = gate_width;
sprite.height = gate_width;
sprite.alpha = gate_opacity;
}
} else {
return;
}
tr.dynamicSprites[x][y] = sprite;
};
tr.updateDynamicTile = function(update) {
/* Updates a given dynamic tile from the server. There is a bug here involving array indexing. */
let prevMapTile = tagpro.map[update.x][update.y];
if (!tr.dynamicSprites[update.x] && !tr.layers.backgroundDrawn) {
//console.log('!BGDRAWN x,y:', update.x, update.y + ' |prev:',prevMapTile + ' |this:', update.v + ' |bgDrawn:',tr.layers.backgroundDrawn)
$('#exit').css('color', 'red');
rafTimeout(tr.updateDynamicTile, 200, update);
return false;
}
tagpro.map[update.x][update.y] = update.v;
if (tr.dynamicSprites[update.x]) {
//console.log('REMOVING x,y:', update.x, update.y + ' |prev:',prevMapTile + ' |this:', update.v + ' |bgDrawn:',tr.layers.backgroundDrawn)
tr.layers.midground.removeChild(tr.dynamicSprites[update.x][update.y]);
} else {
//console.log('BUG HERE x,y:', update.x, update.y + ' |prev:',prevMapTile + ' |this:',update.v + ' |bgDrawn:',tr.layers.backgroundDrawn)
//alert('There is a bug here involving array indexing.');
}
tr.drawDynamicTile(update.x, update.y);
};
tagpro.socket.on("mapupdate", function(data) {
if (!Array.isArray(data)) data = [data];
for (let i = 0; i < data.length; i++) {
//if (data[i].x) console.log('mapupdate ' + i + ': ' + data[i].x, data[i].y, data[i].v);
//else console.log('mapupdate (undefined data.x)', i, data);
//tr.updateDynamicTile(update);
}
});
rafTimeout(function() {
$(document).on('keydown', function(e) {
if (e.which === 27) $('#kick').hide();
});
}, 800);
//Make the viewport transparent...
if (defaultValues.transparent_viewport) {
//PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST;
tr.createRenderer = function() {
let options = {
view: tr.canvas,
antialias: true, //PIXI:false (TagPro:true)
forceFXAA: true, //PIXI:false (forceFXAA is faster, WebGL only)
forceCanvas: tr.options.forceCanvasRenderer, //PIXI:false
powerPreference: 'high-performance', //for devices with dual graphics cards the faster card will be used
transparent: true, //PIXI:false
backgroundColor: 0, //PIXI:0x000000
clearBeforeRender: true, //PIXI:true
preserveDrawingBuffer: false, //PIXI:false
roundPixels: false, //PIXI:false
width: 1280, //PIXI:800
height: 800, //PIXI:600
legacy: false //PIXI:false
};
return tr.options.forceCanvasRenderer ? new PIXI.CanvasRenderer(tr.canvas_width, tr.canvas_height, options) : PIXI.autoDetectRenderer(tr.canvas_width, tr.canvas_height, options);
};
let oldCanvas = $(tr.canvas);
let newCanvas = $('<canvas id="viewport" width="1280" height="800"></canvas>');
oldCanvas.after(newCanvas);
oldCanvas.remove();
tr.canvas = newCanvas.get(0);
tr.renderer = tr.createRenderer();
tr.resizeAndCenterView();
newCanvas.fadeIn(1500, function() {
updateCSS();
loadOptions();
//tr.resizeAndCenterView();
});
} else {
rafTimeout(function() {
updateCSS();
loadOptions();
}, 1500);
}
//Get some useful map data...
tagpro.socket.on('map', function(data) {
//console.log('map:',data);
for (let x=0; x<tagpro.map.length; x++) {
for (let y=0; y<tagpro.map[x].length; y++) {
let tileId = tagpro.map[x][y];
if ((tileId == 3) || (tileId == 3.1)) { //red flag
elementPositions.redflag.push({ x:x*40, y:y*40 });
} else if ((tileId == 4) || (tileId == 4.1)) { //blue flag
elementPositions.blueflag.push({ x:x*40, y:y*40 });
} else if ((tileId == 16) || (tileId == 16.1)) { //yellow flag
elementPositions.yellowflag.push({ x:x*40, y:y*40 });
} else if (tileId == 11) { //red teamtile
elementPositions.teamred.push({ x:x*40, y:y*40 });
} else if (tileId == 12) { //blue teamtile
elementPositions.teamblue.push({ x:x*40, y:y*40 });
} else if (tileId == 23) { //yellow teamtile
elementPositions.teamyellow.push({ x:x*40, y:y*40 });
} else if (tileId == 17) { //red endzone
elementPositions.ezred.locs.push({ x:x*40, y:y*40 });
if (!elementPositions.ezred.x) { //use the first found redzone tile for both
elementPositions.ezred.x = x*40+20;
elementPositions.ezred.y = y*40+20;
elementPositions.ezblue.x = Math.abs(tagpro.map.length*40 - elementPositions.ezred.x);
elementPositions.ezblue.y = Math.abs(tagpro.map[0].length*40 - elementPositions.ezred.y);
}
} else if (tileId == 18) { //blue endzone
elementPositions.ezblue.locs.push({ x:x*40, y:y*40 });
} else if (tileId == 10 || tileId == 10.1 || tileId == 10.11) { //bomb
elementPositions.bombs.push({ x:x*40, y:y*40 });
} else if (tileId == 7) { //spike
elementPositions.spikes.push({ x:x*40, y:y*40 });
} else if (tileId == 6 || tileId == 6.1 || tileId == 6.11 || tileId == 6.2 || tileId == 6.21 || tileId == 6.3 || tileId == 6.31 || tileId == 6.4 || tileId == 6.41) { //powerup
elementPositions.pups.push({ x:x*40, y:y*40 });
} else if (tileId == 5 || tileId == 5.1 || tileId == 5.11) { //neutral boost
elementPositions.boosts.yellow.push({ x:x*40, y:y*40 });
} else if (tileId == 14 || tileId == 14.1 || tileId == 14.11) { //red boost
elementPositions.boosts.red.push({ x:x*40, y:y*40 });
} else if (tileId == 15 || tileId == 15.1 || tileId == 15.11) { //blue boost
elementPositions.boosts.blue.push({ x:x*40, y:y*40 });
} else if (tileId == 9 || tileId == 9.1 || tileId == 9.2 || tileId == 9.3) { //gate
elementPositions.gates.push({ x:x*40, y:y*40 });
} else if (tileId == 8) { //button
elementPositions.buttons.push({ x:x*40, y:y*40 });
} else if (tileId == 13 || tileId == 13.1 || tileId == 13.11) { //portal
elementPositions.portals.push({ x:x*40, y:y*40 });
} else if (tileId == 22) { //gravityWell
elementPositions.gravityWells.push({ x:x*40, y:y*40 });
}
}
}
if (elementPositions.yellowflag.length) {
if (tagpro.map.length > tagpro.map[0].length) { //map width > height
elementPositions.halfway.x =(tagpro.map.length / 2) * 40;
} else if (tagpro.map.length < tagpro.map[0].length) { //map height > width
elementPositions.halfway.y = (tagpro.map[0].length / 2) * 40;
} else { //map width & height are the same
elementPositions.halfway.x = (tagpro.map.length / 2) * 40; //just use width
}
} else if ( Math.abs(elementPositions.redflag[0].x - elementPositions.blueflag[0].x) > Math.abs(elementPositions.redflag[0].y - elementPositions.blueflag[0].y) ) { //flags are further apart on the x axis
elementPositions.halfway.x = (tagpro.map.length / 2) * 40; //Math.floor(tagpro.map.length / 2) * 40;
} else if ( Math.abs(elementPositions.redflag[0].x - elementPositions.blueflag[0].x) < Math.abs(elementPositions.redflag[0].y - elementPositions.blueflag[0].y) ) { //flags are further apart on the y axis
elementPositions.halfway.y = (tagpro.map[0].length / 2) * 40;
} else { //flags are the same distance apart - use map dimensions...
if (tagpro.map.length > tagpro.map[0].length) { //map width > height
elementPositions.halfway.x =(tagpro.map.length / 2) * 40;
} else if (tagpro.map.length < tagpro.map[0].length) { //map height > width
elementPositions.halfway.y = (tagpro.map[0].length / 2) * 40;
} else { //map width & height are the same
elementPositions.halfway.x = (tagpro.map.length / 2) * 40; //just use width
}
}
elementPositions.mapInfo = data.info;
});
//draw to canvas functions...
function addGradientLines(ctx, width, height, type1, type2, color1, color2, opacity1, opacity2, repeats1=50, repeats2=4) {
let tempCanvas = new OffscreenCanvas(ctx.canvas.width, ctx.canvas.height);
let tempCtx = tempCanvas.getContext('2d');
let gradient;
let w2 = width/2;
let h2 = height/2;
opacity1 = opacity1 / 100;
opacity2 = opacity2 / 100;
ctx.save();
ctx.globalCompositeOperation = 'source-atop'; //source-atop
if (type1 === 'centerline') {
if (elementPositions.halfway.x) {
gradient = tempCtx.createLinearGradient(0, h2, width, h2);
} else {
gradient = tempCtx.createLinearGradient(w2, 0, w2, height);
}
} else if (type1 === 'diagonal') {
gradient = tempCtx.createLinearGradient(0, 0, Math.max(width, height), Math.max(width, height));
} else if (type1 === 'rdiagonal') {
gradient = tempCtx.createLinearGradient(Math.max(width, height), 0, 0, Math.max(width, height));
} else if (type1 === 'centercircle') {
gradient = tempCtx.createRadialGradient(w2, h2, 0, w2, h2, Math.sqrt(Math.max(width, height) * Math.max(width, height) * 2) / 2);
}
let co1 = hexToRgbA(color1, opacity1);
let co2 = hexToRgbA(color2, opacity2);
if (repeats1 === '0') {
gradient.addColorStop(0, co1);
gradient.addColorStop(1, co2);
} else {
let gradientInterval = 1 / repeats1;
let i = gradientInterval;
let alt = true;
gradient.addColorStop(0, co1);
while (i < 1) {
if (alt) {
gradient.addColorStop(i, co2);
alt = false;
} else {
gradient.addColorStop(i, co1);
alt = true;
}
i += gradientInterval;
}
gradient.addColorStop(1, co1);
}
tempCtx.fillStyle = gradient;
tempCtx.globalAlpha = 0.5;
tempCtx.fillRect(0, 0, width, height);
if (type2 === 'centerline') {
if (elementPositions.halfway.x) {
gradient = tempCtx.createLinearGradient(0, h2, width, h2);
} else {
gradient = tempCtx.createLinearGradient(w2, 0, w2, height);
}
} else if (type2 === 'diagonal') {
gradient = tempCtx.createLinearGradient(0, 0, Math.max(width, height), Math.max(width, height));
} else if (type2 === 'rdiagonal') {
gradient = tempCtx.createLinearGradient(Math.max(width, height), 0, 0, Math.max(width, height));
} else if (type2 === 'centercircle') {
gradient = tempCtx.createRadialGradient(w2, h2, 0, w2, h2, Math.sqrt(Math.max(width, height) * Math.max(width, height) * 2) / 2);
}
if (repeats2 === '0') {
gradient.addColorStop(0, co1);
gradient.addColorStop(1, co2);
} else {
let gradientInterval = 1 / repeats2;
let i = gradientInterval;
let alt = true;
gradient.addColorStop(0, co1);
while (i < 1) {
if (alt) {
gradient.addColorStop(i, co2);
alt = false;
} else {
gradient.addColorStop(i, co1);
alt = true;
}
i += gradientInterval;
}
gradient.addColorStop(1, co1);
}
tempCtx.fillStyle = gradient;
tempCtx.globalAlpha = 0.5;
tempCtx.fillRect(0, 0, width, height);
ctx.drawImage(tempCanvas, 0, 0);
ctx.globalCompositeOperation = 'source-over';
ctx.restore();
tempCanvas = null;
}
function addGradient(ctx, width, height, type, color1, color2, opacity1, opacity2, repeats='2') {
let gradient;
let w2 = width/2;
let h2 = height/2;
opacity1 = opacity1 / 100;
opacity2 = opacity2 / 100;
ctx.save();
ctx.globalCompositeOperation = 'source-atop'; //source-atop
if (type === 'centerline') {
if (elementPositions.halfway.x) {
gradient = ctx.createLinearGradient(0, h2, width, h2);
} else {
gradient = ctx.createLinearGradient(w2, 0, w2, height);
}
} else if (type === 'diagonal') {
gradient = ctx.createLinearGradient(0, 0, Math.max(width, height), Math.max(width, height));
} else if (type === 'rdiagonal') {
gradient = ctx.createLinearGradient(Math.max(width, height), 0, 0, Math.max(width, height));
} else if (type === 'centercircle') {
gradient = ctx.createRadialGradient(w2, h2, 0, w2, h2, Math.sqrt(Math.max(width, height) * Math.max(width, height) * 2) / 2);
}
let co1 = hexToRgbA(color1, opacity1);
let co2 = hexToRgbA(color2, opacity2);
if (repeats === '0') {
gradient.addColorStop(0, co1);
gradient.addColorStop(1, co2);
} else {
let gradientInterval = 1 / repeats;
let i = gradientInterval;
let alt = true;
gradient.addColorStop(0, co1);
while (i < 1) {
if (alt) {
gradient.addColorStop(i, co2);
alt = false;
} else {
gradient.addColorStop(i, co1);
alt = true;
}
i += gradientInterval;
}
gradient.addColorStop(1, co1);
}
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
ctx.globalCompositeOperation = 'source-over';
ctx.restore();
}
function addCheckered(ctx, mapWidth, mapHeight, size=+defaultValues.checkered_size, margin=+defaultValues.checkered_margin, random=defaultValues.checkered_random, straight=false, stripes=false, globalCompositeOperation='source-over') {
ctx.save();
ctx.globalCompositeOperation = globalCompositeOperation; //'source-over'; //atop
if (random) {
//if (size < 5) size = 5; //too slow with < 5
ctx.beginPath();
for (let i=0; i<mapWidth; i+=size) {
for (let j=0; j<mapHeight; j+=size) {
ctx.fillStyle = hexToRgbA(averageTileColors.floorAlt2, getRandomInt(0, 10) / 100);
ctx.fillRect(i+margin, j+margin, size-margin*2, size-margin*2);
}
}
//ctx.closePath();
} else if (stripes) {
ctx.fillStyle = hexToRgbA(averageTileColors.floorAlt2, defaultValues.checkered_opacity / 100);
for (let j=0; j<mapHeight; j+=size*2) {
ctx.fillRect(0, j, mapWidth, size);
ctx.clearRect(0, j+size, mapWidth, size*2);
}
} else {
let pattern = new OffscreenCanvas(size * 2, size * 2);
let pctx = pattern.getContext('2d');
pctx.beginPath();
pctx.fillStyle = hexToRgbA(averageTileColors.floorAlt2, defaultValues.checkered_opacity / 100);
pctx.fillRect(size+margin, margin, size-margin*2, size-margin*2); //top right
if (!straight) pctx.fillRect(margin, size+margin, size-margin*2, size-margin*2); //bottom left
let patt = ctx.createPattern(pattern, "repeat");
ctx.fillStyle = patt;
ctx.fillRect(0, 0, mapWidth, mapHeight);
pattern = null;
}
ctx.globalCompositeOperation = 'source-over';
ctx.restore();
}
function addSquareGrid(ctx, mapWidth, mapHeight, size=40, random=false, rectangles=false, lines=false, globalCompositeOperation='source-over') {
ctx.save();
ctx.globalCompositeOperation = globalCompositeOperation;
if (random) {
ctx.lineWidth = 1;
ctx.translate(0.5, 0.5);
for (let i=0; i<mapWidth; i+=size) {
for (let j=0; j<mapHeight; j+=size) {
let maxl = 1; //lineWidth
let maxr = 1; //randomDraw
let maxo = 20; //opacity
ctx.beginPath();
if (getRandomInt(0, maxr) === 0) { //top
let gradient = ctx.createLinearGradient(i, j, i+size, j);
gradient.addColorStop(0, hexToRgbA(averageTileColors.floor, getRandomInt(0, maxo) / 100));
gradient.addColorStop(1, hexToRgbA(averageTileColors.floorAlt, getRandomInt(0, maxo) / 100));
ctx.lineWidth = getRandomInt(1, maxl);
ctx.strokeStyle = gradient; //hexToRgbA(averageTileColors.floorAlt, getRandomInt(0, maxo) / 100);
ctx.moveTo(i, j);
ctx.lineTo(i+size, j);
}
if (getRandomInt(0, maxr) === 0) { //right
let gradient = ctx.createLinearGradient(i+size, j, i+size, j+size);
gradient.addColorStop(0, hexToRgbA(averageTileColors.floor, getRandomInt(0, maxo) / 100));
gradient.addColorStop(1, hexToRgbA(averageTileColors.floorAlt, getRandomInt(0, maxo) / 100));
ctx.lineWidth = getRandomInt(1, maxl);
ctx.strokeStyle = gradient; //hexToRgbA(averageTileColors.floorAlt, getRandomInt(0, maxo) / 100);
ctx.moveTo(i+size, j);
ctx.lineTo(i+size, j+size);
}
if (getRandomInt(0, maxr) === 0) { //bottom
let gradient = ctx.createLinearGradient(i+size, j+size, i, j+size);
gradient.addColorStop(0, hexToRgbA(averageTileColors.floorAlt, getRandomInt(0, maxo) / 100));
gradient.addColorStop(1, hexToRgbA(averageTileColors.floor, getRandomInt(0, maxo) / 100));
ctx.lineWidth = getRandomInt(1, maxl);
ctx.strokeStyle = gradient; //hexToRgbA(averageTileColors.floorAlt, getRandomInt(0, maxo) / 100);
ctx.moveTo(i+size, j+size);
ctx.lineTo(i, j+size);
}
if (getRandomInt(0, maxr) === 0) { //left
let gradient = ctx.createLinearGradient(i, j+size, i, j);
gradient.addColorStop(0, hexToRgbA(averageTileColors.floorAlt, getRandomInt(0, maxo) / 100));
gradient.addColorStop(1, hexToRgbA(averageTileColors.floor, getRandomInt(0, maxo) / 100));
ctx.lineWidth = getRandomInt(1, maxl);
ctx.strokeStyle = gradient; //hexToRgbA(averageTileColors.floorAlt, getRandomInt(0, maxo) / 100);
ctx.moveTo(i, j+size);
ctx.lineTo(i, j);
}
ctx.stroke();
ctx.closePath();
}
}
} else {
let pattern = new OffscreenCanvas(size, size);
let pctx = pattern.getContext('2d');
if (defaultValues.grids_square_blur > 0) {
pctx.filter = 'blur('+defaultValues.grids_square_blur+'px)';
}
pctx.translate(0.5, 0.5);
pctx.strokeStyle = hexToRgbA(averageTileColors.floorAlt2, rectangles ? 0.3 : defaultValues.grids_square_opacity / 100); //defaultValues.grids_square_color
pctx.lineWidth = defaultValues.grids_square_linewidth;
pctx.beginPath();
if (lines) {
pctx.moveTo(0, size/2);
pctx.lineTo(size, size/2);
pctx.stroke();
} else {
pctx.moveTo(0, size);
pctx.lineTo(0, 0);
pctx.lineTo(size, 0);
if (rectangles) {
pctx.moveTo(0, size/2);
pctx.lineTo(size, size/2);
}
pctx.stroke();
}
pctx.closePath();
let patt = ctx.createPattern(pattern, "repeat");
ctx.fillStyle = patt;
ctx.fillRect(0, 0, mapWidth, mapHeight);
pattern = null;
}
ctx.filter = 'none';
ctx.globalCompositeOperation = 'source-over';
ctx.restore();
}
function addDiagonalGrid(ctx, mapWidth, mapHeight, size=120, globalCompositeOperation='source-over') {
let pattern = new OffscreenCanvas(size, size);
let pctx = pattern.getContext('2d');
ctx.save();
ctx.globalCompositeOperation = globalCompositeOperation;
pctx.strokeStyle = hexToRgbA(averageTileColors.floorAlt2, defaultValues.grids_diagonal_opacity / 100);
pctx.lineWidth = 1;
pctx.beginPath();
pctx.moveTo(0, 0);
pctx.lineTo(size, size);
pctx.moveTo(size, 0);
pctx.lineTo(0, size);
pctx.stroke();
pctx.closePath();
let patt = ctx.createPattern(pattern, "repeat");
ctx.fillStyle = patt;
ctx.fillRect(0, 0, mapWidth, mapHeight);
pattern = null;
ctx.globalCompositeOperation = 'source-over';
ctx.restore();
}
function addPatternGrid(ctx, mapWidth, mapHeight, size=120, lineWidth=1, color='#000000', blur=0, dashsize=false, max_random=1, max_length=1, type='square', direction='both', globalCompositeOperation='source-over') {
ctx.save();
ctx.globalCompositeOperation = globalCompositeOperation;
ctx.lineWidth = lineWidth;
ctx.lineCap = 'round';
if (Array.isArray(dashsize)) ctx.setLineDash(dashsize);
else if (dashsize > 0) ctx.setLineDash([dashsize]);
ctx.strokeStyle = color;
if (blur > 0) ctx.filter = 'blur(' + blur + 'px)';
ctx.translate(0.5, 0.5);
ctx.beginPath();
let this_type = type;
let do_horizontal = direction === 'horizontal' || direction === 'both' ? true : false;
let do_vertical = direction === 'vertical' || direction === 'both' ? true : false;
for (let x=0; x<mapWidth; x+=size) {
for (let y=0; y<mapHeight; y+=size) {
let this_length = getRandomInt(1, max_length);
let this_random = getRandomInt(0, max_random);
if (type === 'both') {
if (getRandomInt(0, 1) === 0) this_type = 'square';
else this_type = 'diagonal';
}
if (this_type === 'square') {
if (this_random === 0) {
if (do_horizontal) {
ctx.moveTo(x, y);
ctx.lineTo(x + size * this_length, y);
}
} else if (this_random === 1) {
if (do_vertical) {
ctx.moveTo(x, y);
ctx.lineTo(x, y + size * this_length);
}
}
} else if (this_type === 'diagonal') {
if (this_random === 0) {
if (do_horizontal) {
ctx.moveTo(x, y);
ctx.lineTo(x + size * this_length, y + size * this_length);
}
} else if (this_random === 1) {
if (do_vertical) {
ctx.moveTo(x + size, y);
ctx.lineTo((x + size) - size * this_length, y + size * this_length);
}
}
}
}
}
ctx.closePath();
ctx.stroke();
ctx.filter = 'none';
ctx.setLineDash([]);
ctx.translate(-0.5, -0.5);
ctx.globalCompositeOperation = 'source-over';
ctx.restore();
}
function drawCentreCircle(ctx, x, y, color1='#ff8080', color2='#0080ff') {
ctx.filter = 'blur(4px)';
ctx.lineWidth = 5;
ctx.fillStyle = color1;
ctx.strokeStyle = color1;
ctx.beginPath();
if (elementPositions.halfway.x) ctx.arc(x, y, 300, 3/2*Math.PI, Math.PI/2, true);
else ctx.arc(x, y, 300, 0, Math.PI*2, false);
ctx.fill();
ctx.beginPath();
if (elementPositions.halfway.x) ctx.arc(x, y, 160, 3/2*Math.PI, Math.PI/2, true);
else ctx.arc(x, y, 160, 0, Math.PI*2, false);
ctx.stroke();
ctx.fillStyle = color2;
ctx.strokeStyle = color2;
ctx.beginPath();
if (elementPositions.halfway.x) ctx.arc(x, y, 300, 3/2*Math.PI, Math.PI/2);
else ctx.arc(x, y, 300, 0, Math.PI*2, true);
ctx.fill();
ctx.beginPath();
if (elementPositions.halfway.x) ctx.arc(x, y, 160, 3/2*Math.PI, Math.PI/2);
else ctx.arc(x, y, 160, 0, Math.PI*2, true);
ctx.stroke();
ctx.filter = 'none';
}
function drawCircle(ctx, linewidth, radius, color, opacity, useGradient, dashsize, blur, x, y, fill, fillColor) {
ctx.save();
if (blur > 0) ctx.filter = 'blur(' + blur + 'px)';
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2*Math.PI);
ctx.closePath();
if (fill) {
ctx.fillStyle = fillColor;
ctx.fill();
}
if (linewidth > 0) {
ctx.lineWidth = linewidth;
if (Array.isArray(dashsize)) ctx.setLineDash(dashsize);
else if (dashsize > 0) ctx.setLineDash([dashsize]);
if (useGradient) {
let radialGradient = ctx.createRadialGradient(x, y, radius-linewidth/2, x, y, +radius+linewidth/2);
radialGradient.addColorStop(0, hexToRgbA(color, opacity));
radialGradient.addColorStop(1, hexToRgbA(color, 0));
ctx.strokeStyle = radialGradient;
} else {
ctx.strokeStyle = hexToRgbA(color, opacity);
}
ctx.stroke();
ctx.setLineDash([]);
}
ctx.filter = 'none';
ctx.globalCompositeOperation = 'source-over';
ctx.restore();
}
function drawLine(ctx, x1, y1, x2, y2, color='#000000', lineWidth=1, dashsize=0) {
ctx.save();
//ctx.globalCompositeOperation = 'source-over'; //atop
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
if (Array.isArray(dashsize)) {
ctx.setLineDash(dashsize);
if (lineWidth % 2 !== 0) ctx.translate(0.5, 0.5);
} else if (dashsize > 0) {
ctx.setLineDash([dashsize]);
if (lineWidth % 2 !== 0) ctx.translate(0.5, 0.5);
}
if (lineWidth % 2 !== 0) ctx.translate(0.5, 0.5)
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
ctx.closePath();
if (dashsize > 0) {
if (doTranslate) ctx.translate(-0.5, -0.5);
ctx.setLineDash([]);
}
ctx.filter = 'none';
ctx.globalCompositeOperation = 'source-over';
ctx.restore();
}
let kbLogoImage = new Image();
let kbLogoData = 'data:image/png;base64,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';
kbLogoImage.src = kbLogoData;
function addKoalaBeast(ctx, x, y) {
let opacity = 0.1;
let scale = 5;
let blur = 2;
x = (x + 3.5 * scale) - kbLogoImage.naturalWidth * scale / 2;
y = y - kbLogoImage.naturalHeight * scale / 2;
ctx.save();
ctx.globalAlpha = opacity;
ctx.filter = 'blur(' + blur + 'px)';
ctx.drawImage(kbLogoImage, 0,0,kbLogoImage.naturalWidth,kbLogoImage.naturalHeight, x,y,kbLogoImage.naturalWidth*scale,kbLogoImage.naturalHeight*scale);
ctx.filter = 'none';
ctx.globalAlpha = 1;
ctx.restore();
}
//helper functions...
function getAverageColor(data, asHex=false, ignoreGrey=false) {
let rgb = { r:null, g:null, b:null };
let length = data.length;
let pixelInterval = 1;
let count = 0;
let i = -4;
while ((i += pixelInterval * 4) < length) {
//let b = data[i] * 0.299 + data[i+1] * 0.587 + data[i+2] * 0.114;
let isGrey = ignoreGrey && (Math.abs(data[i] - data[i+1]) + Math.abs(data[i+1] - data[i+2]) < 10);
if (!isGrey && data[i+3]) {
rgb.r += data[i];
rgb.g += data[i+1];
rgb.b += data[i+2];
count++;
}
}
if (count === 0) return null; //empty/transparent
rgb.r = Math.floor(rgb.r / count);
rgb.g = Math.floor(rgb.g / count);
rgb.b = Math.floor(rgb.b / count);
if (asHex) {
return rgbToHex(rgb.r, rgb.g, rgb.b).slice(0, 7);
} else {
return rgb;
}
}
function rgbToHex(r, g, b) {
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
function hexToRgbA(hex, alpha=1) {
if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
var 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 getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
// TinyColor v1.4.1
// https://github.com/bgrins/TinyColor
// 2016-07-07, Brian Grinstead, MIT License
!function(a){function b(a,d){if(a=a?a:"",d=d||{},a instanceof b)return a;if(!(this instanceof b))return new b(a,d);var e=c(a);this._originalInput=a,this._r=e.r,this._g=e.g,this._b=e.b,this._a=e.a,this._roundA=P(100*this._a)/100,this._format=d.format||e.format,this._gradientType=d.gradientType,this._r<1&&(this._r=P(this._r)),this._g<1&&(this._g=P(this._g)),this._b<1&&(this._b=P(this._b)),this._ok=e.ok,this._tc_id=O++}function c(a){var b={r:0,g:0,b:0},c=1,e=null,g=null,i=null,j=!1,k=!1;return"string"==typeof a&&(a=K(a)),"object"==typeof a&&(J(a.r)&&J(a.g)&&J(a.b)?(b=d(a.r,a.g,a.b),j=!0,k="%"===String(a.r).substr(-1)?"prgb":"rgb"):J(a.h)&&J(a.s)&&J(a.v)?(e=G(a.s),g=G(a.v),b=h(a.h,e,g),j=!0,k="hsv"):J(a.h)&&J(a.s)&&J(a.l)&&(e=G(a.s),i=G(a.l),b=f(a.h,e,i),j=!0,k="hsl"),a.hasOwnProperty("a")&&(c=a.a)),c=z(c),{ok:j,format:a.format||k,r:Q(255,R(b.r,0)),g:Q(255,R(b.g,0)),b:Q(255,R(b.b,0)),a:c}}function d(a,b,c){return{r:255*A(a,255),g:255*A(b,255),b:255*A(c,255)}}function e(a,b,c){a=A(a,255),b=A(b,255),c=A(c,255);var d,e,f=R(a,b,c),g=Q(a,b,c),h=(f+g)/2;if(f==g)d=e=0;else{var i=f-g;switch(e=h>.5?i/(2-f-g):i/(f+g),f){case a:d=(b-c)/i+(c>b?6:0);break;case b:d=(c-a)/i+2;break;case c:d=(a-b)/i+4}d/=6}return{h:d,s:e,l:h}}function f(a,b,c){function d(a,b,c){return 0>c&&(c+=1),c>1&&(c-=1),1/6>c?a+6*(b-a)*c:.5>c?b:2/3>c?a+6*(b-a)*(2/3-c):a}var e,f,g;if(a=A(a,360),b=A(b,100),c=A(c,100),0===b)e=f=g=c;else{var h=.5>c?c*(1+b):c+b-c*b,i=2*c-h;e=d(i,h,a+1/3),f=d(i,h,a),g=d(i,h,a-1/3)}return{r:255*e,g:255*f,b:255*g}}function g(a,b,c){a=A(a,255),b=A(b,255),c=A(c,255);var d,e,f=R(a,b,c),g=Q(a,b,c),h=f,i=f-g;if(e=0===f?0:i/f,f==g)d=0;else{switch(f){case a:d=(b-c)/i+(c>b?6:0);break;case b:d=(c-a)/i+2;break;case c:d=(a-b)/i+4}d/=6}return{h:d,s:e,v:h}}function h(b,c,d){b=6*A(b,360),c=A(c,100),d=A(d,100);var e=a.floor(b),f=b-e,g=d*(1-c),h=d*(1-f*c),i=d*(1-(1-f)*c),j=e%6,k=[d,h,g,g,i,d][j],l=[i,d,d,h,g,g][j],m=[g,g,i,d,d,h][j];return{r:255*k,g:255*l,b:255*m}}function i(a,b,c,d){var e=[F(P(a).toString(16)),F(P(b).toString(16)),F(P(c).toString(16))];return d&&e[0].charAt(0)==e[0].charAt(1)&&e[1].charAt(0)==e[1].charAt(1)&&e[2].charAt(0)==e[2].charAt(1)?e[0].charAt(0)+e[1].charAt(0)+e[2].charAt(0):e.join("")}function j(a,b,c,d,e){var f=[F(P(a).toString(16)),F(P(b).toString(16)),F(P(c).toString(16)),F(H(d))];return e&&f[0].charAt(0)==f[0].charAt(1)&&f[1].charAt(0)==f[1].charAt(1)&&f[2].charAt(0)==f[2].charAt(1)&&f[3].charAt(0)==f[3].charAt(1)?f[0].charAt(0)+f[1].charAt(0)+f[2].charAt(0)+f[3].charAt(0):f.join("")}function k(a,b,c,d){var e=[F(H(d)),F(P(a).toString(16)),F(P(b).toString(16)),F(P(c).toString(16))];return e.join("")}function l(a,c){c=0===c?0:c||10;var d=b(a).toHsl();return d.s-=c/100,d.s=B(d.s),b(d)}function m(a,c){c=0===c?0:c||10;var d=b(a).toHsl();return d.s+=c/100,d.s=B(d.s),b(d)}function n(a){return b(a).desaturate(100)}function o(a,c){c=0===c?0:c||10;var d=b(a).toHsl();return d.l+=c/100,d.l=B(d.l),b(d)}function p(a,c){c=0===c?0:c||10;var d=b(a).toRgb();return d.r=R(0,Q(255,d.r-P(255*-(c/100)))),d.g=R(0,Q(255,d.g-P(255*-(c/100)))),d.b=R(0,Q(255,d.b-P(255*-(c/100)))),b(d)}function q(a,c){c=0===c?0:c||10;var d=b(a).toHsl();return d.l-=c/100,d.l=B(d.l),b(d)}function r(a,c){var d=b(a).toHsl(),e=(d.h+c)%360;return d.h=0>e?360+e:e,b(d)}function s(a){var c=b(a).toHsl();return c.h=(c.h+180)%360,b(c)}function t(a){var c=b(a).toHsl(),d=c.h;return[b(a),b({h:(d+120)%360,s:c.s,l:c.l}),b({h:(d+240)%360,s:c.s,l:c.l})]}function u(a){var c=b(a).toHsl(),d=c.h;return[b(a),b({h:(d+90)%360,s:c.s,l:c.l}),b({h:(d+180)%360,s:c.s,l:c.l}),b({h:(d+270)%360,s:c.s,l:c.l})]}function v(a){var c=b(a).toHsl(),d=c.h;return[b(a),b({h:(d+72)%360,s:c.s,l:c.l}),b({h:(d+216)%360,s:c.s,l:c.l})]}function w(a,c,d){c=c||6,d=d||30;var e=b(a).toHsl(),f=360/d,g=[b(a)];for(e.h=(e.h-(f*c>>1)+720)%360;--c;)e.h=(e.h+f)%360,g.push(b(e));return g}function x(a,c){c=c||6;for(var d=b(a).toHsv(),e=d.h,f=d.s,g=d.v,h=[],i=1/c;c--;)h.push(b({h:e,s:f,v:g})),g=(g+i)%1;return h}function y(a){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[a[c]]=c);return b}function z(a){return a=parseFloat(a),(isNaN(a)||0>a||a>1)&&(a=1),a}function A(b,c){D(b)&&(b="100%");var d=E(b);return b=Q(c,R(0,parseFloat(b))),d&&(b=parseInt(b*c,10)/100),a.abs(b-c)<1e-6?1:b%c/parseFloat(c)}function B(a){return Q(1,R(0,a))}function C(a){return parseInt(a,16)}function D(a){return"string"==typeof a&&-1!=a.indexOf(".")&&1===parseFloat(a)}function E(a){return"string"==typeof a&&-1!=a.indexOf("%")}function F(a){return 1==a.length?"0"+a:""+a}function G(a){return 1>=a&&(a=100*a+"%"),a}function H(b){return a.round(255*parseFloat(b)).toString(16)}function I(a){return C(a)/255}function J(a){return!!V.CSS_UNIT.exec(a)}function K(a){a=a.replace(M,"").replace(N,"").toLowerCase();var b=!1;if(T[a])a=T[a],b=!0;else if("transparent"==a)return{r:0,g:0,b:0,a:0,format:"name"};var c;return(c=V.rgb.exec(a))?{r:c[1],g:c[2],b:c[3]}:(c=V.rgba.exec(a))?{r:c[1],g:c[2],b:c[3],a:c[4]}:(c=V.hsl.exec(a))?{h:c[1],s:c[2],l:c[3]}:(c=V.hsla.exec(a))?{h:c[1],s:c[2],l:c[3],a:c[4]}:(c=V.hsv.exec(a))?{h:c[1],s:c[2],v:c[3]}:(c=V.hsva.exec(a))?{h:c[1],s:c[2],v:c[3],a:c[4]}:(c=V.hex8.exec(a))?{r:C(c[1]),g:C(c[2]),b:C(c[3]),a:I(c[4]),format:b?"name":"hex8"}:(c=V.hex6.exec(a))?{r:C(c[1]),g:C(c[2]),b:C(c[3]),format:b?"name":"hex"}:(c=V.hex4.exec(a))?{r:C(c[1]+""+c[1]),g:C(c[2]+""+c[2]),b:C(c[3]+""+c[3]),a:I(c[4]+""+c[4]),format:b?"name":"hex8"}:(c=V.hex3.exec(a))?{r:C(c[1]+""+c[1]),g:C(c[2]+""+c[2]),b:C(c[3]+""+c[3]),format:b?"name":"hex"}:!1}function L(a){var b,c;return a=a||{level:"AA",size:"small"},b=(a.level||"AA").toUpperCase(),c=(a.size||"small").toLowerCase(),"AA"!==b&&"AAA"!==b&&(b="AA"),"small"!==c&&"large"!==c&&(c="small"),{level:b,size:c}}var M=/^\s+/,N=/\s+$/,O=0,P=a.round,Q=a.min,R=a.max,S=a.random;b.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var a=this.toRgb();return(299*a.r+587*a.g+114*a.b)/1e3},getLuminance:function(){var b,c,d,e,f,g,h=this.toRgb();return b=h.r/255,c=h.g/255,d=h.b/255,e=.03928>=b?b/12.92:a.pow((b+.055)/1.055,2.4),f=.03928>=c?c/12.92:a.pow((c+.055)/1.055,2.4),g=.03928>=d?d/12.92:a.pow((d+.055)/1.055,2.4),.2126*e+.7152*f+.0722*g},setAlpha:function(a){return this._a=z(a),this._roundA=P(100*this._a)/100,this},toHsv:function(){var a=g(this._r,this._g,this._b);return{h:360*a.h,s:a.s,v:a.v,a:this._a}},toHsvString:function(){var a=g(this._r,this._g,this._b),b=P(360*a.h),c=P(100*a.s),d=P(100*a.v);return 1==this._a?"hsv("+b+", "+c+"%, "+d+"%)":"hsva("+b+", "+c+"%, "+d+"%, "+this._roundA+")"},toHsl:function(){var a=e(this._r,this._g,this._b);return{h:360*a.h,s:a.s,l:a.l,a:this._a}},toHslString:function(){var a=e(this._r,this._g,this._b),b=P(360*a.h),c=P(100*a.s),d=P(100*a.l);return 1==this._a?"hsl("+b+", "+c+"%, "+d+"%)":"hsla("+b+", "+c+"%, "+d+"%, "+this._roundA+")"},toHex:function(a){return i(this._r,this._g,this._b,a)},toHexString:function(a){return"#"+this.toHex(a)},toHex8:function(a){return j(this._r,this._g,this._b,this._a,a)},toHex8String:function(a){return"#"+this.toHex8(a)},toRgb:function(){return{r:P(this._r),g:P(this._g),b:P(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+P(this._r)+", "+P(this._g)+", "+P(this._b)+")":"rgba("+P(this._r)+", "+P(this._g)+", "+P(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:P(100*A(this._r,255))+"%",g:P(100*A(this._g,255))+"%",b:P(100*A(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+P(100*A(this._r,255))+"%, "+P(100*A(this._g,255))+"%, "+P(100*A(this._b,255))+"%)":"rgba("+P(100*A(this._r,255))+"%, "+P(100*A(this._g,255))+"%, "+P(100*A(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":this._a<1?!1:U[i(this._r,this._g,this._b,!0)]||!1},toFilter:function(a){var c="#"+k(this._r,this._g,this._b,this._a),d=c,e=this._gradientType?"GradientType = 1, ":"";if(a){var f=b(a);d="#"+k(f._r,f._g,f._b,f._a)}return"progid:DXImageTransform.Microsoft.gradient("+e+"startColorstr="+c+",endColorstr="+d+")"},toString:function(a){var b=!!a;a=a||this._format;var c=!1,d=this._a<1&&this._a>=0,e=!b&&d&&("hex"===a||"hex6"===a||"hex3"===a||"hex4"===a||"hex8"===a||"name"===a);return e?"name"===a&&0===this._a?this.toName():this.toRgbString():("rgb"===a&&(c=this.toRgbString()),"prgb"===a&&(c=this.toPercentageRgbString()),("hex"===a||"hex6"===a)&&(c=this.toHexString()),"hex3"===a&&(c=this.toHexString(!0)),"hex4"===a&&(c=this.toHex8String(!0)),"hex8"===a&&(c=this.toHex8String()),"name"===a&&(c=this.toName()),"hsl"===a&&(c=this.toHslString()),"hsv"===a&&(c=this.toHsvString()),c||this.toHexString())},clone:function(){return b(this.toString())},_applyModification:function(a,b){var c=a.apply(null,[this].concat([].slice.call(b)));return this._r=c._r,this._g=c._g,this._b=c._b,this.setAlpha(c._a),this},lighten:function(){return this._applyModification(o,arguments)},brighten:function(){return this._applyModification(p,arguments)},darken:function(){return this._applyModification(q,arguments)},desaturate:function(){return this._applyModification(l,arguments)},saturate:function(){return this._applyModification(m,arguments)},greyscale:function(){return this._applyModification(n,arguments)},spin:function(){return this._applyModification(r,arguments)},_applyCombination:function(a,b){return a.apply(null,[this].concat([].slice.call(b)))},analogous:function(){return this._applyCombination(w,arguments)},complement:function(){return this._applyCombination(s,arguments)},monochromatic:function(){return this._applyCombination(x,arguments)},splitcomplement:function(){return this._applyCombination(v,arguments)},triad:function(){return this._applyCombination(t,arguments)},tetrad:function(){return this._applyCombination(u,arguments)}},b.fromRatio=function(a,c){if("object"==typeof a){var d={};for(var e in a)a.hasOwnProperty(e)&&(d[e]="a"===e?a[e]:G(a[e]));a=d}return b(a,c)},b.equals=function(a,c){return a&&c?b(a).toRgbString()==b(c).toRgbString():!1},b.random=function(){return b.fromRatio({r:S(),g:S(),b:S()})},b.mix=function(a,c,d){d=0===d?0:d||50;var e=b(a).toRgb(),f=b(c).toRgb(),g=d/100,h={r:(f.r-e.r)*g+e.r,g:(f.g-e.g)*g+e.g,b:(f.b-e.b)*g+e.b,a:(f.a-e.a)*g+e.a};return b(h)},b.readability=function(c,d){var e=b(c),f=b(d);return(a.max(e.getLuminance(),f.getLuminance())+.05)/(a.min(e.getLuminance(),f.getLuminance())+.05)},b.isReadable=function(a,c,d){var e,f,g=b.readability(a,c);switch(f=!1,e=L(d),e.level+e.size){case"AAsmall":case"AAAlarge":f=g>=4.5;break;case"AAlarge":f=g>=3;break;case"AAAsmall":f=g>=7}return f},b.mostReadable=function(a,c,d){var e,f,g,h,i=null,j=0;d=d||{},f=d.includeFallbackColors,g=d.level,h=d.size;for(var k=0;k<c.length;k++)e=b.readability(a,c[k]),e>j&&(j=e,i=b(c[k]));return b.isReadable(a,i,{level:g,size:h})||!f?i:(d.includeFallbackColors=!1,b.mostReadable(a,["#fff","#000"],d))};var T=b.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},U=b.hexNames=y(T),V=function(){var a="[-\\+]?\\d+%?",b="[-\\+]?\\d*\\.\\d+%?",c="(?:"+b+")|(?:"+a+")",d="[\\s|\\(]+("+c+")[,|\\s]+("+c+")[,|\\s]+("+c+")\\s*\\)?",e="[\\s|\\(]+("+c+")[,|\\s]+("+c+")[,|\\s]+("+c+")[,|\\s]+("+c+")\\s*\\)?";return{CSS_UNIT:new RegExp(c),rgb:new RegExp("rgb"+d),rgba:new RegExp("rgba"+e),hsl:new RegExp("hsl"+d),hsla:new RegExp("hsla"+e),hsv:new RegExp("hsv"+d),hsva:new RegExp("hsva"+e),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();"undefined"!=typeof module&&module.exports?module.exports=b:"function"==typeof define&&define.amd?define(function(){return b}):window.tinycolor=b}(Math);
});
//https://codereview.stackexchange.com/questions/47889/alternative-to-setinterval-and-settimeout
function rafTimeout(callback, delay, arg = null) {
let dateNow = Date.now,
requestAnimation = window.requestAnimationFrame,
start = dateNow(),
stop,
timeoutFunc = function() {
dateNow() - start < delay ? stop || requestAnimation(timeoutFunc) : callback(arg);
};
requestAnimation(timeoutFunc);
return {
clear:function() {
stop = 1;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment