function Node_Camera(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { name = "Camera"; preview_alpha = 0.5; onSurfaceSize = function() { return surface_get_dimension(getInputData(0)); }; newInput(0, nodeValue_Area("Focus area", self, DEF_AREA, { onSurfaceSize, useShape : false })); newInput(1, nodeValue_Float("Zoom", self, 1)) .setDisplay(VALUE_DISPLAY.slider, { range: [ 0.01, 4, 0.01 ] }); newInput(2, nodeValue_Bool("Depth of Field", self, false)); newInput(3, nodeValue_Float("Focal distance", self, 0)); newInput(4, nodeValue_Float("Defocus", self, 1)); newInput(5, nodeValue_Float("Focal range", self, 0)); newOutput(0, nodeValue_Output("Surface out", self, VALUE_TYPE.surface, noone)); input_display_list = [ ["Camera", false], 0, 1, ["Depth Of Field", true, 2], 3, 5, 4, ["Elements", true], ]; attribute_surface_depth(); temp_surface = [ noone, noone ]; static createNewInput = function() { var index = array_length(inputs); var _s = floor((index - input_fix_len) / data_length); if(_s) array_push(input_display_list, new Inspector_Spacer(20, true)); newInput(index + 0, nodeValue_Surface($"Element {_s}", self, noone)); newInput(index + 1, nodeValue_Enum_Button($"Positioning {_s}", self, false, [ "Space", "Camera" ])); newInput(index + 2, nodeValue_Vec2($"Position {_s}", self, [ 0, 0 ] )) .setUnitRef(function(index) { return getDimension(index); }); newInput(index + 3, nodeValue_Enum_Scroll($"Oversample {_s}", self, 0, [ new scrollItem("Empty ", s_node_camera_repeat, 0), new scrollItem("Repeat ", s_node_camera_repeat, 1), new scrollItem("Repeat X", s_node_camera_repeat, 2), new scrollItem("Repeat Y", s_node_camera_repeat, 3), ])); newInput(index + 4, nodeValue_Vec2($"Parallax {_s}", self, [ 0, 0 ])); newInput(index + 5, nodeValue($"Depth {_s}", self, CONNECT_TYPE.input, VALUE_TYPE.float, 0)); for( var i = 0; i < data_length; i++ ) array_push(input_display_list, index + i); return inputs[index + 0]; } setDynamicInput(6, true, VALUE_TYPE.surface); static getPreviewValues = function() { return getInputData(input_fix_len); } static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny, _params) { PROCESSOR_OVERLAY_CHECK var _out = outputs[0].getValue(); if(is_array(_out)) _out = _out[preview_index]; var _area = current_data[0]; var _zoom = current_data[1]; var _cam_x = _x + (_area[0] - _area[2] * _zoom) * _s; var _cam_y = _y + (_area[1] - _area[3] * _zoom) * _s; if(PANEL_PREVIEW.getNodePreview() == self) draw_surface_ext_safe(_out, _cam_x, _cam_y, _s * _zoom, _s * _zoom); inputs[0].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); draw_set_color(COLORS._main_accent); var x0 = _cam_x; var y0 = _cam_y; var x1 = x0 + _area[2] * 2 * _zoom * _s; var y1 = y0 + _area[3] * 2 * _zoom * _s; draw_rectangle_dashed(x0, y0, x1, y1); } static processData = function(_outSurf, _data, _output_index, _array_index) { var _area = _data[0]; var _zoom = _data[1]; var _dof = _data[2]; var _dof_dist = _data[3]; var _dof_stop = _data[4]; var _dof_rang = _data[5]; var cDep = attrDepth(); 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)); _outSurf = surface_verify(_outSurf, _surf_w, _surf_h, cDep); for( var i = 0, n = array_length(temp_surface); i < n; i++ ) { temp_surface[i] = surface_verify(temp_surface[i], _surf_w, _surf_h, cDep); surface_clear(temp_surface[i]); } var amo = getInputAmount(); if(amo <= 0) return _outSurf; shader_set(sh_camera); shader_set_f("camDimension", _surf_w, _surf_h); shader_set_f("zoom", _zoom); var ppInd = 0; for( var i = 0; i < amo; i++ ) { var ind = input_fix_len + i * data_length; var _surf = _data[ind + 0]; var _sposT = _data[ind + 1]; var _spos = _data[ind + 2]; var _samp = _data[ind + 3]; var _paral = _data[ind + 4]; var _sdof = _data[ind + 5]; if(!is_surface(_surf)) continue; ppInd = !ppInd; var sx = _spos[0] + _paral[0] * _cam_x; var sy = _spos[1] + _paral[1] * _cam_y; var px, py; if(_sposT == 0) { px = _cam_x - sx; py = _cam_y - sy; } else { px = -sx; py = -sy; } var _scnW = surface_get_width_safe(_surf); var _scnH = surface_get_height_safe(_surf); px /= _scnW; py /= _scnH; shader_set_i("sampleMode", _samp); shader_set_f("scnDimension", _scnW, _scnH); shader_set_f("position", px, py); shader_set_f("bokehStrength", 0); if(_dof) { var _x = max(abs(_sdof - _dof_dist) - _dof_rang, 0); _x = _x * tanh(_x / 10); shader_set_f("bokehStrength", _x * _dof_stop); } shader_set_surface("backg", temp_surface[!ppInd]); //prev surface shader_set_surface("scene", _surf); //surface to draw surface_set_target(temp_surface[ppInd]); draw_sprite_stretched(s_fx_pixel, 0, 0, 0, _surf_w, _surf_h); surface_reset_target(); } shader_reset(); surface_set_shader(_outSurf, noone); draw_surface_safe(temp_surface[ppInd]); surface_reset_shader(); return _outSurf; } }