2023-02-28 09:43:01 +01:00
|
|
|
function Node_Camera(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
|
2022-12-16 09:18:09 +01:00
|
|
|
name = "Camera";
|
|
|
|
preview_alpha = 0.5;
|
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
inputs[| 0] = nodeValue("Background", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, 0);
|
2023-10-02 08:57:44 +02:00
|
|
|
|
2023-11-24 10:41:53 +01:00
|
|
|
onSurfaceSize = function() { return surface_get_dimension(getInputData(0)); };
|
2023-07-11 14:18:23 +02:00
|
|
|
inputs[| 1] = nodeValue("Focus area", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 0, 0, 16, 16, AREA_SHAPE.rectangle ])
|
2023-10-02 08:57:44 +02:00
|
|
|
.setDisplay(VALUE_DISPLAY.area, { onSurfaceSize });
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
inputs[| 2] = nodeValue("Zoom", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
|
2023-10-02 08:57:44 +02:00
|
|
|
.setDisplay(VALUE_DISPLAY.slider, { range: [ 0.01, 4, 0.01 ] });
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
inputs[| 3] = nodeValue("Oversample mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0, "How to deal with pixel outside the surface.\n - Empty: Use empty pixel\n - Clamp: Repeat edge pixel\n - Repeat: Repeat texture.")
|
2023-07-11 20:36:44 +02:00
|
|
|
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Empty", "Repeat", "Repeat X", "Repeat Y" ]);
|
2022-12-16 09:18:09 +01:00
|
|
|
|
2023-02-28 09:43:01 +01:00
|
|
|
inputs[| 4] = nodeValue("Fix background", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
|
|
|
|
|
2023-07-11 20:36:44 +02:00
|
|
|
inputs[| 5] = nodeValue("Depth of Field", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
|
|
|
|
|
|
|
|
inputs[| 6] = nodeValue("Focal distance", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0);
|
|
|
|
|
|
|
|
inputs[| 7] = nodeValue("Defocus", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1);
|
|
|
|
|
|
|
|
inputs[| 8] = nodeValue("Focal range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0);
|
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
|
2022-12-16 09:18:09 +01:00
|
|
|
|
2023-01-17 08:11:55 +01:00
|
|
|
input_display_list = [
|
2023-07-11 14:18:23 +02:00
|
|
|
["Background", true], 0, 4, 3,
|
2024-01-09 03:39:40 +01:00
|
|
|
["Camera", false], 1, 2,
|
|
|
|
["Depth Of Field", true, 5], 6, 8, 7,
|
2023-07-11 14:18:23 +02:00
|
|
|
["Elements", true],
|
2023-01-17 08:11:55 +01:00
|
|
|
];
|
|
|
|
|
2023-03-19 09:17:39 +01:00
|
|
|
attribute_surface_depth();
|
2023-08-05 14:00:33 +02:00
|
|
|
|
|
|
|
setIsDynamicInput(3);
|
2023-07-11 14:18:23 +02:00
|
|
|
|
|
|
|
temp_surface = [ noone, noone ];
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-11-21 11:54:45 +01:00
|
|
|
static createNewInput = function() { #region
|
2023-01-17 08:11:55 +01:00
|
|
|
var index = ds_list_size(inputs);
|
|
|
|
var _s = floor((index - input_fix_len) / data_length);
|
|
|
|
|
2023-07-11 14:18:23 +02:00
|
|
|
inputs[| index + 0] = nodeValue($"Element {_s}", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, 0);
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-07-11 14:18:23 +02:00
|
|
|
inputs[| index + 1] = nodeValue($"Parallax {_s}", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0 ] )
|
2023-01-17 08:11:55 +01:00
|
|
|
.setDisplay(VALUE_DISPLAY.vector)
|
|
|
|
.setUnitRef(function(index) { return getDimension(index); });
|
|
|
|
|
2023-07-11 14:18:23 +02:00
|
|
|
inputs[| index + 2] = nodeValue($"Oversample {_s}", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
|
2023-07-11 20:36:44 +02:00
|
|
|
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Empty", "Repeat", "Repeat X", "Repeat Y" ]);
|
2023-07-11 14:18:23 +02:00
|
|
|
|
|
|
|
array_append(input_display_list, [ index + 0, index + 1, index + 2 ]);
|
2023-11-21 11:54:45 +01:00
|
|
|
} if(!LOADING && !APPENDING) createNewInput(); #endregion
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-11-21 11:54:45 +01:00
|
|
|
static refreshDynamicInput = function() { #region
|
2023-01-17 08:11:55 +01:00
|
|
|
var _in = ds_list_create();
|
|
|
|
|
|
|
|
for( var i = 0; i < input_fix_len; i++ )
|
|
|
|
ds_list_add(_in, inputs[| i]);
|
|
|
|
|
|
|
|
array_resize(input_display_list, input_display_len);
|
|
|
|
|
|
|
|
for( var i = input_fix_len; i < ds_list_size(inputs); i += data_length ) {
|
|
|
|
if(inputs[| i].value_from) {
|
|
|
|
ds_list_add(_in, inputs[| i + 0]);
|
|
|
|
ds_list_add(_in, inputs[| i + 1]);
|
2023-07-11 14:18:23 +02:00
|
|
|
ds_list_add(_in, inputs[| i + 2]);
|
2023-01-17 08:11:55 +01:00
|
|
|
|
|
|
|
array_push(input_display_list, i + 0);
|
|
|
|
array_push(input_display_list, i + 1);
|
2023-07-11 14:18:23 +02:00
|
|
|
array_push(input_display_list, i + 2);
|
2023-01-17 08:11:55 +01:00
|
|
|
} else {
|
|
|
|
delete inputs[| i + 0];
|
|
|
|
delete inputs[| i + 1];
|
2023-07-11 14:18:23 +02:00
|
|
|
delete inputs[| i + 2];
|
2023-01-17 08:11:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for( var i = 0; i < ds_list_size(_in); i++ )
|
|
|
|
_in[| i].index = i;
|
|
|
|
|
|
|
|
ds_list_destroy(inputs);
|
|
|
|
inputs = _in;
|
|
|
|
|
|
|
|
createNewInput();
|
2023-11-21 11:54:45 +01:00
|
|
|
} #endregion
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-11-21 11:54:45 +01:00
|
|
|
static onValueFromUpdate = function(index) { #region
|
2023-01-17 08:11:55 +01:00
|
|
|
if(index < input_fix_len) return;
|
|
|
|
if(LOADING || APPENDING) return;
|
|
|
|
|
|
|
|
refreshDynamicInput();
|
2023-11-21 11:54:45 +01:00
|
|
|
} #endregion
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-10-02 08:57:44 +02:00
|
|
|
static getPreviewValues = function() { return getInputData(0); }
|
2022-12-16 09:18:09 +01:00
|
|
|
|
2023-11-21 11:54:45 +01:00
|
|
|
static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
|
2022-12-27 04:00:50 +01:00
|
|
|
if(array_length(current_data) == 0) return;
|
|
|
|
|
2022-12-16 09:18:09 +01:00
|
|
|
var _out = outputs[| 0].getValue();
|
|
|
|
var _area = current_data[1];
|
2023-01-17 08:11:55 +01:00
|
|
|
var _zoom = current_data[2];
|
2022-12-16 09:18:09 +01:00
|
|
|
|
2023-07-11 14:18:23 +02:00
|
|
|
var _cam_x = _x + (_area[0] - _area[2] * _zoom) * _s;
|
|
|
|
var _cam_y = _y + (_area[1] - _area[3] * _zoom) * _s;
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-07-11 14:18:23 +02:00
|
|
|
draw_surface_ext_safe(_out, _cam_x, _cam_y, _s * _zoom, _s * _zoom);
|
2022-12-19 13:35:30 +01:00
|
|
|
inputs[| 1].drawOverlay(active, _x, _y, _s, _mx, _my, _snx, _sny);
|
2023-01-17 08:11:55 +01:00
|
|
|
|
|
|
|
draw_set_color(COLORS._main_accent);
|
2023-07-11 14:18:23 +02:00
|
|
|
var x0 = _cam_x;
|
|
|
|
var y0 = _cam_y;
|
2023-01-17 08:11:55 +01:00
|
|
|
var x1 = x0 + _area[2] * 2 * _zoom * _s;
|
|
|
|
var y1 = y0 + _area[3] * 2 * _zoom * _s;
|
|
|
|
|
|
|
|
draw_rectangle_dashed(x0, y0, x1, y1);
|
2023-11-21 11:54:45 +01:00
|
|
|
} #endregion
|
2022-12-16 09:18:09 +01:00
|
|
|
|
2023-11-21 11:54:45 +01:00
|
|
|
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
|
2023-02-14 05:32:32 +01:00
|
|
|
if(!is_surface(_data[0])) return;
|
2022-12-16 09:18:09 +01:00
|
|
|
var _area = _data[1];
|
2023-01-17 08:11:55 +01:00
|
|
|
var _zoom = _data[2];
|
2023-07-11 14:18:23 +02:00
|
|
|
var _samp = _data[3];
|
2023-02-28 09:43:01 +01:00
|
|
|
var _fix = _data[4];
|
2023-07-11 20:36:44 +02:00
|
|
|
|
|
|
|
var _dof = _data[5];
|
|
|
|
var _dof_dist = _data[6];
|
|
|
|
var _dof_stop = _data[7];
|
|
|
|
var _dof_rang = _data[8];
|
|
|
|
|
2023-03-19 09:17:39 +01:00
|
|
|
var cDep = attrDepth();
|
2022-12-16 09:18:09 +01:00
|
|
|
|
2023-07-11 14:18:23 +02:00
|
|
|
var _cam_x = round(_area[0]);
|
|
|
|
var _cam_y = round(_area[1]);
|
|
|
|
var _cam_w = round(_area[2]);
|
|
|
|
var _cam_h = round(_area[3]);
|
|
|
|
|
|
|
|
var _surf_w = round(surface_valid_size(_cam_w * 2));
|
|
|
|
var _surf_h = round(surface_valid_size(_cam_h * 2));
|
|
|
|
var ppInd = 0;
|
|
|
|
|
|
|
|
_outSurf = surface_verify(_outSurf, _surf_w, _surf_h, cDep);
|
|
|
|
temp_surface[0] = surface_verify(temp_surface[0], _surf_w, _surf_h, cDep);
|
|
|
|
temp_surface[1] = surface_verify(temp_surface[1], _surf_w, _surf_h, cDep);
|
2023-01-25 06:49:00 +01:00
|
|
|
|
2023-02-28 09:43:01 +01:00
|
|
|
var amo = (ds_list_size(inputs) - input_fix_len) / data_length - 1;
|
|
|
|
|
2023-07-11 14:18:23 +02:00
|
|
|
surface_set_target(temp_surface[0]);
|
2023-03-19 09:17:39 +01:00
|
|
|
DRAW_CLEAR
|
2023-01-25 06:49:00 +01:00
|
|
|
surface_reset_target();
|
|
|
|
|
2023-07-11 14:18:23 +02:00
|
|
|
surface_set_target(temp_surface[1]);
|
2023-03-19 09:17:39 +01:00
|
|
|
DRAW_CLEAR
|
2023-01-25 06:49:00 +01:00
|
|
|
surface_reset_target();
|
2022-12-16 09:18:09 +01:00
|
|
|
|
2023-07-11 20:36:44 +02:00
|
|
|
shader_set(sh_camera);
|
|
|
|
shader_set_f("camDimension", _surf_w, _surf_h);
|
|
|
|
shader_set_f("zoom", _zoom);
|
2023-01-25 06:49:00 +01:00
|
|
|
|
2023-07-11 20:36:44 +02:00
|
|
|
var _surface, sx, sy, sz, _samp;
|
|
|
|
var px, py;
|
|
|
|
var _scnW, _scnH;
|
|
|
|
|
|
|
|
for( var i = -1; i < amo; i++ ) {
|
2023-01-25 06:49:00 +01:00
|
|
|
ppInd = !ppInd;
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-07-11 14:18:23 +02:00
|
|
|
surface_set_target(temp_surface[ppInd]);
|
2023-07-11 20:36:44 +02:00
|
|
|
if(i == -1) {
|
|
|
|
_surface = _data[0];
|
|
|
|
sx = _fix? 0 : _cam_x;
|
|
|
|
sy = _fix? 0 : _cam_y;
|
|
|
|
sz = 0;
|
|
|
|
_samp = _data[3];
|
|
|
|
|
|
|
|
px = sx;
|
|
|
|
py = sy;
|
|
|
|
} else {
|
|
|
|
var ind = input_fix_len + i * data_length;
|
|
|
|
|
|
|
|
_surface = _data[ind];
|
|
|
|
sz = _data[ind + 1][2];
|
|
|
|
sx = _data[ind + 1][0] * sz * _cam_x;
|
|
|
|
sy = _data[ind + 1][1] * sz * _cam_y;
|
|
|
|
_samp = _data[ind + 2];
|
|
|
|
|
|
|
|
px = _cam_x + sx;
|
|
|
|
py = _cam_y + sy;
|
|
|
|
}
|
|
|
|
|
2023-09-08 21:37:36 +02:00
|
|
|
_scnW = surface_get_width_safe(_surface);
|
|
|
|
_scnH = surface_get_height_safe(_surface);
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-07-11 20:36:44 +02:00
|
|
|
px /= _scnW;
|
|
|
|
py /= _scnH;
|
2023-07-11 14:18:23 +02:00
|
|
|
|
2023-07-11 20:36:44 +02:00
|
|
|
shader_set_i("bg", i == -1? 1 : 0);
|
|
|
|
shader_set_i("sampleMode", _samp);
|
|
|
|
shader_set_f("scnDimension", _scnW, _scnH);
|
|
|
|
shader_set_f("position", px, py);
|
|
|
|
if(_dof) {
|
|
|
|
var _x = max(abs(sz - _dof_dist) - _dof_rang, 0);
|
|
|
|
_x = _x * tanh(_x / 10);
|
|
|
|
shader_set_f("bokehStrength", _x * _dof_stop);
|
|
|
|
} else shader_set_f("bokehStrength", 0);
|
2023-01-25 06:49:00 +01:00
|
|
|
|
2023-07-11 20:36:44 +02:00
|
|
|
shader_set_surface("backg", temp_surface[!ppInd]); //prev surface
|
|
|
|
shader_set_surface("scene", _surface); //surface to draw
|
2023-07-11 14:18:23 +02:00
|
|
|
|
2023-07-15 20:01:29 +02:00
|
|
|
draw_sprite_stretched(s_fx_pixel, 0, 0, 0, _surf_w, _surf_h);
|
2023-01-25 06:49:00 +01:00
|
|
|
surface_reset_target();
|
|
|
|
}
|
|
|
|
|
2023-01-17 08:11:55 +01:00
|
|
|
shader_reset();
|
2023-01-25 06:49:00 +01:00
|
|
|
|
|
|
|
surface_set_target(_outSurf);
|
2023-03-19 09:17:39 +01:00
|
|
|
DRAW_CLEAR
|
2023-02-14 05:32:32 +01:00
|
|
|
BLEND_OVERRIDE;
|
2023-07-11 14:18:23 +02:00
|
|
|
draw_surface_safe(temp_surface[ppInd], 0, 0);
|
2023-02-14 05:32:32 +01:00
|
|
|
BLEND_NORMAL;
|
2022-12-16 09:18:09 +01:00
|
|
|
surface_reset_target();
|
|
|
|
|
|
|
|
return _outSurf;
|
2023-11-21 11:54:45 +01:00
|
|
|
} #endregion
|
2022-12-16 09:18:09 +01:00
|
|
|
}
|