Pixel-Composer/scripts/__tiler_rule/__tiler_rule.gml

522 lines
17 KiB
Plaintext
Raw Normal View History

function tiler_rule_replacement(_index) constructor {
index = _index;
}
function tiler_rule() constructor {
name = "rule";
open = false;
active = true;
range = 1;
size = [ 1, 1 ];
2024-11-01 05:57:42 +01:00
scanSize = [ 1, 1 ];
probability = 100;
_probability = 1;
selection_rules = array_create(9, -1);
selection_rules[4] = -10000;
replacements = [];
sl_prop = new textBox(TEXTBOX_INPUT.number, function(v) /*=>*/ { probability = v; })
.setSlideRange(0, 100);
sl_prop.suffix = "%";
sl_prop.font = f_p3;
__aut = [];
__sel = [];
static shader_select = function(tileset) {
2024-11-01 05:57:42 +01:00
var _sw = size[0] + range * 2;
var _sh = size[1] + range * 2;
2024-11-01 05:57:42 +01:00
selection_rules = array_verify_ext(selection_rules, _sw * _sh, function() /*=>*/ {return -1} );
__aut = [];
__sel = [];
var autI = [];
2024-11-01 05:57:42 +01:00
var minX = 999, maxX = 0;
var minY = 999, maxY = 0;
// print($"{size}, {range}")
for( var i = 0, n = array_length(selection_rules); i < n; i++ ) {
2024-11-01 05:57:42 +01:00
var _s = selection_rules[i];
var _r = floor(i / _sw);
var _c = i % _sw;
if(_s != -1 && (_r < range || _r >= size[1] + range || _c < range || _c >= size[0] + range)) {
minX = min(minX, _c);
maxX = max(maxX, _c);
minY = min(minY, _r);
maxY = max(maxY, _r);
// print($"{_s}: {_c}, {_r}");
}
2024-11-01 05:57:42 +01:00
if(is_array(_s)) {
var _auI = _s[1];
array_push(__sel, 10000 + _auI);
2024-11-01 05:57:42 +01:00
array_push(autI, _auI);
} else
2024-11-01 05:57:42 +01:00
array_push(__sel, _s);
}
2024-11-02 05:10:04 +01:00
scanSize = minX < maxX? [ max(1, maxX - minX + 1), max(1, maxY - minY + 1) ] : size;
2024-11-01 05:57:42 +01:00
// print($"{maxX}, {minX} | {maxY}, {minY} | {scanSize}");
autI = array_unique(autI);
for( var i = 0, n = array_length(autI); i < n; i++ ) {
var _i = autI[i];
2024-11-02 05:10:04 +01:00
var _t = array_safe_get(tileset.autoterrain, _i, noone);
if(_t == noone) continue;
var _ind = 64 * i;
__aut[_ind] = array_length(_t.index);
for( var j = 0, m = array_length(_t.index); j < m; j++ )
__aut[_ind + 1 + j] = _t.index[j];
}
2024-11-01 05:57:42 +01:00
var _selu = array_unique(__sel);
shader_set_f("selection", _selu);
shader_set_i("selectionSize", array_length(_selu));
shader_set_f("selectionGroup", __aut);
}
static shader_submit = function(tileset) {
shader_set_i("range", range);
2024-11-01 05:57:42 +01:00
shader_set_f("size", size);
shader_set_f("scanSize", scanSize);
shader_set_f("probability", probability / 100);
shader_set_f("selection", __sel);
shader_set_f("selectionGroup", __aut);
var rep = [];
var rsz = size[0] * size[1];
for( var i = 0, n = array_length(replacements); i < n; i++ ) {
var _r = replacements[i];
_r.index = array_verify_ext(_r.index, rsz, function() /*=>*/ {return -1} );
array_append(rep, _r.index);
}
2024-11-01 05:57:42 +01:00
// print($"selection: {__sel}");
// print($"selectGroup: {__aut}\n");
shader_set_f("replacements", rep);
shader_set_i("replacementCount", array_length(replacements));
}
static deserialize = function(_struct) {
name = struct_try_get(_struct, "name", name);
size = struct_try_get(_struct, "size", size);
range = struct_try_get(_struct, "range", range);
active = struct_try_get(_struct, "active", active);
selection_rules = struct_try_get(_struct, "selection_rules", selection_rules);
probability = struct_try_get(_struct, "probability", probability);
var _rep = struct_try_get(_struct, "replacements", noone);
if(_rep != noone) {
for( var i = 0, n = array_length(_rep); i < n; i++ )
replacements[i] = new tiler_rule_replacement(_rep[i].index);
}
return self;
}
}
function Tileset_Rule(_tileset) : Inspector_Custom_Renderer(noone, noone) constructor {
name = "Tile Riles";
tileset = _tileset;
ruleTiles = [];
rule_dragging = noone;
rule_selector_h = 0;
renaming = noone;
rename_text = "";
tb_rename = new textBox(TEXTBOX_INPUT.text, function(_name) {
if(renaming == noone) return;
renaming.name = _name;
renaming = noone;
});
tb_rename.font = f_p2;
tb_rename.hide = true;
2024-11-01 05:57:42 +01:00
temp_surface = [ noone, noone, noone ];
function setTileset(_tileset) { tileset = _tileset; return self; }
function draw(_x, _y, _w, _m, _hover, _focus, _panel = noone) {
var _yy = _y;
var _h = 0;
2024-11-01 05:57:42 +01:00
if(tileset == noone) return _h;
var _tileSet = tileset.texture;
var _tileSiz = tileset.tileSize;
if(!is_surface(_tileSet)) return _h;
var _tdim = surface_get_dimension(_tileSet);
var _tileAmo = [ floor(_tdim[0] / _tileSiz[0]), floor(_tdim[1] / _tileSiz[1]) ];
var bx = _x;
var by = _yy;
var bs = ui(24);
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover, "New rule", THEME.add_16, 0, COLORS._main_value_positive) == 2) {
var _new_rl = new tiler_rule();
_new_rl.name = $"rule {array_length(ruleTiles)}"
_new_rl.open = true;
array_push(ruleTiles, _new_rl);
tileset.triggerRender();
}
_h += bs + ui(4);
_yy += bs + ui(4);
var _pd = ui(4);
var _ah = _pd * 2;
var del = -1;
var rl_iHover = 0;
draw_sprite_stretched_ext(THEME.ui_panel_bg, 1, _x, _yy, _w, rule_selector_h, COLORS.node_composite_bg_blend, 1);
_yy += _pd;
for( var i = 0, n = array_length(ruleTiles); i < n; i++ ) {
var _hg = ui(32);
var _rl = ruleTiles[i];
var _pw = ui(24);
var _ph = ui(24);
var _px = _x + ui(8);
var _py = _yy + ui(4);
if(_m[1] > _yy) rl_iHover = i;
var _prin = array_safe_get(_rl.replacements, 0, undefined);
if(_prin == undefined)
draw_sprite_stretched_ext(THEME.ui_panel, 1, _px, _py, _pw, _ph, COLORS._main_icon);
else if(is(_prin, tiler_rule_replacement)) {
var _ind = array_safe_get(_prin.index, 0);
2024-11-01 05:57:42 +01:00
tileset.drawTile(_ind, _px, _py, _pw, _ph);
}
var _tx = _px + _pw + ui(8);
var _hov = _hover && point_in_rectangle(_m[0], _m[1], _x, _yy, _x + _w, _yy + _hg - 1);
if(renaming == _rl) {
tb_rename.setFocusHover(_focus, _hover);
tb_rename.draw(_tx, _yy, _w - _pw - ui(8), _hg, rename_text, _m);
} else {
var _cc = _hov? COLORS._main_text : COLORS._main_text_sub;
if(rule_dragging == _rl) _cc = COLORS._main_accent;
draw_set_text(f_p2, fa_left, fa_center, _cc);
draw_text_add(_tx, _yy + _hg / 2, _rl.name);
var bs = ui(24);
var bx = _w - bs - ui(4);
var by = _yy + _hg / 2 - bs / 2;
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover, "", THEME.minus_16, 0, _hov? COLORS._main_value_negative : COLORS._main_icon) == 2)
del = i;
}
if(_hov && _m[0] < _x + _w - ui(32 + 160)) {
if(_m[0] > _tx) {
2024-11-01 05:57:42 +01:00
if(DOUBLE_CLICK && _focus) {
renaming = _rl;
rename_text = _rl.name;
tb_rename._current_text = _rl.name;
tb_rename.activate();
2024-11-01 05:57:42 +01:00
} else if(mouse_press(mb_left, _focus)) {
rule_dragging = _rl;
}
} else {
draw_sprite_stretched_ext(THEME.ui_panel, 1, _px, _py, _pw, _ph, COLORS._main_accent);
if(mouse_press(mb_left, _focus))
_rl.open = !_rl.open;
}
}
var _atWid = _rl.sl_prop;
var _scw = ui(120);
var _sch = ui(20);
var _scx = _x + _w - _scw - ui(32 + 8);
var _scy = _yy + _hg / 2 - _sch / 2;
_atWid.setFocusHover(_focus, _hover);
_atWid.rx = rx;
_atWid.ry = ry;
_atWid.draw(_scx, _scy, _scw, _sch, _rl.probability, _m);
if(_rl.probability != _rl._probability) {
_rl._probability = _rl.probability;
tileset.triggerRender();
}
var _acw = ui(20);
var _ach = ui(20);
var _acx = _scx - _acw - ui(8);
var _acy = _yy + _hg / 2 - _sch / 2;
var _ahv = _hover && point_in_rectangle(_m[0], _m[1], _acx, _acy, _acx + _acw, _acy + _ach);
if(_ahv) {
TOOLTIP = "Active";
if(mouse_press(mb_left, _focus)) {
_rl.active = !_rl.active;
tileset.triggerRender();
}
}
draw_sprite_stretched_ext(THEME.checkbox_def, _ahv, _acx, _acy, _acw, _ach, c_white);
if(_rl.active) draw_sprite_stretched_ext(THEME.checkbox_def, 2, _acx, _acy, _acw, _ach, COLORS._main_accent);
_yy += _hg;
_ah += _hg;
if(_rl.open) {
_yy += ui(4);
_ah += ui(4);
var _sls = ui(28);
2024-11-01 05:57:42 +01:00
var _rep = _rl.replacements;
var _siz = _rl.size;
var _rpw = _sls * _siz[0];
var _rph = _sls * _siz[1];
var _radw = _rl.size[0] + _rl.range * 2;
var _radh = _rl.size[1] + _rl.range * 2;
var _slw = ui(16) + _radw * _sls;
var _slh = ui(16) + _radh * _sls;
var _hh0 = _slh;
2024-11-01 05:57:42 +01:00
var _dx = ui(8) + _slw + ui(16);
var _nln = (_rpw + ui(4)) * 2 > _w - _dx - ui(24);
var _sx = _x + ui(8);
if(_nln) {
_sx = _w / 2 - _slw / 2 + ui(4);
_slw = _w - ui(16);
}
draw_sprite_stretched_ext(THEME.ui_panel_bg, 1, _x + ui(8), _yy, _slw, _slh, COLORS.node_composite_bg_blend, 1);
for( var j = 0, m = array_length(_rl.selection_rules); j < m; j++ ) {
var _rl_sel = _rl.selection_rules[j];
var _rl_col = j % _radw;
var _rl_row = floor(j / _radw);
var _cen = _rl_col >= _rl.range && _rl_col < _rl.range + _rl.size[0] &&
_rl_row >= _rl.range && _rl_row < _rl.range + _rl.size[1];
2024-11-01 05:57:42 +01:00
var _rl_x = _sx + ui(8) + _rl_col * _sls;
var _rl_y = _yy + ui(8) + _rl_row * _sls;
var _rl_selected = tileset.object_selecting == _rl && tileset.object_select_id == j;
var _rl_hov = _hover && point_in_rectangle(_m[0], _m[1], _rl_x, _rl_y, _rl_x + _sls - 1, _rl_y + _sls - 1);
var _pad = ui(2);
var _cc = _rl_selected? COLORS._main_accent : COLORS._main_icon;
var _aa = _rl_selected? 1 : .5 + _rl_hov * .5;
if(is_array(_rl_sel)) {
2024-11-02 05:10:04 +01:00
var _autt = array_safe_get(tileset.autoterrain, _rl_sel[1], noone);
tileset.drawTile(_autt == noone? 0 : _autt.index[0], _rl_x + ui(2), _rl_y + ui(2), _sls - ui(4), _sls - ui(4));
draw_sprite_uniform(THEME.circle, 0, _rl_x + _sls - ui(8), _rl_y + _sls - ui(8), 1, COLORS._main_accent);
} else if (_rl_sel == -10000) {
draw_sprite_uniform(THEME.cross, 0, _rl_x + _sls / 2, _rl_y + _sls / 2, 1, _cc, _aa);
} else if(_rl_sel != -1) {
2024-11-01 05:57:42 +01:00
tileset.drawTile(_rl_sel, _rl_x + ui(2), _rl_y + ui(2), _sls - ui(4), _sls - ui(4));
} else if(!_cen) _pad = ui(10);
draw_sprite_stretched_ext(THEME.ui_panel, 1 + _cen, _rl_x + _pad, _rl_y + _pad, _sls - _pad * 2, _sls - _pad * 2, _cc, _aa);
if(_rl_hov) {
if(mouse_press(mb_left, _focus)) {
tileset.object_selecting = _rl_selected? noone : _rl;
tileset.object_select_id = j;
tileset.triggerRender();
}
if(mouse_press(mb_right, _focus)) {
_rl.selection_rules[j] = -1;
tileset.object_selecting = noone;
tileset.object_select_id = noone;
tileset.triggerRender();
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2024-11-01 05:57:42 +01:00
var _rx, _rpww;
2024-11-01 05:57:42 +01:00
if(_nln) {
_rx = _x + ui(8);
_rpww = _w - ui(16);
_hh0 = 0;
_yy += _slh + ui(8);
_ah += _slh + ui(8);
2024-11-01 05:57:42 +01:00
draw_sprite_uniform(THEME.arrow, 3, _x + _w / 2, _yy + ui(2), 1, COLORS._main_icon, 1);
2024-11-01 05:57:42 +01:00
_yy += ui(8);
_ah += ui(8);
} else {
2024-11-01 05:57:42 +01:00
_rx = _x + _dx;
_rpww = _w - _dx - ui(8);
draw_sprite_uniform(THEME.arrow, 0, _rx - ui(8), _yy + _slh / 2, 1, COLORS._main_icon, 1);
}
2024-11-01 05:57:42 +01:00
var _col = max(1, floor((_rpww - ui(16)) / (_rpw + ui(4))));
var _row = ceil((array_length(_rep) + 1) / _col);
2024-11-01 05:57:42 +01:00
var _rphh = ui(16) + _row * _rph;
2024-11-01 05:57:42 +01:00
draw_sprite_stretched_ext(THEME.ui_panel_bg, 1, _rx, _yy, _rpww, max(_hh0, _rphh), COLORS.node_composite_bg_blend, 1);
var del_rep = -1;
for( var j = 0, m = array_length(_rep) + 1; j < m; j++ ) {
var _rcl = j % _col;
var _rrw = floor(j / _col);
var _rpx = _rx + ui(8) + _rcl * (_rpw + ui(4));
var _rpy = _yy + ui(8) + _rrw * _rph;
var _rl_hov = _hover && point_in_rectangle(_m[0], _m[1], _rpx, _rpy, _rpx + _rpw, _rpy + _rph);
if(j == 0) {
var _cc = _rl_hov? COLORS._main_value_positive : COLORS._main_icon;
draw_sprite_uniform(THEME.add_16, 0, _rpx + _rpw / 2, _rpy + _rph / 2, 1, _cc);
if(_rl_hov && mouse_press(mb_left, _focus)) {
var _new_rep = new tiler_rule_replacement([-1]);
array_push(_rl.replacements, _new_rep);
tileset.object_selecting = _new_rep;
tileset.object_select_id = _rl;
}
continue;
}
var _replace = _rep[j - 1];
var _repIndex = _replace.index;
if(!is_array(_repIndex)) continue;
for( var k = 0, q = array_length(_repIndex); k < q; k++ ) {
var _repBlockCol = k % _siz[0];
var _repBlockRow = floor(k / _siz[0]);
var _rpbx = _rpx + _repBlockCol * _sls;
var _rpby = _rpy + _repBlockRow * _sls;
2024-11-01 05:57:42 +01:00
if(_replace.index[k] != -1) tileset.drawTile(_replace.index[k], _rpbx, _rpby, _sls, _sls);
}
var _rl_selected = tileset.object_selecting == _replace;
var _cc = _rl_selected? COLORS._main_accent : COLORS._main_icon;
var _aa = _rl_selected? 1 : .5 + _rl_hov * .5;
draw_sprite_stretched_ext(THEME.ui_panel, 1, _rpx, _rpy, _rpw, _rph, _cc, _aa);
if(_rl_hov) {
if(mouse_press(mb_left, _focus)) {
tileset.object_selecting = tileset.object_selecting == _replace? noone : _replace;
tileset.object_select_id = _rl;
tileset.triggerRender();
}
2024-11-01 05:57:42 +01:00
if(mouse_press(mb_right, _focus))
del_rep = j - 1;
}
}
if(del_rep != -1) {
array_delete(_rep, del_rep, 1);
tileset.triggerRender();
}
2024-11-01 05:57:42 +01:00
_yy += max(_hh0, _rphh) + ui(8);
_ah += max(_hh0, _rphh) + ui(8);
}
}
if(rule_dragging != noone) {
2024-11-01 05:57:42 +01:00
array_remove(ruleTiles, rule_dragging);
array_insert(ruleTiles, rl_iHover, rule_dragging);
if(mouse_release(mb_left)) {
rule_dragging = noone;
tileset.triggerRender();
}
}
if(del != -1) {
2024-11-01 05:57:42 +01:00
array_delete(ruleTiles, del, 1);
tileset.triggerRender();
}
rule_selector_h = max(ui(12), _ah);
return _h + _ah;
}
2024-11-01 05:57:42 +01:00
function apply(_tilemap, _seed) {
var _mapSize = surface_get_dimension(_tilemap);
temp_surface[0] = surface_verify(temp_surface[0], _mapSize[0], _mapSize[1], surface_rgba16float);
temp_surface[1] = surface_verify(temp_surface[1], _mapSize[0], _mapSize[1], surface_rgba16float);
temp_surface[2] = surface_verify(temp_surface[2], _mapSize[0], _mapSize[1], surface_r16float);
var bg = 0;
2024-11-01 05:57:42 +01:00
surface_set_shader(temp_surface[1], noone, true, BLEND.over);
draw_surface(_tilemap, 0, 0);
surface_reset_shader();
for( var i = 0, n = array_length(ruleTiles); i < n; i++ ) {
var _rule = ruleTiles[i];
if(!_rule.active) continue;
if(array_empty(_rule.replacements)) continue;
surface_set_shader(temp_surface[2], sh_tile_rule_select, true, BLEND.over);
shader_set_2("dimension", _mapSize);
_rule.shader_select(tileset);
draw_surface(_tilemap, 0, 0);
surface_reset_shader();
surface_set_shader(temp_surface[bg], sh_tile_rule_apply, true, BLEND.over);
shader_set_2("dimension", _mapSize);
shader_set_f("seed", _seed);
shader_set_surface("group", temp_surface[2]);
_rule.shader_submit(tileset);
draw_surface(temp_surface[!bg], 0, 0);
surface_reset_shader();
bg = !bg;
}
2024-11-01 05:57:42 +01:00
surface_set_shader(_tilemap, noone, true, BLEND.over);
draw_surface(temp_surface[!bg], 0, 0);
surface_reset_shader();
return _tilemap;
}
}