Skip to content

Commit

Permalink
Edit Color Matrix from goonstation (TauCetiStation#6361)
Browse files Browse the repository at this point in the history
* Color-Matrix

* debug_color_matrix

* static

* oof

* Кнопка, чтобы скопировать текущую матрицу

* Update code/modules/admin/verbs/debug.dm

Co-authored-by: LudwigVonChesterfield <[email protected]>

* Рефактор (в что-то более читаемое)

* addtimer

* removes fuckYouByondBrowser()

Co-authored-by: LudwigVonChesterfield <[email protected]>
  • Loading branch information
T6751 and LudwigVonChesterfield authored Dec 28, 2020
1 parent 28b5d52 commit ecc056d
Show file tree
Hide file tree
Showing 3 changed files with 363 additions and 0 deletions.
1 change: 1 addition & 0 deletions code/modules/admin/admin_verbs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ var/list/admin_verbs_server = list(
/client/proc/adminchangemap,
)
var/list/admin_verbs_debug = list(
/client/proc/edit_color_matrix,
/client/proc/restart_controller,
/client/proc/cmd_admin_list_open_jobs,
/client/proc/Debug2,
Expand Down
52 changes: 52 additions & 0 deletions code/modules/admin/verbs/debug.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2101,3 +2101,55 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
usr.client.sent_assets = list()

to_chat(usr, "Your NanoUI Resource files have been refreshed")

// from Goonstation
/client/proc/edit_color_matrix()
set category = "Debug"
set name = "Edit Color Matrix"
set desc = "A little more control over the VFX"

if(!check_rights(R_DEBUG))
return

var/static/datum/debug_color_matrix/debug_color_matrix = new
debug_color_matrix.edit(src)

/datum/debug_color_matrix

/datum/debug_color_matrix/proc/edit(client/user)
var/static/editor = file2text('html/admin/color_matrix.html')
user << browse(editor, "window=colormatrix;size=410x500;")
addtimer(CALLBACK(src, .proc/callJsFunc, usr, "setRef", list("\ref[src]")), 10) //This is shit but without it, it calls the JS before the window is open and doesn't work.

/datum/debug_color_matrix/Topic(href, href_list)
if(!islist(usr.client.color))
usr.client.color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1)

// as somepotato pointed out this form is very insecure, so let's do some serverside verification that we got what we wanted
var/sanitised = sanitize(strip_html_properly(href_list["matrix"]))
var/list/matrixStrings = splittext(sanitised, ",")
// we are expecting 12 strings, so abort if we don't have that many
if(matrixStrings.len != 20)
return

var/list/matrix = list()
for(var/matrixString in matrixStrings)
var/num = text2num(matrixString)
if(isnum(num))
matrix += num

var/list/show_to = list(usr.client)

if(href_list["everyone"] == "y")
show_to = clients

if(href_list["animate"] == "y")
for(var/client/C in show_to)
animate(C, color = matrix, time = 5, easing = SINE_EASING)
else
for(var/client/C in show_to)
C.color = matrix

/datum/debug_color_matrix/proc/callJsFunc(client, funcName, list/params)
var/paramsJS = list2params(params)
client << output(paramsJS,"colormatrix.browser:[funcName]")
310 changes: 310 additions & 0 deletions html/admin/color_matrix.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
<!DOCTYPE html>
<html>
<head>
<title>Color Matrix Editor</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<style>
.cell {
display: inline-block;
border-style: solid;
border-width: 1px;
width: 17%;
text-align: center;
vertical-align: center;
}

.cell input {
margin: auto;
display: block;
text-align: center;
width: 90%;
}
</style>
</head>
<body>
<input type="text" value="" id="current_matrix" readonly class='cell'>
<button onclick="copy_matrix()">Copy Matrix</button>
<form name="matrix" method='GET' action='byond://?src=\ref[src]'>
<div id="red">
<div class="cell">
<input id="rr_num" type="number" value="1" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="rr" type="range" value="1" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="rg_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="rg" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="rb_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="rb" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="ra_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="ra" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="rx_num" type="number" value="0" min="-2.0" max="2.0" disabled onchange="cellChange(event)"/>
<input id="rx" type="range" value="0" min="-2.0" max="2.0" disabled onchange="cellChange(event)"/>
</div>
</div>
<div id="green">
<div class="cell">
<input id="gr_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="gr" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="gg_num" type="number" value="1" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="gg" type="range" value="1" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="gb_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="gb" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="ga_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="ga" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="gx_num" type="number" value="0" min="-2.0" max="2.0" disabled onchange="cellChange(event)"/>
<input id="gx" type="range" value="0" min="-2.0" max="2.0" disabled onchange="cellChange(event)"/>
</div>
</div>
<div id="blue">
<div class="cell">
<input id="br_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="br" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="bg_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="bg" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="bb_num" type="number" value="1" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="bb" type="range" value="1" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="ba_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="ba" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="bx_num" type="number" value="0" min="-2.0" max="2.0" disabled onchange="cellChange(event)"/>
<input id="bx" type="range" value="0" min="-2.0" max="2.0" disabled onchange="cellChange(event)"/>
</div>
</div>
<div id="alpha">
<div class="cell">
<input id="ar_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="ar" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="ag_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="ag" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="ab_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="ab" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="aa_num" type="number" value="1" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="aa" type="range" value="1" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="ax_num" type="number" value="0" min="-2.0" max="2.0" disabled onchange="cellChange(event)"/>
<input id="ax" type="range" value="0" min="-2.0" max="2.0" disabled onchange="cellChange(event)"/>
</div>
</div>
<div id="constant">
<div class="cell">
<input id="cr_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="cr" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="cg_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="cg" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="cb_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="cb" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="ca_num" type="number" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
<input id="ca" type="range" value="0" min="-2.0" max="2.0" step="0.05" onchange="cellChange(event)"/>
</div>
<div class="cell">
<input id="cx_num" type="number" value="1" min="-2.0" max="2.0" disabled onchange="cellChange(event)"/>
<input id="cx" type="range" value="1" min="-2.0" max="2.0" disabled onchange="cellChange(event)"/>
</div>
</div>
<div id="controls">
<button id="reset" type="reset">Reset</button>
<button id="randomize" type="button">Randomize</button>
<button id="randomize_rgb" type="button">Randomize (RGB)</button>
<button id="tweak" type="button">Tweak</button>
<button id="tweak_rgb" type="button">Tweak (RGB)</button>
<input type="checkbox" id="doAnimation"> <label for="doAnimation">Animate change</label>
<input type="checkbox" id="forAll"> <label for="forAll">Affect <b>everyone</b></label>
</div>
</form>

<script type="text/javascript">
var ordering = ["rr", "rg", "rb", "ra", "gr", "gg", "gb", "ga", "br", "bg", "bb", "ba", "ar", "ag", "ab", "aa", "cr", "cg", "cb", "ca"];
window.onload = restoreFromURL(document.location.href);
var identityMatrix = [
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1,
0,0,0,0];

var cellMin = -2;
var cellMax = 2;
var tweakRange = 0.2;
var resolution = 0.05; // the smallest increment being worked with

var ref;

var setRef = function setRef(theRef) {
ref = theRef;
};

document.getElementById("reset").addEventListener("click", function() {
sendMatrix(identityMatrix);
});

document.getElementById("randomize").addEventListener("click", function() {
randomizeAllValues(cellMax - cellMin);
sendMatrix(generateMatrixList());
});

document.getElementById("randomize_rgb").addEventListener("click", function() {
randomizeAllValues(cellMax - cellMin, false, true);
sendMatrix(generateMatrixList());
});

document.getElementById("tweak").addEventListener("click", function() {
randomizeAllValues(tweakRange, true);
sendMatrix(generateMatrixList());
});

document.getElementById("tweak_rgb").addEventListener("click", function() {
randomizeAllValues(tweakRange, true, true);
sendMatrix(generateMatrixList());
});

function setMatrixFromURL(matrixListURL) {
var matrixList = matrixListURL.split(",");
for(var i=0; i<ordering.length; i++) {
var id = ordering[i];
document.getElementById(id).value = matrixList[i];
document.getElementById(id + "_num").value = matrixList[i];
}
var copyText = document.getElementById("current_matrix");
copyText.value = matrixList
}

function copy_matrix() {
var copyText = document.getElementById("current_matrix");
copyText.select();
document.execCommand("copy");
}

function randomizeAllValues(range, isAdditive, rgbOnly) {
var randVal = 0;
Array.prototype.slice.call(
document.getElementsByTagName("input")).forEach(function (el) {
var id = el.id;
// if only rgb only, only elements with "a" somewhere in their id related to alpha
if(rgbOnly && id.indexOf("a") !== -1)
return true; // because this is a function, we can't use "continue"
if(ordering.indexOf(id) !== -1) {
randVal = (Math.random()*range) - range/2;
if(isAdditive) {
randVal = Number(el.value) + randVal;
}
// round to nearest increment
randVal = (Math.ceil(randVal*(1/resolution) - 0.5)/(1/resolution)).toFixed(2);
// clamp
randVal = Math.min(Math.max(randVal, cellMin), cellMax);
el.value = randVal;
document.getElementById(id + "_num").value = randVal;
}
});
}

function generateMatrixList() {
var cellValues = [];
// get filtered input values
Array.prototype.slice.call(
document.getElementsByTagName("input")).forEach(function (el) {
var id = el.id;
if(ordering.indexOf(id) !== -1) {
cellValues[id] = el.value;
}
});
// create a list based on ordering
var list = [];
ordering.forEach(function (key) {
list.push(cellValues[key]);
});
return list;
}

function cellChange(e) {
var target = event.target ? event.target : event.srcElement;
var value = target.value;
var changeId = target.id;
if(changeId.indexOf("num") === -1) {
// a slider was changed
var linkedNum = document.getElementById(changeId + "_num");
linkedNum.value = value;
} else {
// a number field was changed
var linkedSlider = document.getElementById(changeId.slice(0, 2))
linkedSlider.value = value;
}
sendMatrix(generateMatrixList());
}


function sendMatrix(matrixList) {
var matrixData = matrixList.join(',');
var doAnimation = document.getElementById("doAnimation").checked;
var forAll = document.getElementById("forAll").checked;
var newLoc = "?src=" + ref + ";animate=" + (doAnimation ? "y" : "n") + ";matrix=" + matrixData + ";forAll=" + (forAll?"y":"n");
window.location = newLoc;

var copyText = document.getElementById("current_matrix");
copyText.value = matrixData
}

function restoreFromURL(url) {
var params = getParams(url);
if(params["src"]) {
src = params["src"];
}
if(params["animate"]) {
document.getElementById("doAnimation").checked = (params["animate"] === "y");
}
if(params["matrix"]) {
setMatrixFromURL(params["matrix"]);
}
}

function getParams(url) {
var params = [];
var paramSection = url.split("?")[1];
if(paramSection) {
var pairs = paramSection.split(";");
if(pairs) {
pairs.forEach(function (pair) {
var parts = pair.split("=");
params[parts[0]] = parts[1]
})
}
}
return params;
}

</script>
</body>
</html>

0 comments on commit ecc056d

Please sign in to comment.