2024-01-30 15:04:56 +01:00
|
|
|
#region ==================================== DRAW ====================================
|
|
|
|
|
|
|
|
function draw_surface_safe(surface, _x = 0, _y = 0) { #region
|
|
|
|
INLINE
|
|
|
|
|
|
|
|
if(is_struct(surface)) {
|
|
|
|
if(is_instanceof(surface, dynaSurf)) {
|
|
|
|
surface.draw(_x, _y);
|
|
|
|
return;
|
|
|
|
} else if(is_instanceof(surface, SurfaceAtlas))
|
|
|
|
surface = surface.getSurface();
|
|
|
|
}
|
2024-06-25 08:44:08 +02:00
|
|
|
if(is_array(surface) || !surface_exists(surface)) return;
|
2024-01-30 15:04:56 +01:00
|
|
|
|
|
|
|
__channel_pre(surface);
|
|
|
|
draw_surface(surface, _x, _y);
|
|
|
|
__channel_pos(surface);
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function draw_surface_stretched_safe(surface, _x, _y, _w, _h) { #region
|
|
|
|
INLINE
|
|
|
|
|
|
|
|
if(is_struct(surface)) {
|
|
|
|
if(is_instanceof(surface, dynaSurf)) {
|
|
|
|
surface.drawStretch(_x, _y, _w, _h);
|
|
|
|
return;
|
|
|
|
} else if(is_instanceof(surface, SurfaceAtlas))
|
|
|
|
surface = surface.getSurface();
|
|
|
|
}
|
2024-06-25 08:44:08 +02:00
|
|
|
if(is_array(surface) || !surface_exists(surface)) return;
|
2024-01-30 15:04:56 +01:00
|
|
|
|
|
|
|
__channel_pre(surface);
|
|
|
|
draw_surface_stretched(surface, _x, _y, _w, _h);
|
|
|
|
__channel_pos(surface);
|
|
|
|
} #endregion
|
|
|
|
|
2024-04-14 07:58:38 +02:00
|
|
|
function draw_surface_ext_safe(surface, _x = 0, _y = 0, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
|
2024-01-30 15:04:56 +01:00
|
|
|
INLINE
|
|
|
|
|
|
|
|
if(is_struct(surface)) {
|
|
|
|
if(is_instanceof(surface, dynaSurf)) {
|
|
|
|
surface.draw(_x, _y, _xs, _ys, _rot, _col, _alpha);
|
|
|
|
return;
|
|
|
|
} else if(is_instanceof(surface, SurfaceAtlas))
|
|
|
|
surface = surface.getSurface();
|
|
|
|
}
|
|
|
|
|
2024-06-25 08:44:08 +02:00
|
|
|
if(is_array(surface) || !surface_exists(surface)) return;
|
2024-01-30 15:04:56 +01:00
|
|
|
|
|
|
|
__channel_pre(surface);
|
|
|
|
draw_surface_ext(surface, _x, _y, _xs, _ys, _rot, _col, _alpha);
|
|
|
|
__channel_pos(surface);
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function draw_surface_tiled_safe(surface, _x, _y) { #region
|
|
|
|
INLINE
|
|
|
|
|
|
|
|
if(is_struct(surface)) {
|
|
|
|
if(is_instanceof(surface, dynaSurf)) {
|
|
|
|
surface.drawTile(_x, _y);
|
|
|
|
return;
|
|
|
|
} else if(is_instanceof(surface, SurfaceAtlas))
|
|
|
|
surface = surface.getSurface();
|
|
|
|
}
|
2024-06-25 08:44:08 +02:00
|
|
|
if(is_array(surface) || !surface_exists(surface)) return;
|
2024-01-30 15:04:56 +01:00
|
|
|
|
|
|
|
__channel_pre(surface);
|
|
|
|
draw_surface_tiled(surface, _x, _y);
|
|
|
|
__channel_pos(surface);
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function draw_surface_tiled_ext_safe(surface, _x, _y, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
|
|
|
|
INLINE
|
|
|
|
|
|
|
|
if(is_struct(surface)) {
|
|
|
|
if(is_instanceof(surface, dynaSurf)) {
|
|
|
|
surface.drawTile(_x, _y, _xs, _ys, _col, _alpha);
|
|
|
|
return;
|
|
|
|
} else if(is_instanceof(surface, SurfaceAtlas))
|
|
|
|
surface = surface.getSurface();
|
|
|
|
}
|
2024-06-25 08:44:08 +02:00
|
|
|
if(is_array(surface) || !surface_exists(surface)) return;
|
2024-01-30 15:04:56 +01:00
|
|
|
|
|
|
|
var back = surface_get_target();
|
|
|
|
var bdim = surface_get_dimension(back);
|
|
|
|
|
|
|
|
shader_set(sh_draw_tile);
|
|
|
|
shader_set_f("backDimension", bdim);
|
|
|
|
shader_set_f("foreDimension", surface_get_dimension(surface));
|
|
|
|
shader_set_f("position" , [ _x, _y ]);
|
|
|
|
shader_set_f("scale" , [ _xs, _ys ]);
|
|
|
|
shader_set_f("rotation" , _rot);
|
|
|
|
|
|
|
|
draw_surface_stretched_ext(surface, 0, 0, bdim[0], bdim[1], _col, _alpha);
|
|
|
|
shader_reset();
|
|
|
|
} #endregion
|
2023-09-08 21:09:09 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function draw_surface_part_ext_safe(surface, _l, _t, _w, _h, _x, _y, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2023-10-06 11:51:11 +02:00
|
|
|
if(is_struct(surface)) {
|
|
|
|
if(is_instanceof(surface, dynaSurf)) {
|
2024-01-30 15:04:56 +01:00
|
|
|
surface.drawPart(_l, _t, _w, _h, _x, _y, _xs, _ys, _rot, _col, _alpha);
|
2023-10-06 11:51:11 +02:00
|
|
|
return;
|
|
|
|
} else if(is_instanceof(surface, SurfaceAtlas))
|
|
|
|
surface = surface.getSurface();
|
2023-09-08 21:09:09 +02:00
|
|
|
}
|
2024-06-25 08:44:08 +02:00
|
|
|
if(is_array(surface) || !surface_exists(surface)) return;
|
2023-03-19 09:17:39 +01:00
|
|
|
|
|
|
|
__channel_pre(surface);
|
2024-01-30 15:04:56 +01:00
|
|
|
draw_surface_part_ext(surface, _l, _t, _w, _h, _x, _y, _xs, _ys, _col, _alpha);
|
2023-03-19 09:17:39 +01:00
|
|
|
__channel_pos(surface);
|
2024-01-17 14:57:32 +01:00
|
|
|
} #endregion
|
2024-01-30 15:04:56 +01:00
|
|
|
|
|
|
|
#endregion ==================================== DRAW ====================================
|
2023-09-08 21:09:09 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
#region ==================================== CHECK ===================================
|
2023-09-08 21:09:09 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function is_surface(s) { #region
|
|
|
|
INLINE
|
2024-05-22 12:13:46 +02:00
|
|
|
|
|
|
|
return !is_array(s) && (
|
|
|
|
is_instanceof(s, dynaSurf) ||
|
|
|
|
is_instanceof(s, SurfaceAtlas) ||
|
|
|
|
(is_numeric(s) && s > 0 && surface_exists(s))
|
|
|
|
);
|
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
} #endregion
|
2023-09-08 21:09:09 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_verify(surf, w, h, format = surface_rgba8unorm) { #region
|
|
|
|
INLINE
|
2023-03-19 09:17:39 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!is_surface(surf)) return surface_create_valid(w, h, format);
|
|
|
|
return surface_size_to(surf, w, h, format, true);
|
|
|
|
} #endregion
|
2023-09-08 21:09:09 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_valid(surf, w, h, format = surface_rgba8unorm) { #region
|
2024-04-30 10:49:12 +02:00
|
|
|
INLINE
|
|
|
|
|
|
|
|
if(!is_surface(surf)) return false;
|
|
|
|
var _sw = surface_get_width(surf);
|
|
|
|
var _sh = surface_get_height(surf);
|
|
|
|
var _f = surface_get_format(surf);
|
2023-03-19 09:17:39 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return _sw == w && _sh == h && _f == format;
|
2024-01-17 14:57:32 +01:00
|
|
|
} #endregion
|
2023-03-19 09:17:39 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
#endregion ==================================== CHECK ====================================
|
2023-06-17 18:59:20 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
#region ==================================== GET =====================================
|
2023-06-17 18:59:20 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_get_width_safe(s, crop = true) { #region
|
|
|
|
INLINE
|
2023-04-10 20:02:59 +02:00
|
|
|
|
2024-05-22 12:13:46 +02:00
|
|
|
if(!is_surface(s)) return 1;
|
2024-01-30 15:04:56 +01:00
|
|
|
if(is_struct(s)) {
|
|
|
|
if(is_instanceof(s, dynaSurf)) return s.getWidth();
|
|
|
|
else if(is_instanceof(s, SurfaceAtlas)) return crop? surface_get_width(s.getSurface()) : s.oriSurf_w;
|
|
|
|
else return 1;
|
|
|
|
}
|
2023-04-10 20:02:59 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return surface_get_width(s);
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_get_height_safe(s, crop = true) { #region
|
|
|
|
INLINE
|
2023-03-19 09:17:39 +01:00
|
|
|
|
2024-05-22 12:13:46 +02:00
|
|
|
if(!is_surface(s)) return 1;
|
2024-01-30 15:04:56 +01:00
|
|
|
if(is_struct(s)) {
|
|
|
|
if(is_instanceof(s, dynaSurf)) return s.getHeight();
|
|
|
|
else if(is_instanceof(s, SurfaceAtlas)) return crop? surface_get_height(s.getSurface()) : s.oriSurf_h;
|
|
|
|
else return 1;
|
|
|
|
}
|
2023-03-19 09:17:39 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return surface_get_height(s);
|
|
|
|
} #endregion
|
|
|
|
|
2024-04-08 07:13:46 +02:00
|
|
|
function surface_get_format_safe(s, crop = true) { #region
|
|
|
|
INLINE
|
|
|
|
|
|
|
|
if(is_struct(s)) {
|
|
|
|
if(is_instanceof(s, dynaSurf)) return s.getFormat();
|
|
|
|
else if(is_instanceof(s, SurfaceAtlas)) return surface_get_format(s.getSurface());
|
|
|
|
else return surface_rgba8unorm;
|
|
|
|
}
|
|
|
|
|
|
|
|
return surface_get_format(s);
|
|
|
|
} #endregion
|
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_get_dimension(s) { #region
|
|
|
|
INLINE
|
2023-03-19 09:17:39 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!is_surface(s)) return [ 1, 1 ];
|
|
|
|
return [ surface_get_width_safe(s), surface_get_height_safe(s) ];
|
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_get_pixel(surface, _x, _y) { #region
|
|
|
|
INLINE
|
2023-12-15 12:56:36 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!is_surface(surface)) return;
|
|
|
|
var f = surface_get_format(surface);
|
|
|
|
var fx = floor(_x);
|
|
|
|
var fy = floor(_y);
|
|
|
|
var rx = frac(_x);
|
|
|
|
var ry = frac(_y);
|
|
|
|
var px = surface_getpixel(surface, fx, fy);
|
2023-12-15 12:56:36 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(rx == 0 && ry == 0) {
|
|
|
|
if(is_numeric(px)) return px;
|
|
|
|
return make_color_rgb(px[0] * 256, px[1] * 256, px[2] * 256);
|
|
|
|
}
|
2023-12-15 12:56:36 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var p1 = surface_getpixel(surface, fx + 1, fy + 0);
|
|
|
|
var p2 = surface_getpixel(surface, fx + 0, fy + 1);
|
|
|
|
var p3 = surface_getpixel(surface, fx + 1, fy + 1);
|
2023-09-08 21:37:36 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return merge_color(
|
|
|
|
merge_color(px, p1, rx),
|
|
|
|
merge_color(p2, p3, rx),
|
|
|
|
ry);
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
} #endregion
|
2023-09-08 21:37:36 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_get_pixel_ext(surface, _x, _y) { #region
|
|
|
|
INLINE
|
2024-04-26 13:21:25 +02:00
|
|
|
|
|
|
|
if(is_instanceof(surface, SurfaceAtlas)) surface = surface.surface.get();
|
2024-06-25 08:44:08 +02:00
|
|
|
if(is_array(surface) || !surface_exists(surface)) return 0;
|
2024-01-30 15:04:56 +01:00
|
|
|
var px = surface_getpixel_ext(surface, _x, _y);
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2024-02-01 05:26:02 +01:00
|
|
|
if(is_numeric(px)) return int64(px);
|
2024-01-30 15:04:56 +01:00
|
|
|
return round(px[0] * (255 * power(256, 0))) + round(px[1] * (255 * power(256, 1))) + round(px[2] * (255 * power(256, 2))) + round(px[3] * (255 * power(256, 3)));
|
|
|
|
} #endregion
|
2023-09-08 21:37:36 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
#endregion ==================================== GET ====================================
|
2023-11-23 13:39:35 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
#region =================================== CREATE ===================================
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_create_empty(w, h, format = surface_rgba8unorm) { #region
|
|
|
|
INLINE
|
2023-10-02 14:41:44 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var s = surface_create(w, h, format);
|
|
|
|
surface_clear(s);
|
|
|
|
return s;
|
|
|
|
} #endregion
|
2022-12-10 05:06:01 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_create_size(surface, format = surface_rgba8unorm) { #region
|
|
|
|
INLINE
|
2024-01-20 05:06:56 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return surface_create_valid(surface_get_width_safe(surface), surface_get_height_safe(surface), format);
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_create_valid(w, h, format = surface_rgba8unorm) { #region
|
|
|
|
INLINE
|
2024-01-20 05:06:56 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return surface_create_empty(surface_valid_size(w), surface_valid_size(h), format);
|
|
|
|
} #endregion
|
2024-01-20 05:06:56 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_create_from_buffer(w, h, buff, format = surface_rgba8unorm) { #region
|
|
|
|
INLINE
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(buff < 0) return;
|
|
|
|
var s = surface_create_valid(surface_valid_size(w), surface_valid_size(h), format);
|
|
|
|
buffer_set_surface(buff, s, 0);
|
|
|
|
return s;
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_from_buffer(buff) { #region
|
|
|
|
static header_length = 24;
|
2024-03-19 09:49:29 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!buffer_exists(buff)) return noone;
|
|
|
|
if(buffer_get_size(buff) < header_length) return noone;
|
2023-03-31 06:59:08 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
buffer_seek(buff, buffer_seek_start, 0);
|
|
|
|
var text = "";
|
|
|
|
repeat(4) text += chr(buffer_read(buff, buffer_u8));
|
|
|
|
if(text != "PXCS") return noone;
|
2024-01-17 14:57:32 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var w = buffer_read(buff, buffer_u16);
|
|
|
|
var h = buffer_read(buff, buffer_u16);
|
|
|
|
var format = buffer_read(buff, buffer_u8);
|
|
|
|
if(w < 1 || h < 1) return noone;
|
2024-01-17 14:57:32 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var s = surface_create(w, h, format);
|
|
|
|
buffer_set_surface(buff, s, header_length);
|
|
|
|
return s;
|
|
|
|
} #endregion
|
2023-03-31 06:59:08 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_create_from_sprite(spr) { #region
|
|
|
|
if(!sprite_exists(spr)) return noone;
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(sprite_get_number(spr) == 1)
|
|
|
|
return surface_create_from_sprite_ext(spr, 0);
|
2023-03-31 06:59:08 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var s = [];
|
|
|
|
for( var i = 0; i < sprite_get_number(spr); i++ ) {
|
|
|
|
array_push(s, surface_create_from_sprite_ext(spr, i));
|
|
|
|
}
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return s;
|
|
|
|
} #endregion
|
2023-07-14 20:34:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_create_from_sprite_ext(spr, ind, format = surface_rgba8unorm) { #region
|
|
|
|
if(!sprite_exists(spr)) return noone;
|
|
|
|
var sw = sprite_get_width(spr);
|
|
|
|
var sh = sprite_get_height(spr);
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var s = surface_create_valid(sw, sh, format);
|
|
|
|
surface_set_target(s);
|
|
|
|
BLEND_OVERRIDE;
|
|
|
|
DRAW_CLEAR
|
|
|
|
draw_sprite(spr, ind, sprite_get_xoffset(spr), sprite_get_yoffset(spr));
|
|
|
|
BLEND_NORMAL
|
|
|
|
surface_reset_target();
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return s;
|
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_size_lim(surface, width, height) { #region
|
|
|
|
var sw = surface_get_width_safe(surface);
|
|
|
|
var sh = surface_get_height_safe(surface);
|
|
|
|
if(sw <= width && sh <= height) return surface;
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var ss = min(width / sw, height / sh);
|
|
|
|
var s = surface_create(max(1, sw * ss), max(1, sh * ss));
|
|
|
|
surface_set_target(s);
|
|
|
|
DRAW_CLEAR
|
|
|
|
draw_surface_ext_safe(surface, 0, 0, ss, ss, 0, c_white, 1);
|
|
|
|
surface_reset_target();
|
|
|
|
return s;
|
|
|
|
} #endregion
|
2022-11-01 03:06:03 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_size_to(surface, width, height, format = noone, skipCheck = false) { #region
|
2024-03-31 05:36:11 +02:00
|
|
|
INLINE
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!skipCheck && !is_surface(surface)) return surface;
|
|
|
|
if(!is_numeric(width) || !is_numeric(height)) return surface;
|
|
|
|
if(width < 1 && height < 1) return surface;
|
2024-01-20 05:06:56 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(format != noone && format != surface_get_format(surface)) {
|
|
|
|
surface_free(surface);
|
|
|
|
return surface_create(width, height, format);
|
|
|
|
}
|
2023-06-24 22:12:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
width = surface_valid_size(width);
|
|
|
|
height = surface_valid_size(height);
|
2023-06-24 22:12:35 +02:00
|
|
|
|
2024-03-31 05:36:11 +02:00
|
|
|
var ww = surface_get_width(surface);
|
|
|
|
var hh = surface_get_height(surface);
|
2023-06-24 22:12:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(ww == width && hh == height) return surface;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
surface_resize(surface, width, height);
|
2024-03-31 05:36:11 +02:00
|
|
|
//surface_clear(surface);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return surface;
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_clear(surface) { #region
|
|
|
|
INLINE
|
2023-02-19 02:13:19 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!is_surface(surface)) return;
|
|
|
|
surface_set_target(surface);
|
|
|
|
DRAW_CLEAR
|
|
|
|
surface_reset_target();
|
|
|
|
} #endregion
|
2022-09-27 06:37:28 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_copy_from(dst, src, format = noone) { #region
|
|
|
|
INLINE
|
2022-09-27 06:37:28 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
surface_set_target(dst);
|
2023-03-19 09:17:39 +01:00
|
|
|
DRAW_CLEAR
|
2024-01-30 15:04:56 +01:00
|
|
|
BLEND_OVERRIDE;
|
|
|
|
draw_surface_safe(src, 0, 0);
|
2022-09-27 06:37:28 +02:00
|
|
|
BLEND_NORMAL
|
2024-01-30 15:04:56 +01:00
|
|
|
surface_reset_target();
|
|
|
|
} #endregion
|
2023-03-21 03:01:53 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_clone(surface, destination = noone, format = noone) { #region
|
|
|
|
INLINE
|
2022-09-27 06:37:28 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(is_struct(surface) && is_instanceof(surface, dynaSurf))
|
|
|
|
return surface.clone();
|
|
|
|
if(!is_surface(surface)) return noone;
|
2022-09-27 06:37:28 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
destination = surface_verify(destination, surface_get_width_safe(surface), surface_get_height_safe(surface), format == noone? surface_get_format(surface) : format);
|
2023-02-19 02:13:19 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
surface_set_target(destination);
|
|
|
|
DRAW_CLEAR
|
|
|
|
BLEND_OVERRIDE;
|
|
|
|
draw_surface_safe(surface, 0, 0);
|
|
|
|
BLEND_NORMAL
|
|
|
|
surface_reset_target();
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return destination;
|
|
|
|
} #endregion
|
2022-12-27 04:00:50 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
#endregion ==================================== CREATE ====================================
|
2023-07-14 20:34:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
#region =================================== MODIFY ===================================
|
2023-02-19 02:13:19 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_stretch(surf, _w, _h) { #region
|
|
|
|
INLINE
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!is_surface(surf)) return noone;
|
2023-02-19 02:13:19 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
_w = surface_valid_size(_w);
|
|
|
|
_h = surface_valid_size(_h);
|
2023-02-19 02:13:19 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var _surf = surface_create(_w, _h);
|
|
|
|
surface_set_target(_surf);
|
|
|
|
DRAW_CLEAR
|
|
|
|
draw_surface_stretched(surf, 0, 0, _w, _h);
|
|
|
|
surface_reset_target();
|
2023-02-19 02:13:19 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
surface_free(surf);
|
|
|
|
return _surf;
|
|
|
|
} #endregion
|
2023-02-19 02:13:19 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_mirror(surf, _h, _v) { #region
|
|
|
|
INLINE
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!is_surface(surf)) return noone;
|
|
|
|
var _surf = surface_create_size(surf);
|
2023-07-23 20:21:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
surface_set_target(_surf);
|
|
|
|
DRAW_CLEAR
|
|
|
|
|
|
|
|
var x0 = _h * surface_get_width_safe(_surf);
|
|
|
|
var y0 = _v * surface_get_height_safe(_surf);
|
|
|
|
|
|
|
|
draw_surface_ext_safe(surf, x0, y0, _h * 2 - 1, _v * 2 - 1, 0, c_white, 1);
|
|
|
|
surface_reset_target();
|
|
|
|
surface_free(surf);
|
2023-07-23 20:21:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return _surf;
|
|
|
|
} #endregion
|
2023-07-23 20:21:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_project_posterize(surf) { #region
|
|
|
|
INLINE
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!PROJECT.attributes.palette_fix) return surf;
|
|
|
|
if(!is_surface(surf)) return surf;
|
2023-07-23 20:21:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var _surf = surface_create(surface_get_width(surf), surface_get_height(surf));
|
|
|
|
|
|
|
|
surface_set_shader(_surf, sh_posterize_palette);
|
|
|
|
shader_set_f("palette", PROJECT.palettes);
|
|
|
|
shader_set_i("keys", array_length(PROJECT.attributes.palette));
|
|
|
|
shader_set_i("alpha", 1);
|
|
|
|
|
|
|
|
draw_surface(surf, 0, 0);
|
|
|
|
surface_reset_shader();
|
2023-07-23 20:21:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
surface_free(surf);
|
2023-07-23 20:21:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return _surf;
|
|
|
|
} #endregion
|
2023-07-23 20:21:35 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
#endregion ==================================== MODIFY ====================================
|
|
|
|
|
|
|
|
#region =================================== OTHERS ===================================
|
|
|
|
|
|
|
|
function surface_copy_size(dest, source, format = noone) { #region
|
|
|
|
INLINE
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!is_surface(dest)) return;
|
|
|
|
if(!is_surface(source)) return;
|
2023-02-19 02:13:19 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
surface_size_to(dest, surface_get_width_safe(source), surface_get_height_safe(source), format);
|
|
|
|
surface_set_target(dest);
|
|
|
|
DRAW_CLEAR
|
|
|
|
surface_reset_target();
|
2023-02-19 02:13:19 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
surface_copy_from(dest, source);
|
|
|
|
} #endregion
|
2023-02-19 02:13:19 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_valid_size(s) { #region
|
|
|
|
INLINE
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-04-30 10:49:12 +02:00
|
|
|
if(!is_numeric(s)) return 1;
|
2024-01-30 15:04:56 +01:00
|
|
|
if(is_infinity(s)) return 1;
|
2024-04-30 10:49:12 +02:00
|
|
|
return clamp(round(s), 1, 8192);
|
2024-01-30 15:04:56 +01:00
|
|
|
} #endregion
|
2023-02-14 13:44:46 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_array_free(arr) { #region
|
|
|
|
INLINE
|
2023-02-14 13:44:46 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!is_array(arr)) {
|
|
|
|
if(is_surface(arr)) surface_free(arr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( var i = 0, n = array_length(arr); i < n; i++ )
|
|
|
|
surface_array_free(arr[i]);
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_array_clone(arr) { #region
|
|
|
|
if(!is_array(arr)) {
|
|
|
|
if(is_surface(arr))
|
|
|
|
return surface_clone(arr);
|
|
|
|
else
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
var _arr = [];
|
|
|
|
|
|
|
|
for( var i = 0, n = array_length(arr); i < n; i++ )
|
|
|
|
_arr[i] = surface_array_clone(arr[i]);
|
|
|
|
|
|
|
|
return _arr;
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_array_serialize(arr) { #region
|
|
|
|
INLINE
|
|
|
|
|
|
|
|
var _arr = __surface_array_serialize(arr);
|
|
|
|
return json_stringify(_arr);
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function __surface_array_serialize(arr) { #region
|
|
|
|
if(!is_array(arr)) {
|
|
|
|
if(is_surface(arr)) {
|
|
|
|
var buff = buffer_create(surface_get_width_safe(arr) * surface_get_height_safe(arr) * 4, buffer_fixed, 1);
|
|
|
|
buffer_get_surface(buff, arr, 0);
|
|
|
|
var comp = buffer_compress(buff, 0, buffer_get_size(buff));
|
|
|
|
var enc = buffer_base64_encode(comp, 0, buffer_get_size(comp));
|
|
|
|
buffer_delete(buff);
|
|
|
|
return { width: surface_get_width_safe(arr), height: surface_get_height_safe(arr), buffer: enc };
|
|
|
|
} else
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
var _arr = [];
|
|
|
|
|
|
|
|
for( var i = 0, n = array_length(arr); i < n; i++ )
|
|
|
|
_arr[i] = __surface_array_serialize(arr[i]);
|
|
|
|
|
|
|
|
return _arr;
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_array_deserialize(arr, index = -1) { #region
|
|
|
|
INLINE
|
|
|
|
|
|
|
|
var _arr = json_try_parse(arr);
|
|
|
|
return index == -1? __surface_array_deserialize(_arr) : __surface_array_deserialize(_arr[index]);
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function __surface_array_deserialize(arr) { #region
|
|
|
|
if(!is_array(arr)) {
|
|
|
|
if(!is_struct(arr) || !struct_has(arr, "buffer"))
|
|
|
|
return noone;
|
|
|
|
|
|
|
|
var buff = buffer_base64_decode(arr.buffer);
|
|
|
|
buff = buffer_decompress(buff);
|
|
|
|
return surface_create_from_buffer(arr.width, arr.height, buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
var _arr = [];
|
|
|
|
|
|
|
|
for( var i = 0, n = array_length(arr); i < n; i++ )
|
|
|
|
_arr[i] = __surface_array_deserialize(arr[i]);
|
|
|
|
|
|
|
|
return _arr;
|
|
|
|
} #endregion
|
|
|
|
|
2024-04-12 11:45:21 +02:00
|
|
|
function surface_encode(surface, stringify = true) { #region
|
2024-04-26 13:21:25 +02:00
|
|
|
if(is_instanceof(surface, SurfaceAtlas)) surface = surface.surface.get();
|
2024-06-25 08:44:08 +02:00
|
|
|
if(is_array(surface) || !surface_exists(surface)) return "";
|
2024-01-30 15:04:56 +01:00
|
|
|
|
|
|
|
var buff = buffer_create(surface_get_width_safe(surface) * surface_get_height_safe(surface) * 4, buffer_fixed, 1);
|
2024-04-12 11:45:21 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
buffer_get_surface(buff, surface, 0);
|
|
|
|
var comp = buffer_compress(buff, 0, buffer_get_size(buff));
|
2024-04-12 11:45:21 +02:00
|
|
|
var enc = buffer_base64_encode(comp, 0, buffer_get_size(comp));
|
|
|
|
var str = { width: surface_get_width_safe(surface), height: surface_get_height_safe(surface), buffer: enc };
|
2024-01-30 15:04:56 +01:00
|
|
|
buffer_delete(buff);
|
2024-04-12 11:45:21 +02:00
|
|
|
|
|
|
|
return stringify? json_stringify(str) : str;
|
2024-01-30 15:04:56 +01:00
|
|
|
} #endregion
|
|
|
|
|
2024-04-21 11:52:16 +02:00
|
|
|
function surface_decode(_struct) { #region
|
|
|
|
var buff = buffer_base64_decode(_struct.buffer);
|
2024-01-30 15:04:56 +01:00
|
|
|
var buff = buffer_decompress(buff);
|
2024-04-21 11:52:16 +02:00
|
|
|
return surface_create_from_buffer(_struct.width, _struct.height, buff);
|
2024-01-30 15:04:56 +01:00
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_format_get_bytes(format) { #region
|
|
|
|
switch(format) {
|
|
|
|
case surface_rgba4unorm : return 4 * 0.5; break;
|
|
|
|
case surface_rgba8unorm : return 4 * 1; break;
|
|
|
|
case surface_rgba16float : return 4 * 2; break;
|
|
|
|
case surface_rgba32float : return 4 * 4; break;
|
|
|
|
|
|
|
|
case surface_r8unorm : return 1 * 1; break;
|
|
|
|
case surface_r16float : return 1 * 2; break;
|
|
|
|
case surface_r32float : return 1 * 3; break;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
} #endregion
|
2023-02-14 13:44:46 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_get_size(surface) { #region
|
|
|
|
INLINE
|
2023-02-14 13:44:46 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var sw = surface_get_width_safe(surface);
|
|
|
|
var sh = surface_get_height_safe(surface);
|
|
|
|
var sz = sw * sh * surface_format_get_bytes(surface_get_format(surface));
|
|
|
|
return sz;
|
|
|
|
} #endregion
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_texture(surface) { #region
|
|
|
|
INLINE
|
2023-07-29 10:10:48 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!is_surface(surface)) return -1;
|
|
|
|
return surface_get_texture(surface);
|
|
|
|
} #endregion
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
#macro surface_free surface_free_safe
|
|
|
|
#macro __surface_free surface_free
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
function surface_free_safe(surface) { #region
|
|
|
|
INLINE
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(!is_surface(surface)) return;
|
|
|
|
__surface_free(surface);
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_save_safe(surface, path) { #region
|
|
|
|
if(!is_surface(surface)) return;
|
2024-04-13 07:32:04 +02:00
|
|
|
|
|
|
|
if(is_instanceof(surface, SurfaceAtlas)) surface = surface.surface.get();
|
|
|
|
else if(is_instanceof(surface, SurfaceAtlasFast)) surface = surface.surface;
|
|
|
|
else if(is_instanceof(surface, dynaSurf)) surface = array_safe_get(surface.surfaces, 0);
|
|
|
|
|
2024-06-25 08:44:08 +02:00
|
|
|
if(is_array(surface) || !surface_exists(surface)) return;
|
2024-04-13 07:32:04 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
var f = surface_get_format(surface);
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
if(f == surface_rgba8unorm) {
|
|
|
|
surface_save(surface, path);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var w = surface_get_width_safe(surface);
|
|
|
|
var h = surface_get_height_safe(surface);
|
|
|
|
var s = surface_create(w, h, surface_rgba8unorm);
|
|
|
|
|
|
|
|
switch(f) {
|
|
|
|
case surface_rgba4unorm :
|
|
|
|
case surface_rgba8unorm :
|
|
|
|
case surface_rgba16float :
|
|
|
|
case surface_rgba32float :
|
|
|
|
surface_set_shader(s, sh_draw_normal);
|
|
|
|
draw_surface(surface, 0, 0);
|
|
|
|
surface_reset_shader();
|
|
|
|
surface_save(s, path);
|
|
|
|
return;
|
|
|
|
case surface_r8unorm : s = surface_create(w, h, surface_rgba8unorm); break;
|
|
|
|
case surface_r16float : s = surface_create(w, h, surface_rgba16float); break;
|
|
|
|
case surface_r32float : s = surface_create(w, h, surface_rgba32float); break;
|
|
|
|
default: return;
|
|
|
|
}
|
|
|
|
|
|
|
|
surface_set_shader(s, sh_draw_single_channel);
|
|
|
|
draw_surface(surface, 0, 0);
|
|
|
|
surface_reset_shader();
|
|
|
|
|
|
|
|
surface_save(s, path);
|
|
|
|
surface_free(s);
|
|
|
|
return;
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_cvt_8unorm(target, surface) { #region
|
|
|
|
if(!is_surface(surface)) return target;
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
target = surface_verify(target, surface_get_width_safe(surface), surface_get_height_safe(surface));
|
|
|
|
var _typ = surface_get_format(surface);
|
2023-03-02 07:59:14 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
switch(_typ) {
|
|
|
|
case surface_rgba4unorm :
|
|
|
|
case surface_rgba8unorm :
|
|
|
|
case surface_rgba16float :
|
|
|
|
case surface_rgba32float :
|
|
|
|
surface_set_shader(target, sh_draw_normal);
|
|
|
|
break;
|
|
|
|
case surface_r8unorm :
|
|
|
|
case surface_r16float :
|
|
|
|
case surface_r32float :
|
|
|
|
surface_set_shader(target, sh_draw_single_channel);
|
|
|
|
break;
|
2023-03-19 09:17:39 +01:00
|
|
|
}
|
2024-01-30 15:04:56 +01:00
|
|
|
|
|
|
|
draw_surface(surface, 0, 0);
|
|
|
|
surface_reset_shader();
|
2023-08-17 16:56:54 +02:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
return target;
|
2024-01-17 14:57:32 +01:00
|
|
|
} #endregion
|
2023-10-31 13:33:36 +01:00
|
|
|
|
2024-01-30 15:04:56 +01:00
|
|
|
#endregion =================================== OTHERS ===================================
|