diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm
index 6be76b4df87..b87878e7453 100644
--- a/code/modules/admin/holder2.dm
+++ b/code/modules/admin/holder2.dm
@@ -32,7 +32,7 @@ GLOBAL_PROTECT(href_token)
var/deadmined
- var/datum/filter_editor/filteriffic
+ var/datum/filter_editor/filterrific
var/datum/particle_editor/particle_test
var/datum/colorblind_tester/color_test
var/datum/plane_master_debug/plane_debug
diff --git a/code/modules/admin/view_variables/filterrific.dm b/code/modules/admin/view_variables/filterrific.dm
index f8dbd7fee43..89172c46e12 100644
--- a/code/modules/admin/view_variables/filterrific.dm
+++ b/code/modules/admin/view_variables/filterrific.dm
@@ -10,7 +10,7 @@
/datum/filter_editor/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
- ui = new(user, src, "Filteriffic")
+ ui = new(user, src, "Filterrific")
ui.open()
/datum/filter_editor/ui_static_data(mob/user)
@@ -21,7 +21,14 @@
/datum/filter_editor/ui_data()
var/list/data = list()
data["target_name"] = target.name
- data["target_filter_data"] = target.filter_data
+ var/list/target_filter_data = list()
+ for (var/list/filter_info as anything in target.filter_data)
+ filter_info = deep_copy_list(filter_info)
+ if (filter_info["transform"])
+ var/matrix/filter_transform = filter_info["transform"]
+ filter_info["transform"] = list("a" = filter_transform.a, "b" = filter_transform.b, "c" = filter_transform.c, "d" = filter_transform.d, "e" = filter_transform.e, "f" = filter_transform.f)
+ target_filter_data += list(filter_info)
+ data["target_filter_data"] = target_filter_data
return data
/datum/filter_editor/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
@@ -59,7 +66,7 @@
target.modify_filter(params["name"], params["new_data"])
. = TRUE
if("modify_color_value")
- var/new_color = input(usr, "Pick new filter color", "Filteriffic Colors!") as color|null
+ var/new_color = input(usr, "Pick new filter color", "Filterrific Colors!") as color|null
if(new_color)
target.transition_filter(params["name"], list("color" = new_color), 4)
. = TRUE
@@ -68,6 +75,16 @@
if(new_icon)
target.modify_filter(params["name"], list("icon" = new_icon))
. = TRUE
+ if("modify_transform_value")
+ var/list/filter_info = target.get_filter_data(params["name"])
+ if (!filter_info)
+ return
+ var/matrix/new_transform = matrix(filter_info[params["field_name"]])
+ if (!(params["transform_key"] in list("a", "b", "c", "d", "e", "f")))
+ return
+ new_transform.vars[params["transform_key"]] = text2num(params["transform_value"])
+ target.modify_filter(params["name"], list(params["field_name"] = new_transform))
+ . = TRUE
if("mass_apply")
if(!check_rights_for(usr.client, R_FUN))
to_chat(usr, span_userdanger("Stay in your lane, jannie."))
diff --git a/code/modules/admin/view_variables/nobody_wants_to_learn_matrix_math.dm b/code/modules/admin/view_variables/nobody_wants_to_learn_matrix_math.dm
index 4d057383284..db887d8053e 100644
--- a/code/modules/admin/view_variables/nobody_wants_to_learn_matrix_math.dm
+++ b/code/modules/admin/view_variables/nobody_wants_to_learn_matrix_math.dm
@@ -4,7 +4,7 @@
*
* More than just a completely true statement, this datum is created as a tgui interface
* allowing you to modify each vector until you know what you're doing.
- * Much like filteriffic, 'nobody wants to learn matrix math' is meant for developers like you and I
+ * Much like filterrific, 'nobody wants to learn matrix math' is meant for developers like you and I
* to implement interesting matrix transformations without the hassle if needing to know... algebra? Damn, i'm stupid.
*/
/datum/nobody_wants_to_learn_matrix_math
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index d9c1389c0cf..19bfebc0fe2 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -1126,8 +1126,8 @@ GLOBAL_LIST_INIT(unrecommended_builds, list(
/client/proc/open_filter_editor(atom/in_atom)
if(holder)
- holder.filteriffic = new /datum/filter_editor(in_atom)
- holder.filteriffic.ui_interact(mob)
+ holder.filterrific = new /datum/filter_editor(in_atom)
+ holder.filterrific.ui_interact(mob)
///opens the particle editor UI for the in_atom object for this client
/client/proc/open_particle_editor(atom/movable/in_atom)
diff --git a/tgui/packages/tgui/interfaces/Filteriffic.jsx b/tgui/packages/tgui/interfaces/Filterrific.jsx
similarity index 65%
rename from tgui/packages/tgui/interfaces/Filteriffic.jsx
rename to tgui/packages/tgui/interfaces/Filterrific.jsx
index a82fecf8638..b1b28373853 100644
--- a/tgui/packages/tgui/interfaces/Filteriffic.jsx
+++ b/tgui/packages/tgui/interfaces/Filterrific.jsx
@@ -11,6 +11,7 @@ import {
NoticeBox,
NumberInput,
Section,
+ Stack,
} from 'tgui-core/components';
import { numberOfDecimalDigits, toFixed } from 'tgui-core/math';
@@ -193,6 +194,159 @@ const FilterOptionsEntry = (props) => {
);
};
+const FilterTransformEntry = (props) => {
+ const { value, name, filterName } = props;
+ const { act } = useBackend();
+
+ return (
+ <>
+
+ {['a', 'b', 'c'].map((letter_key) => (
+
+
+ {letter_key}:
+
+
+ act('modify_transform_value', {
+ name: filterName,
+ field_name: name,
+ transform_key: letter_key,
+ transform_value: value,
+ })
+ }
+ />
+
+ ))}
+
+
+ {['d', 'e', 'f'].map((letter_key) => (
+
+
+ {letter_key}:
+
+
+ act('modify_transform_value', {
+ name: filterName,
+ field_name: name,
+ transform_key: letter_key,
+ transform_value: value,
+ })
+ }
+ />
+
+ ))}
+
+ >
+ );
+};
+
+const FilterMatrixEntry = (props) => {
+ const { name, value, filterName, filterType } = props;
+ const { act } = useBackend();
+ const matrix_sizes = [9, 12, 16, 20];
+ const resize_matrix = (matrix, size) => {
+ let identity = [1, 0, 0, 0, 1, 0, 0, 0, 1];
+ switch (size) {
+ case 12:
+ identity = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0];
+ break;
+ case 16:
+ identity = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
+ break;
+ case 20:
+ identity = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0];
+ break;
+ }
+ if (matrix === null || matrix === undefined) return identity;
+
+ for (let i = 0; i < Math.min(size, matrix.length); i++) {
+ if (matrix.length === 9)
+ identity[i + Math.floor(i / 3)] = matrix[i]; // Account for skipped constants
+ else identity[i] = matrix[i];
+ }
+ return identity;
+ };
+
+ let matrix = value;
+
+ if (value === null || value === undefined) {
+ matrix = resize_matrix(value, 9);
+ }
+
+ const processed_matrix = [];
+ const row_width = matrix.length > 9 ? 4 : 3;
+ for (let i = 0; i < (matrix.length > 9 ? matrix.length / 4 : 3); i++) {
+ const new_row = [];
+ for (let j = 0; j < row_width; j++) {
+ new_row.push(matrix[i * row_width + j]);
+ }
+ processed_matrix.push(new_row);
+ }
+
+ return (
+
+ `${size} elements`)}
+ onSelected={(option) =>
+ matrix.length === parseInt(option.split(' '))
+ ? null
+ : act('modify_filter_value', {
+ name: filterName,
+ new_data: {
+ [name]: resize_matrix(matrix, parseInt(option.split(' '))),
+ },
+ })
+ }
+ />
+
+ {processed_matrix.map((matrix_row, row_index) => (
+
+
+ {matrix_row.map((matrix_elem, elem_index) => (
+
+ {
+ matrix[row_index * row_width + elem_index] = value;
+ act('transition_filter_value', {
+ name: filterName,
+ new_data: {
+ [name]: matrix,
+ },
+ });
+ }}
+ />
+
+ ))}
+
+
+ ))}
+
+
+ );
+};
+
const FilterDataEntry = (props) => {
const { name, value, hasValue, filterName, filterType } = props;
@@ -204,6 +358,8 @@ const FilterDataEntry = (props) => {
icon: ,
flags: ,
options: ,
+ transform: ,
+ matrix: ,
plug: 'Not Implemented',
};
@@ -214,7 +370,7 @@ const FilterDataEntry = (props) => {
render_source: 'string',
flags: 'flags',
size: 'float',
- color: { default: 'color', color: 'plug' },
+ color: { default: 'color', color: 'matrix' },
offset: 'float',
radius: 'int',
falloff: 'float',
@@ -225,7 +381,7 @@ const FilterDataEntry = (props) => {
repeat: 'int',
space: 'options',
blend_mode: 'options',
- transform: 'plug',
+ transform: 'transform',
};
let filterInputType = filterEntryMap[name];
@@ -315,7 +471,7 @@ const FilterEntry = (props) => {
);
};
-export const Filteriffic = (props) => {
+export const Filterrific = (props) => {
const { act, data } = useBackend();
const name = data.target_name || 'Unknown Object';
const filters = data.target_filter_data || {};
@@ -325,7 +481,7 @@ export const Filteriffic = (props) => {
const [hiddenSecret, setHiddenSecret] = useState(false);
return (
-
+
DO NOT MESS WITH EXISTING FILTERS IF YOU DO NOT KNOW THE CONSEQUENCES.