2022-01-13 05:24:03 +01:00
|
|
|
enum GRADIENT_INTER {
|
|
|
|
smooth,
|
2022-11-14 03:16:15 +01:00
|
|
|
none,
|
|
|
|
hue
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
function gradientKey(time, value) constructor { #region
|
2023-02-14 05:32:32 +01:00
|
|
|
self.time = time;
|
|
|
|
self.value = value;
|
|
|
|
|
|
|
|
static clone = function() { return new gradientKey(time, value); }
|
2023-10-03 11:27:36 +02:00
|
|
|
static serialize = function() { return { time, value }; }
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
function gradientObject(color = c_black) constructor { #region
|
2023-07-28 19:41:57 +02:00
|
|
|
static GRADIENT_LIMIT = 128;
|
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
if(is_array(color)) keys = [ new gradientKey(0, color[0]), new gradientKey(1, color[1]) ];
|
|
|
|
else keys = [ new gradientKey(0, color) ];
|
2023-03-02 07:59:14 +01:00
|
|
|
type = GRADIENT_INTER.smooth;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
static clone = function() { #region
|
2023-03-02 07:59:14 +01:00
|
|
|
var g = new gradientObject();
|
2023-07-28 19:41:57 +02:00
|
|
|
for( var i = 0, n = array_length(keys); i < n; i++ )
|
2023-03-02 07:59:14 +01:00
|
|
|
g.keys[i] = keys[i].clone();
|
|
|
|
g.type = type;
|
2023-02-23 07:02:19 +01:00
|
|
|
|
2023-03-02 07:59:14 +01:00
|
|
|
return g;
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
2022-11-14 03:16:15 +01:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
static add = function(_addkey, _deleteDup = true) { #region
|
2023-07-28 19:41:57 +02:00
|
|
|
if(array_length(keys) > GRADIENT_LIMIT) return;
|
2023-03-02 07:59:14 +01:00
|
|
|
if(array_length(keys) == 0) {
|
|
|
|
array_push(keys, _addkey);
|
|
|
|
return;
|
|
|
|
}
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-03-02 07:59:14 +01:00
|
|
|
for(var i = 0; i < array_length(keys); i++) {
|
|
|
|
var _key = keys[i];
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-03-02 07:59:14 +01:00
|
|
|
if(_key.time == _addkey.time) {
|
|
|
|
if(_deleteDup)
|
|
|
|
_key.value = _addkey.value;
|
|
|
|
return;
|
|
|
|
} else if(_key.time > _addkey.time) {
|
|
|
|
array_insert(keys, i, _addkey);
|
|
|
|
return;
|
|
|
|
}
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
2023-03-02 07:59:14 +01:00
|
|
|
|
|
|
|
array_push(keys, _addkey);
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
static eval = function(position) { #region
|
2023-11-30 08:55:33 +01:00
|
|
|
var _len = array_length(keys);
|
|
|
|
if(_len == 0) return c_black;
|
|
|
|
if(_len == 1) return keys[0].value;
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2023-11-30 08:55:33 +01:00
|
|
|
if(position <= keys[0].time) return keys[0].value;
|
|
|
|
if(position >= keys[_len - 1].time) return keys[_len - 1].value;
|
|
|
|
|
|
|
|
var _pkey = keys[0];
|
|
|
|
|
|
|
|
for(var i = 1; i < _len; i++) {
|
2023-03-02 07:59:14 +01:00
|
|
|
var _key = keys[i];
|
|
|
|
if(_key.time < position) continue;
|
|
|
|
if(_key.time == position) return keys[i].value;
|
2023-11-30 08:55:33 +01:00
|
|
|
|
2023-03-02 07:59:14 +01:00
|
|
|
if(type == GRADIENT_INTER.smooth) {
|
2023-11-30 08:55:33 +01:00
|
|
|
var rat = (position - _pkey.time) / (_key.time - _pkey.time);
|
|
|
|
return merge_color(_pkey.value, _key.value, rat);
|
2023-03-02 07:59:14 +01:00
|
|
|
} else if(type == GRADIENT_INTER.none) {
|
2023-11-30 08:55:33 +01:00
|
|
|
return _pkey.value;
|
2023-03-02 07:59:14 +01:00
|
|
|
}
|
2023-11-30 08:55:33 +01:00
|
|
|
|
|
|
|
_pkey = _key;
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
2023-03-02 07:59:14 +01:00
|
|
|
|
|
|
|
return keys[array_length(keys) - 1].value; //after last color
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
static draw = function(_x, _y, _w, _h, _a = 1) { #region
|
2023-03-02 07:59:14 +01:00
|
|
|
var uniform_grad_blend = shader_get_uniform(sh_gradient_display, "gradient_blend");
|
|
|
|
var uniform_grad = shader_get_uniform(sh_gradient_display, "gradient_color");
|
|
|
|
var uniform_grad_time = shader_get_uniform(sh_gradient_display, "gradient_time");
|
|
|
|
var uniform_grad_key = shader_get_uniform(sh_gradient_display, "gradient_keys");
|
|
|
|
|
|
|
|
var _grad_color = [];
|
|
|
|
var _grad_time = [];
|
2023-07-28 19:41:57 +02:00
|
|
|
|
|
|
|
var len = min(128, array_length(keys));
|
|
|
|
|
|
|
|
for(var i = 0; i < len; i++) {
|
2023-03-02 07:59:14 +01:00
|
|
|
if(keys[i].value == undefined) return;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-03-02 07:59:14 +01:00
|
|
|
_grad_color[i * 4 + 0] = color_get_red(keys[i].value) / 255;
|
|
|
|
_grad_color[i * 4 + 1] = color_get_green(keys[i].value) / 255;
|
|
|
|
_grad_color[i * 4 + 2] = color_get_blue(keys[i].value) / 255;
|
|
|
|
_grad_color[i * 4 + 3] = 1;
|
|
|
|
_grad_time[i] = keys[i].time;
|
|
|
|
}
|
|
|
|
|
2023-07-28 19:41:57 +02:00
|
|
|
if(len == 0) {
|
2023-03-26 07:13:36 +02:00
|
|
|
draw_sprite_stretched_ext(s_fx_pixel, 0, _x, _y, _w, _h, c_white, _a)
|
2023-03-02 07:59:14 +01:00
|
|
|
} else {
|
|
|
|
shader_set(sh_gradient_display);
|
|
|
|
shader_set_uniform_i(uniform_grad_blend, type);
|
2023-07-28 19:41:57 +02:00
|
|
|
shader_set_uniform_f_array_safe(uniform_grad, _grad_color, GRADIENT_LIMIT * 4);
|
2023-03-02 07:59:14 +01:00
|
|
|
shader_set_uniform_f_array_safe(uniform_grad_time, _grad_time);
|
2023-07-28 19:41:57 +02:00
|
|
|
shader_set_uniform_i(uniform_grad_key, len);
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2023-03-26 07:13:36 +02:00
|
|
|
draw_sprite_stretched_ext(s_fx_pixel, 0, _x, _y, _w, _h, c_white, _a)
|
2023-03-02 07:59:14 +01:00
|
|
|
shader_reset();
|
|
|
|
}
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
static toArray = function() { #region
|
2023-03-02 07:59:14 +01:00
|
|
|
var _grad_color = [], _grad_time = [];
|
2023-10-03 11:27:36 +02:00
|
|
|
|
2023-03-02 07:59:14 +01:00
|
|
|
for(var i = 0; i < array_length(keys); i++) {
|
|
|
|
if(is_undefined(keys[i].value)) continue;
|
2023-10-03 11:27:36 +02:00
|
|
|
|
2023-03-02 07:59:14 +01:00
|
|
|
_grad_color[i * 4 + 0] = color_get_red(keys[i].value) / 255;
|
|
|
|
_grad_color[i * 4 + 1] = color_get_green(keys[i].value) / 255;
|
|
|
|
_grad_color[i * 4 + 2] = color_get_blue(keys[i].value) / 255;
|
|
|
|
_grad_color[i * 4 + 3] = 1;
|
2023-03-08 12:14:01 +01:00
|
|
|
_grad_time[i] = keys[i].time;
|
2023-03-02 07:59:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return [ _grad_color, _grad_time ];
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
static lerpTo = function(target, amount) { #region
|
2023-07-11 14:18:23 +02:00
|
|
|
var grad = new gradientObject();
|
|
|
|
grad.keys = [];
|
|
|
|
grad.type = type;
|
|
|
|
|
|
|
|
var key_count = ceil(lerp(array_length(keys), array_length(target.keys), amount));
|
|
|
|
|
|
|
|
for( var i = 0; i < key_count; i++ ) {
|
|
|
|
var rat = i / (key_count - 1);
|
|
|
|
|
|
|
|
var kf = keys[rat * (array_length(keys) - 1)];
|
|
|
|
var kt = target.keys[rat * (array_length(target.keys) - 1)];
|
|
|
|
|
|
|
|
var time = lerp(kf.time, kt.time, amount);
|
|
|
|
var value = merge_color(eval(time), target.eval(time), amount);
|
|
|
|
|
|
|
|
grad.keys[i] = new gradientKey(time, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return grad;
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
2023-07-11 14:18:23 +02:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
static shader_submit = function() { #region
|
2023-09-27 14:55:21 +02:00
|
|
|
var _grad = toArray();
|
|
|
|
var _grad_color = _grad[0];
|
|
|
|
var _grad_time = _grad[1];
|
|
|
|
|
|
|
|
shader_set_i("gradient_blend", type);
|
|
|
|
shader_set_f("gradient_color", _grad_color);
|
|
|
|
shader_set_f("gradient_time", _grad_time);
|
|
|
|
shader_set_i("gradient_keys", array_length(keys));
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
2023-09-27 14:55:21 +02:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
static clone = function() { #region
|
2023-07-11 14:18:23 +02:00
|
|
|
var g = new gradientObject();
|
|
|
|
g.keys = [];
|
|
|
|
g.type = type;
|
|
|
|
|
2023-07-25 20:12:40 +02:00
|
|
|
for( var i = 0, n = array_length(keys); i < n; i++ )
|
2023-07-11 14:18:23 +02:00
|
|
|
g.keys[i] = keys[i].clone();
|
|
|
|
|
|
|
|
return g;
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
2023-07-11 14:18:23 +02:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
static serialize = function() { #region
|
2023-10-03 11:27:36 +02:00
|
|
|
var s = { type: type };
|
2023-07-11 14:18:23 +02:00
|
|
|
s.keys = [];
|
2023-07-25 20:12:40 +02:00
|
|
|
for( var i = 0, n = array_length(keys); i < n; i++ )
|
2023-07-11 14:18:23 +02:00
|
|
|
s.keys[i] = keys[i].serialize();
|
|
|
|
|
|
|
|
return json_stringify(s, false);
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
static deserialize = function(str) { #region
|
2023-04-22 16:23:51 +02:00
|
|
|
var s;
|
|
|
|
|
|
|
|
if(is_string(str))
|
|
|
|
s = json_try_parse(str);
|
|
|
|
else if(is_struct(str))
|
|
|
|
s = str;
|
2023-06-13 14:42:06 +02:00
|
|
|
else if(is_array(str)) {
|
2023-04-22 16:23:51 +02:00
|
|
|
keys = [];
|
2023-07-25 20:12:40 +02:00
|
|
|
for( var i = 0, n = array_length(str); i < n; i++ )
|
2023-06-13 14:42:06 +02:00
|
|
|
keys[i] = new gradientKey(str[i].time, str[i].value);
|
2023-04-22 16:23:51 +02:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2023-10-03 11:27:36 +02:00
|
|
|
type = struct_try_get(s, "type");
|
|
|
|
keys = array_create(array_length(s.keys));
|
|
|
|
for( var i = 0, n = array_length(s.keys); i < n; i++ ) {
|
|
|
|
var _time = real(s.keys[i].time);
|
|
|
|
var _value = real(s.keys[i].value);
|
|
|
|
|
|
|
|
keys[i] = new gradientKey(_time, _value);
|
|
|
|
}
|
2023-03-02 07:59:14 +01:00
|
|
|
|
|
|
|
return self;
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
|
|
|
} #endregion
|
2023-03-28 06:58:28 +02:00
|
|
|
|
2023-10-16 12:54:20 +02:00
|
|
|
function loadGradient(path) { #region
|
2023-03-28 06:58:28 +02:00
|
|
|
if(path == "") return noone;
|
2023-12-08 03:50:09 +01:00
|
|
|
if(!file_exists_empty(path)) return noone;
|
2023-03-28 06:58:28 +02:00
|
|
|
|
|
|
|
var grad = new gradientObject();
|
|
|
|
grad.keys = [];
|
|
|
|
|
|
|
|
var _t = file_text_open_read(path);
|
|
|
|
while(!file_text_eof(_t)) {
|
2023-05-30 11:09:15 +02:00
|
|
|
var key = string_trim(file_text_readln(_t));
|
2023-03-28 06:58:28 +02:00
|
|
|
var _col = 0, _pos = 0;
|
|
|
|
|
|
|
|
if(string_pos(",", key)) {
|
|
|
|
var keys = string_splice(key, ",");
|
2023-05-30 11:09:15 +02:00
|
|
|
if(array_length(keys) < 2) continue;
|
2023-03-28 06:58:28 +02:00
|
|
|
|
|
|
|
_col = toNumber(keys[0]);
|
|
|
|
_pos = toNumber(keys[1]);
|
|
|
|
} else {
|
|
|
|
_col = toNumber(key);
|
|
|
|
if(file_text_eof(_t)) break;
|
|
|
|
_pos = toNumber(file_text_readln(_t));
|
|
|
|
}
|
|
|
|
|
|
|
|
array_push(grad.keys, new gradientKey(_pos, _col));
|
|
|
|
}
|
|
|
|
file_text_close(_t);
|
2023-05-30 11:09:15 +02:00
|
|
|
|
2023-03-28 06:58:28 +02:00
|
|
|
return grad;
|
2023-10-16 12:54:20 +02:00
|
|
|
} #endregion
|
|
|
|
|
|
|
|
globalvar GRADIENTS;
|
|
|
|
GRADIENTS = [];
|
|
|
|
|
2023-11-28 09:42:22 +01:00
|
|
|
function __initGradient() { #region
|
2023-10-16 12:54:20 +02:00
|
|
|
GRADIENTS = [];
|
|
|
|
|
|
|
|
var path = DIRECTORY + "Gradients/"
|
|
|
|
var file = file_find_first(path + "*", 0);
|
|
|
|
while(file != "") {
|
|
|
|
array_push(GRADIENTS, {
|
|
|
|
name: filename_name_only(file),
|
|
|
|
path: path + file,
|
|
|
|
gradient: loadGradient(path + file)
|
|
|
|
});
|
|
|
|
file = file_find_next();
|
|
|
|
}
|
|
|
|
file_find_close();
|
2023-11-28 09:42:22 +01:00
|
|
|
} #endregion
|