Onion skin, active indicator

This commit is contained in:
Tanasart 2023-07-08 20:29:23 +02:00
parent 7c2bacea4e
commit 1623e8fc1b
24 changed files with 894 additions and 257 deletions

View file

@ -271,6 +271,7 @@
{"name":"bbmod_lerp_delta_time","order":1,"path":"scripts/bbmod_lerp_delta_time/bbmod_lerp_delta_time.yy",},
{"name":"_3D","order":6,"path":"scripts/_3D/_3D.yy",},
{"name":"node_vector_cross2D","order":11,"path":"scripts/node_vector_cross2D/node_vector_cross2D.yy",},
{"name":"o_dialog_preview_onion_skin","order":2,"path":"objects/o_dialog_preview_onion_skin/o_dialog_preview_onion_skin.yy",},
{"name":"sh_corner_erode","order":48,"path":"shaders/sh_corner_erode/sh_corner_erode.yy",},
{"name":"node_outline","order":11,"path":"scripts/node_outline/node_outline.yy",},
{"name":"sh_mesh_generation","order":4,"path":"shaders/sh_mesh_generation/sh_mesh_generation.yy",},
@ -722,6 +723,7 @@
{"name":"o_dialog_graph_grid","order":3,"path":"objects/o_dialog_graph_grid/o_dialog_graph_grid.yy",},
{"name":"append_function","order":1,"path":"scripts/append_function/append_function.yy",},
{"name":"fd_rectangle_reset_target","order":17,"path":"scripts/fd_rectangle_reset_target/fd_rectangle_reset_target.yy",},
{"name":"node_rate_remap","order":3,"path":"scripts/node_rate_remap/node_rate_remap.yy",},
{"name":"obj_reader","order":2,"path":"scripts/obj_reader/obj_reader.yy",},
{"name":"sh_invert","order":25,"path":"shaders/sh_invert/sh_invert.yy",},
{"name":"preview_overlay_puppet","order":4,"path":"scripts/preview_overlay_puppet/preview_overlay_puppet.yy",},
@ -799,6 +801,7 @@
{"name":"o_dialog_save","order":12,"path":"objects/o_dialog_save/o_dialog_save.yy",},
{"name":"s_node_BW","order":13,"path":"sprites/s_node_BW/s_node_BW.yy",},
{"name":"s_node_strandSim_collide","order":7,"path":"sprites/s_node_strandSim_collide/s_node_strandSim_collide.yy",},
{"name":"node_onion_skin","order":12,"path":"scripts/node_onion_skin/node_onion_skin.yy",},
{"name":"sh_fd_turbulence","order":22,"path":"shaders/sh_fd_turbulence/sh_fd_turbulence.yy",},
{"name":"s_node_compare","order":1,"path":"sprites/s_node_compare/s_node_compare.yy",},
{"name":"s_node_fluidSim_domain_queue","order":9,"path":"sprites/s_node_fluidSim_domain_queue/s_node_fluidSim_domain_queue.yy",},
@ -937,6 +940,7 @@
{"name":"s_node_text_length","order":9,"path":"sprites/s_node_text_length/s_node_text_length.yy",},
{"name":"s_node_grid_hex","order":4,"path":"sprites/s_node_grid_hex/s_node_grid_hex.yy",},
{"name":"sh_fd_visualize_colorize_glsl","order":13,"path":"shaders/sh_fd_visualize_colorize_glsl/sh_fd_visualize_colorize_glsl.yy",},
{"name":"s_node_rate_remap","order":4,"path":"sprites/s_node_rate_remap/s_node_rate_remap.yy",},
{"name":"o_dialog_preview_window","order":1,"path":"objects/o_dialog_preview_window/o_dialog_preview_window.yy",},
{"name":"s_node_sampler","order":11,"path":"sprites/s_node_sampler/s_node_sampler.yy",},
{"name":"__background_get_element","order":1,"path":"scripts/__background_get_element/__background_get_element.yy",},

View file

@ -243,6 +243,7 @@
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_addon.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_animate_clock_strip3.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_animate_node_go.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_animate_onion_skin.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_animation_setting.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_animation_stretch.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_animation_timing.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
@ -332,6 +333,7 @@
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_noti_icon_log_strip2.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_noti_icon_tick.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_noti_icon_warning_strip2.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_onion_skin.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_padding_link_strip2.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_panel_active_split.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_panel_animation.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/icon",},
@ -463,6 +465,7 @@
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_timeline_elastic.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/timeline",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_timeline_keyframe_selecting.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/timeline",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_timeline_keyframes.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/timeline",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_timeline_onion_skin.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/timeline",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"graphics x2.ai","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/tool",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_3d_tool_rotate.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/tool",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_3d_tool_scale.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/tool",},
@ -511,6 +514,7 @@
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_menu_separator.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/UI",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_menu_white.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/UI",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_shadow_drop_down_24.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/UI",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_timeline_dopesheet_bg.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/UI",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_toolbar_shadow.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/UI",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_toolbar.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/UI",},
{"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"s_ui_label_bg.png","CopyToMask":-1,"filePath":"datafiles/data/themes/default/graphics/UI",},
@ -752,6 +756,7 @@
{"id":{"name":"bbmod_lerp_delta_time","path":"scripts/bbmod_lerp_delta_time/bbmod_lerp_delta_time.yy",},},
{"id":{"name":"_3D","path":"scripts/_3D/_3D.yy",},},
{"id":{"name":"node_vector_cross2D","path":"scripts/node_vector_cross2D/node_vector_cross2D.yy",},},
{"id":{"name":"o_dialog_preview_onion_skin","path":"objects/o_dialog_preview_onion_skin/o_dialog_preview_onion_skin.yy",},},
{"id":{"name":"sh_corner_erode","path":"shaders/sh_corner_erode/sh_corner_erode.yy",},},
{"id":{"name":"__init_view","path":"scripts/__init_view/__init_view.yy",},},
{"id":{"name":"node_outline","path":"scripts/node_outline/node_outline.yy",},},
@ -1269,6 +1274,7 @@
{"id":{"name":"o_dialog_graph_grid","path":"objects/o_dialog_graph_grid/o_dialog_graph_grid.yy",},},
{"id":{"name":"append_function","path":"scripts/append_function/append_function.yy",},},
{"id":{"name":"fd_rectangle_reset_target","path":"scripts/fd_rectangle_reset_target/fd_rectangle_reset_target.yy",},},
{"id":{"name":"node_rate_remap","path":"scripts/node_rate_remap/node_rate_remap.yy",},},
{"id":{"name":"obj_reader","path":"scripts/obj_reader/obj_reader.yy",},},
{"id":{"name":"sh_invert","path":"shaders/sh_invert/sh_invert.yy",},},
{"id":{"name":"preview_overlay_puppet","path":"scripts/preview_overlay_puppet/preview_overlay_puppet.yy",},},
@ -1352,6 +1358,7 @@
{"id":{"name":"o_dialog_save","path":"objects/o_dialog_save/o_dialog_save.yy",},},
{"id":{"name":"s_node_BW","path":"sprites/s_node_BW/s_node_BW.yy",},},
{"id":{"name":"s_node_strandSim_collide","path":"sprites/s_node_strandSim_collide/s_node_strandSim_collide.yy",},},
{"id":{"name":"node_onion_skin","path":"scripts/node_onion_skin/node_onion_skin.yy",},},
{"id":{"name":"sh_fd_turbulence","path":"shaders/sh_fd_turbulence/sh_fd_turbulence.yy",},},
{"id":{"name":"s_node_compare","path":"sprites/s_node_compare/s_node_compare.yy",},},
{"id":{"name":"s_node_fluidSim_domain_queue","path":"sprites/s_node_fluidSim_domain_queue/s_node_fluidSim_domain_queue.yy",},},
@ -1506,6 +1513,7 @@
{"id":{"name":"s_node_text_length","path":"sprites/s_node_text_length/s_node_text_length.yy",},},
{"id":{"name":"s_node_grid_hex","path":"sprites/s_node_grid_hex/s_node_grid_hex.yy",},},
{"id":{"name":"sh_fd_visualize_colorize_glsl","path":"shaders/sh_fd_visualize_colorize_glsl/sh_fd_visualize_colorize_glsl.yy",},},
{"id":{"name":"s_node_rate_remap","path":"sprites/s_node_rate_remap/s_node_rate_remap.yy",},},
{"id":{"name":"s_node_3d_cube","path":"sprites/s_node_3d_cube/s_node_3d_cube.yy",},},
{"id":{"name":"o_dialog_preview_window","path":"objects/o_dialog_preview_window/o_dialog_preview_window.yy",},},
{"id":{"name":"s_node_sampler","path":"sprites/s_node_sampler/s_node_sampler.yy",},},

Binary file not shown.

View file

@ -0,0 +1,41 @@
/// @description init
event_inherited();
#region data
dialog_w = ui(400);
dialog_h = ui(300);
destroy_on_click_out = true;
#endregion
#region data
cb_enable = new checkBox(function() {
var _node = PANEL_PREVIEW.getNodePreview();
PROJECT.onion_skin.enabled = !PROJECT.onion_skin.enabled;
});
cb_top = new checkBox(function() {
var _node = PANEL_PREVIEW.getNodePreview();
PROJECT.onion_skin.on_top = !PROJECT.onion_skin.on_top;
});
tb_step = new textBox(TEXTBOX_INPUT.number, function(str) {
var _node = PANEL_PREVIEW.getNodePreview();
PROJECT.onion_skin.step = max(1, round(real(str)));
});
cl_color_pre = new buttonColor(function(color) {
var _node = PANEL_PREVIEW.getNodePreview();
PROJECT.onion_skin.color[0] = color;
}, self);
cl_color_post = new buttonColor(function(color) {
var _node = PANEL_PREVIEW.getNodePreview();
PROJECT.onion_skin.color[1] = color;
}, self);
sl_opacity = new slider(0, 1, .05, function(str) {
var _node = PANEL_PREVIEW.getNodePreview();
PROJECT.onion_skin.alpha = clamp(real(str), 0, 1);
});
#endregion

View file

@ -0,0 +1,57 @@
/// @description init
if !ready exit;
#region base UI
draw_sprite_stretched(THEME.dialog_bg, 0, dialog_x, dialog_y, dialog_w, dialog_h);
if(sFOCUS)
draw_sprite_stretched_ext(THEME.dialog_active, 0, dialog_x, dialog_y, dialog_w, dialog_h, COLORS._main_accent, 1);
draw_set_text(f_p0, fa_left, fa_top, COLORS._main_text);
draw_text(dialog_x + ui(24), dialog_y + ui(16), __txt("Onion Skin"));
#endregion
#region draw
var yy = dialog_y + ui(64);
var ww = ui(208);
cb_enable.setFocusHover(sFOCUS, sHOVER);
cb_enable.register();
draw_set_text(f_p1, fa_left, fa_center, COLORS._main_text);
draw_text(dialog_x + ui(32), yy, __txt("Enabled"));
cb_enable.draw(dialog_x + dialog_w - ui(24) - ww / 2, yy, PROJECT.onion_skin.enabled, mouse_ui,, fa_center, fa_center);
yy += ui(40);
cb_top.setFocusHover(sFOCUS, sHOVER);
cb_top.register();
draw_set_text(f_p1, fa_left, fa_center, COLORS._main_text);
draw_text(dialog_x + ui(32), yy, __txtx("onion_skin_top", "Draw on top"));
cb_top.draw(dialog_x + dialog_w - ui(24) - ww / 2, yy, PROJECT.onion_skin.on_top, mouse_ui,, fa_center, fa_center);
yy += ui(40);
tb_step.setFocusHover(sFOCUS, sHOVER);
tb_step.register();
draw_set_text(f_p1, fa_left, fa_center, COLORS._main_text);
draw_text(dialog_x + ui(32), yy, __txt("Frame step"));
tb_step.draw(dialog_x + dialog_w - ui(24), yy, ww, TEXTBOX_HEIGHT, PROJECT.onion_skin.step, mouse_ui,, fa_right, fa_center);
yy += ui(40);
cl_color_pre.setFocusHover(sFOCUS, sHOVER);
cl_color_pre.register();
draw_set_text(f_p1, fa_left, fa_center, COLORS._main_text);
draw_text(dialog_x + ui(32), yy, __txt("Pre Color"));
cl_color_pre.draw(dialog_x + dialog_w - ui(24) - ww, yy - TEXTBOX_HEIGHT / 2, ww, TEXTBOX_HEIGHT, PROJECT.onion_skin.color[0], mouse_ui);
yy += ui(40);
cl_color_post.setFocusHover(sFOCUS, sHOVER);
cl_color_post.register();
draw_set_text(f_p1, fa_left, fa_center, COLORS._main_text);
draw_text(dialog_x + ui(32), yy, __txt("Post Color"));
cl_color_post.draw(dialog_x + dialog_w - ui(24) - ww, yy - TEXTBOX_HEIGHT / 2, ww, TEXTBOX_HEIGHT, PROJECT.onion_skin.color[1], mouse_ui);
yy += ui(40);
sl_opacity.setFocusHover(sFOCUS, sHOVER);
sl_opacity.register();
draw_set_text(f_p1, fa_left, fa_center, COLORS._main_text);
draw_text(dialog_x + ui(32), yy, __txt("Opacity"));
sl_opacity.draw(dialog_x + dialog_w - ui(24), yy, ww, TEXTBOX_HEIGHT, PROJECT.onion_skin.alpha, mouse_ui, ui(52), fa_right, fa_center);
#endregion

View file

@ -0,0 +1,37 @@
{
"resourceType": "GMObject",
"resourceVersion": "1.0",
"name": "o_dialog_preview_onion_skin",
"eventList": [
{"resourceType":"GMEvent","resourceVersion":"1.0","name":"","collisionObjectId":null,"eventNum":0,"eventType":0,"isDnD":false,},
{"resourceType":"GMEvent","resourceVersion":"1.0","name":"","collisionObjectId":null,"eventNum":64,"eventType":8,"isDnD":false,},
],
"managed": true,
"overriddenProperties": [],
"parent": {
"name": "preview",
"path": "folders/dialog/preview.yy",
},
"parentObjectId": {
"name": "_p_dialog",
"path": "objects/_p_dialog/_p_dialog.yy",
},
"persistent": false,
"physicsAngularDamping": 0.1,
"physicsDensity": 0.5,
"physicsFriction": 0.2,
"physicsGroup": 1,
"physicsKinematic": false,
"physicsLinearDamping": 0.1,
"physicsObject": false,
"physicsRestitution": 0.1,
"physicsSensor": false,
"physicsShape": 1,
"physicsShapePoints": [],
"physicsStartAwake": true,
"properties": [],
"solid": false,
"spriteId": null,
"spriteMaskId": null,
"visible": true,
}

View file

@ -16,7 +16,7 @@
#region project
function Project() constructor {
path = "";
version = 1440;
version = 0;
seed = irandom_range(100000, 999999);
modified = false;
@ -31,6 +31,15 @@
globalNode = new Node_Global();
addons = {};
onion_skin = {
enabled: false,
range: [ -1, 1 ],
step: 1,
color: [ c_red, c_blue ],
alpha: 0.5,
on_top: true,
};
}
globalvar PROJECTS, PROJECT;
@ -53,9 +62,9 @@
globalvar VERSION, SAVE_VERSION, VERSION_STRING, BUILD_NUMBER;
VERSION = 1146;
VERSION = 1147;
SAVE_VERSION = 1440;
VERSION_STRING = "1.14.6n1";
VERSION_STRING = "1.14.6n2";
BUILD_NUMBER = 114600;
globalvar APPEND_MAP;

View file

@ -110,6 +110,10 @@ function __LOAD_PATH(path, readonly = false, safe_mode = false, override = false
log_warning("LOAD, animator", exception_print(e));
}
if(struct_has(_load_content, "onion_skin")) {
PROJECT.onion_skin = _load_content.onion_skin;
}
try {
if(struct_has(_load_content, "metadata"))
METADATA.deserialize(_load_content.metadata);

View file

@ -9,6 +9,9 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
destroy_when_upgroup = false;
ds_list_add(PANEL_GRAPH.getNodeList(_group), self);
active_index = -1;
active_range = [ 0, PROJECT.animator.frames_total - 1 ];
color = c_white;
icon = noone;
bg_spr = THEME.node_bg;
@ -101,7 +104,8 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
auto_render_time = true;
updated = false;
use_cache = false;
use_cache = false;
clearCacheOnChange = true;
cached_output = [];
cache_result = [];
temp_surface = [];
@ -111,7 +115,8 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
on_dragdrop_file = -1;
anim_show = true;
dopesheet_y = 0;
dopesheet_color = COLORS.panel_animation_dope_blend_default;
dopesheet_y = 0;
value_validation = array_create(3);
@ -348,7 +353,7 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
if(!is_instanceof(self, Node_Collection))
setRenderStatus(true);
update(); ///UPDATE
update(); ///UPDATE
if(!is_instanceof(self, Node_Collection))
render_time = get_timer() - t;
@ -360,6 +365,14 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
log_warning("RENDER", exception_print(exception), self);
}
if(!use_cache && PROJECT.onion_skin) {
for( var i = 0; i < ds_list_size(outputs); i++ ) {
if(outputs[| i].type != VALUE_TYPE.surface) continue;
cacheCurrentFrame(outputs[| i].getValue());
break;
}
}
if(hasInspector1Update()) {
var trigger = inspectInput1.getValue();
if(trigger) onInspector1Update();
@ -1049,7 +1062,7 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
static enable = function() { active = true; }
static disable = function() { active = false; }
static destroy = function(_merge = false) {
if(!active) return;
disable();
@ -1177,13 +1190,19 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
cache_result[i] = false;
}
}
static clearCacheForward = function() {
if(!clearCacheOnChange) return;
_clearCacheForward();
}
static _clearCacheForward = function() {
if(!isRenderActive()) return;
clearCache();
for( var i = 0; i < ds_list_size(outputs); i++ )
for( var j = 0; j < ds_list_size(outputs[| i].value_to); j++ )
outputs[| i].value_to[| j].node.clearCacheForward();
outputs[| i].value_to[| j].node._clearCacheForward();
}
static checkConnectGroup = function(_type = "group") {
@ -1317,7 +1336,7 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
_map.preview = previewable;
}
_map.attri = attributeSerialize();
_map.attri = attributeSerialize();
var _inputs = [];
for(var i = 0; i < ds_list_size(inputs); i++)

View file

@ -0,0 +1,80 @@
function Node_Onion_Skin(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Onion Skin";
use_cache = true;
clearCacheOnChange = false;
inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, 0);
inputs[| 1] = nodeValue("Range", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [-1, 1])
.setDisplay(VALUE_DISPLAY.slider_range, [ -16, 16, 1 ]);
inputs[| 2] = nodeValue("Alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5)
.setDisplay(VALUE_DISPLAY.slider, [ 0, 1, 0.01 ]);
inputs[| 3] = nodeValue("Color pre", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_red)
inputs[| 4] = nodeValue("Color post", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_blue)
inputs[| 5] = nodeValue("Step", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1)
inputs[| 6] = nodeValue("On top", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true, "Render current frame on top of all frames.")
outputs[| 0] = nodeValue("Output", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, 0);
input_display_list = [
["Surface", false], 0, 1, 5,
["Render", false], 2, 3, 4, 6,
];
insp2UpdateTooltip = "Clear cache";
insp2UpdateIcon = [ THEME.cache, 0, COLORS._main_icon ];
static onInspector2Update = function() { clearCache(); }
static update = function() {
if(!inputs[| 0].value_from) return;
var _surf = inputs[| 0].getValue();
var _rang = inputs[| 1].getValue();
var _alph = inputs[| 2].getValue();
var _cpre = inputs[| 3].getValue();
var _cpos = inputs[| 4].getValue();
var _step = inputs[| 5].getValue();
var _top = inputs[| 6].getValue();
cacheCurrentFrame(_surf);
var _outSurf = outputs[| 0].getValue();
_outSurf = surface_verify(_outSurf, surface_get_width(_surf), surface_get_height(_surf));
outputs[| 0].setValue(_outSurf);
surface_set_target(_outSurf);
DRAW_CLEAR
var fr = PROJECT.animator.current_frame;
var st = min(_rang[0], _rang[1]);
var ed = max(_rang[0], _rang[1]);
st = sign(st) * floor(abs(st) / _step) * _step;
ed = sign(ed) * floor(abs(ed) / _step) * _step;
st += fr;
ed += fr;
for( var i = st; i <= ed; i += _step ) {
var surf = getCacheFrame(i);
if(!is_surface(surf)) continue;
var aa = power(_alph, abs(i - fr));
var cc = c_white;
if(i < fr) cc = _cpre;
else if(i > fr) cc = _cpos;
draw_surface_ext_safe(surf, 0, 0, 1, 1, 0, cc, aa);
}
if(_top) draw_surface_safe(_surf, 0, 0);
surface_reset_target();
}
}

View file

@ -0,0 +1,11 @@
{
"resourceType": "GMScript",
"resourceVersion": "1.0",
"name": "node_onion_skin",
"isCompatibility": false,
"isDnD": false,
"parent": {
"name": "node",
"path": "folders/nodes/data/node.yy",
},
}

View file

@ -0,0 +1,12 @@
{
"isDnD": false,
"isCompatibility": false,
"parent": {
"name": "process",
"path": "folders/nodes/data/process.yy",
},
"resourceVersion": "1.0",
"name": "node_outline",
"tags": [],
"resourceType": "GMScript",
}

View file

@ -14,8 +14,7 @@ function Node_Processor(_x, _y, _group = noone) : Node(_x, _y, _group) construct
process_amount = 0;
process_length = [];
dimension_index = 0;
active_index = -1;
dimension_index = 0;
icon = THEME.node_processor;
@ -224,4 +223,28 @@ function Node_Processor(_x, _y, _group = noone) : Node(_x, _y, _group) construct
static processDeserialize = function() {
attributes.array_process = struct_try_get(load_map, "array_process", ARRAY_PROCESS.loop);
}
///////////////////// CACHE /////////////////////
static cacheCurrentFrameIndex = function(_frame, index) {
cacheArrayCheck();
if(PROJECT.animator.current_frame < 0) return;
if(PROJECT.animator.current_frame >= array_length(cached_output)) return;
var prev = cached_output[PROJECT.animator.current_frame];
surface_array_free(array_safe_get(prev, index));
cached_output[PROJECT.animator.current_frame][index] = surface_array_clone(_frame);
array_safe_set(cache_result, PROJECT.animator.current_frame, true);
return cached_output[PROJECT.animator.current_frame];
}
static getCacheFrameIndex = function(frame = PROJECT.animator.current_frame, index = 0) {
if(frame < 0) return false;
if(!cacheExist(frame)) return noone;
var surf = array_safe_get(cached_output, frame);
return array_safe_get(surf, index);
}
}

View file

@ -0,0 +1,34 @@
function Node_Rate_Remap(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Rate Remap";
use_cache = true;
inputs[| 0] = nodeValue("Surface", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 1] = nodeValue("Framerate", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 10);
inputs[| 2] = nodeValue("Active", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
active_index = 2;
outputs[| 0] = nodeValue("Surface", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [ 2,
0, 1
];
static step = function() {
}
function process_data(_output, _data, _output_index, _array_index = 0) {
var _surf = _data[0];
var _rate = _data[1];
var _time = PROJECT.animator.current_frame;
var _step = PROJECT.animator.framerate / _rate;
var _targ = floor(_time / _step) * _step;
cacheCurrentFrameIndex(_surf, _array_index);
var s = getCacheFrameIndex(_targ, _array_index);
return s;
}
}

View file

@ -0,0 +1,11 @@
{
"resourceType": "GMScript",
"resourceVersion": "1.0",
"name": "node_rate_remap",
"isCompatibility": false,
"isDnD": false,
"parent": {
"name": "animation",
"path": "folders/nodes/data/animation.yy",
},
}

View file

@ -565,6 +565,7 @@ function NodeObject(_name, _spr, _node, _create, tags = []) constructor {
addNodeObject(animation, "Frame Index", s_node_counter, "Node_Counter", [1, Node_Counter], ["current frame", "counter"], "Output current frame as frame index, or animation progress (0 - 1).");
addNodeObject(animation, "Wiggler", s_node_wiggler, "Node_Wiggler", [1, Node_Wiggler],, "Create smooth random value.");
addNodeObject(animation, "Evaluate Curve", s_node_curve_eval, "Node_Anim_Curve", [1, Node_Anim_Curve],, "Evaluate value from an animation curve.");
addNodeObject(animation, "Rate Remap", s_node_rate_remap, "Node_Rate_Remap", [1, Node_Rate_Remap],, "Remap animation to a new framerate.").setVersion(1147);
ds_list_add(animation, "Audio");
addNodeObject(animation, "WAV File In", s_node_wav_file_read, "Node_WAV_File_Read", [0, Node_create_WAV_File_Read],, "Load wav audio file.").setVersion(1144);
@ -618,6 +619,7 @@ function NodeObject(_name, _spr, _node, _create, tags = []) constructor {
addNodeObject(hid, "Hexagonal Noise", s_node_grid_hex_noise, "Node_Noise_Hex", [1, Node_Noise_Hex]).setVersion(1090);
addNodeObject(hid, "Sort Input", s_node_grid_hex_noise, "Node_Iterator_Sort_Input", [1, Node_Iterator_Sort_Input]);
addNodeObject(hid, "Sort Output", s_node_grid_hex_noise, "Node_Iterator_Sort_Output", [1, Node_Iterator_Sort_Output]);
addNodeObject(node, "Onion Skin", s_node_cache, "Node_Onion_Skin", [1, Node_Onion_Skin]).setVersion(1147);
}
#endregion

View file

@ -32,6 +32,9 @@ function Panel_Animation() : PanelContent() constructor {
dope_sheet_y_max = 0;
is_scrolling = false;
dopesheet_dragging = noone;
dopesheet_drag_mx = 0;
dope_sheet_node_padding = ui(2);
ds_name_surface = surface_create_valid(tool_width - ui(16), 1);
@ -50,6 +53,7 @@ function Panel_Animation() : PanelContent() constructor {
timeline_drag_sy = 0;
timeline_drag_mx = 0;
timeline_drag_my = 0;
timeline_draggable = true;
timeline_stretch = 0;
timeline_stretch_sx = 0;
@ -64,9 +68,11 @@ function Panel_Animation() : PanelContent() constructor {
keyframe_drag_mx = 0;
keyframe_drag_my = 0;
keyframe_selecting = [];
keyframe_boxing = false;
keyframe_box_sx = -1;
keyframe_box_sy = -1;
keyframe_boxable = true;
keyframe_boxing = false;
keyframe_box_sx = -1;
keyframe_box_sy = -1;
value_hovering = noone;
value_focusing = noone;
@ -80,6 +86,12 @@ function Panel_Animation() : PanelContent() constructor {
anim_properties = ds_list_create();
tool_width_drag = false;
tool_width_start = 0;
tool_width_mx = 0;
onion_dragging = noone;
prev_cache = array_create(PROJECT.animator.frames_total);
control_buttons = [
@ -455,6 +467,7 @@ function Panel_Animation() : PanelContent() constructor {
for( var i = 0; i < ds_list_size(anim_properties); i++ ) {
var node = anim_properties[| i];
if(!show_node_outside_context && node.group != PANEL_GRAPH.getCurrentContext()) continue;
for( var j = 0; j < ds_list_size(node.inputs); j++ ) {
@ -465,6 +478,7 @@ function Panel_Animation() : PanelContent() constructor {
for(var k = 0; k < ds_list_size(prop.animators[a].values); k++) {
var t = (prop.animators[a].values[| k].time + 1) * ui(timeline_scale) + timeline_shift;
prop.animators[a].values[| k].dopesheet_x = t;
var ind = prop.animators[a].values[| k].ease_in_type == CURVE_TYPE.cut? 4 : 1;
draw_sprite_ui_uniform(THEME.timeline_keyframe, ind, t, key_y, 1, COLORS.panel_animation_keyframe_hide);
}
@ -472,6 +486,7 @@ function Panel_Animation() : PanelContent() constructor {
for(var k = 0; k < ds_list_size(prop.animator.values); k++) {
var t = (prop.animator.values[| k].time + 1) * ui(timeline_scale) + timeline_shift;
prop.animator.values[| k].dopesheet_x = t;
var ind = prop.animator.values[| k].ease_in_type == CURVE_TYPE.cut? 4 : 1;
draw_sprite_ui_uniform(THEME.timeline_keyframe, ind, t, key_y, 1, COLORS.panel_animation_keyframe_hide);
}
@ -549,12 +564,14 @@ function Panel_Animation() : PanelContent() constructor {
}
if(pHOVER && point_in_rectangle(mx, my, bar_x, 8, bar_x + min(timeline_w, timeline_shift + bar_total_w), 8 + 16)) { //top bar
if(mouse_press(mb_left, pFOCUS)) {
if(mouse_press(mb_left, pFOCUS) && timeline_draggable) {
timeline_scubbing = true;
timeline_scub_st = PROJECT.animator.current_frame;
_scrub_frame = timeline_scub_st;
}
}
timeline_draggable = true;
#endregion
gpu_set_blendmode(bm_subtract);
@ -565,7 +582,7 @@ function Panel_Animation() : PanelContent() constructor {
draw_surface_safe(timeline_surface, bar_x, bar_y);
}
function drawDopesheetLine(animator, key_y, msx, msy, _gy_val_min = 999999, _gy_val_max = -999999) {
function drawDopesheetLine(animator, key_y, msx, msy, _gy_val_min = 999999, _gy_val_max = -999999) {
var bar_total_w = PROJECT.animator.frames_total * ui(timeline_scale);
var bar_show_w = timeline_shift + bar_total_w;
var hovering = noone;
@ -775,235 +792,6 @@ function Panel_Animation() : PanelContent() constructor {
drawDopesheetLine(prop.animator, key_y, msx, msy);
}
function drawDopesheetAnimator(_node, animator, msx, msy) {
var aa = _node.group == PANEL_GRAPH.getCurrentContext()? 1 : 0.9;
var tx = tool_width - ui(16 + 16 * 3);
var ty = animator.dopesheet_y - 1;
#region keyframe control
if(pHOVER && point_in_circle(msx, msy, tx, ty, ui(6))) {
draw_sprite_ui_uniform(THEME.prop_keyframe, 0, tx, ty, 1, COLORS._main_icon_on_inner, 1);
if(mouse_press(mb_left, pFOCUS)) {
var _t = -1;
for(var k = 0; k < ds_list_size(animator.values); k++) {
var _key = animator.values[| k];
if(_key.time < PROJECT.animator.current_frame)
_t = _key.time;
}
if(_t > -1) PROJECT.animator.setFrame(_t);
}
} else
draw_sprite_ui_uniform(THEME.prop_keyframe, 0, tx, ty, 1, COLORS._main_icon_on_inner, 1);
tx = tool_width - ui(16 + 16 * 1);
if(pHOVER && point_in_circle(msx, msy, tx, ty, ui(6))) {
draw_sprite_ui_uniform(THEME.prop_keyframe, 2, tx, ty, 1, COLORS._main_icon_on_inner, 1);
if(mouse_press(mb_left, pFOCUS)) {
for(var k = 0; k < ds_list_size(animator.values); k++) {
var _key = animator.values[| k];
if(_key.time > PROJECT.animator.current_frame) {
PROJECT.animator.setFrame(_key.time);
break;
}
}
}
} else
draw_sprite_ui_uniform(THEME.prop_keyframe, 2, tx, ty, 1, COLORS._main_icon_on_inner);
#endregion
#region add keyframe
tx = tool_width - ui(16 + 16 * 2);
if(pHOVER && point_in_circle(msx, msy, tx, ty, ui(6))) {
draw_sprite_ui_uniform(THEME.prop_keyframe, 1, tx, ty, 1, COLORS._main_accent, 1);
if(mouse_press(mb_left, pFOCUS)) {
var _add = false;
for(var k = 0; k < ds_list_size(animator.values); k++) {
var _key = animator.values[| k];
if(_key.time == PROJECT.animator.current_frame) {
if(ds_list_size(animator.values) > 1)
ds_list_delete(animator.values, k);
_add = true;
break;
} else if(_key.time > PROJECT.animator.current_frame) {
ds_list_insert(animator.values, k, new valueKey(PROJECT.animator.current_frame, animator.getValue(), animator));
_add = true;
break;
}
}
if(!_add) ds_list_add(animator.values, new valueKey(PROJECT.animator.current_frame, animator.getValue(, false), animator));
}
} else
draw_sprite_ui_uniform(THEME.prop_keyframe, 1, tx, ty, 1, COLORS._main_accent);
#endregion
if(isGraphable(animator.prop)) {
tx = tool_width - ui(16);
if(pHOVER && point_in_circle(msx, msy, tx, ty, ui(8))) {
draw_sprite_ui_uniform(THEME.timeline_graph, 1, tx, ty, 1, COLORS._main_icon_on_inner, 1);
TOOLTIP = __txtx("panel_animation_show_graph", "Show graph");
if(mouse_press(mb_left, pFOCUS))
animator.prop.show_graph = !animator.prop.show_graph;
} else
draw_sprite_ui_uniform(THEME.timeline_graph, 1, tx, ty, 1, animator.prop.show_graph? COLORS._main_accent : COLORS._main_icon_on_inner);
}
tx = tool_width - ui(16 + 16 * 4.5);
if(pHOVER && point_in_circle(msx, msy, tx, ty, ui(6))) {
draw_sprite_ui_uniform(THEME.prop_on_end, animator.prop.on_end, tx, ty, 1, COLORS._main_icon_on_inner, 1);
TOOLTIP = __txtx("panel_animation_looping_mode", "Looping mode") + ": " + ON_END_NAME[animator.prop.on_end];
if(mouse_press(mb_left, pFOCUS))
animator.prop.on_end = safe_mod(animator.prop.on_end + 1, sprite_get_number(THEME.prop_on_end));
} else
draw_sprite_ui_uniform(THEME.prop_on_end, animator.prop.on_end, tx, ty, 1, COLORS._main_icon_on_inner);
if(pHOVER && point_in_circle(msx, msy, ui(22), ty - 1, ui(10))) {
draw_sprite_ui_uniform(THEME.timeline_clock, 1, ui(22), ty - 1, 1, COLORS._main_icon_on_inner, 1);
if(mouse_press(mb_left, pFOCUS)) {
animator.prop.setAnim(!animator.prop.is_anim);
updatePropertyList();
}
} else
draw_sprite_ui_uniform(THEME.timeline_clock, 1, ui(22), ty - 1, 1, COLORS._main_icon_on_inner);
var hov = pHOVER && point_in_rectangle(msx, msy, 0, ty - ui(8), w, ty + ui(8));
if(hov) {
value_hovering = animator.prop;
if(mouse_click(mb_left, pFOCUS))
value_focusing = animator.prop;
}
var cc = animator.prop.sep_axis? COLORS.axis[animator.index] : COLORS._main_text_inner;
if(hov) cc = COLORS._main_text_accent;
draw_set_color(cc);
draw_set_alpha(aa);
draw_text_add(ui(32), ty - 2, animator.getName());
draw_set_alpha(1);
}
function drawDopesheetName() {
surface_set_target(ds_name_surface);
draw_clear_alpha(COLORS.panel_bg_clear, 0);
var msx = mx - ui(8);
var msy = my - ui(8);
var lable_w = tool_width;
var _node = noone;
var _node_y = 0;
draw_set_text(f_p2, fa_left, fa_center);
var hovering = noone;
var hoverIndex = 0;
value_hovering = noone;
if(mouse_click(mb_left, pFOCUS))
value_focusing = noone;
for( var i = 0; i < ds_list_size(anim_properties); i++ ) {
_node = anim_properties[| i];
var _inContext = _node == PROJECT.globalNode || _node.group == PANEL_GRAPH.getCurrentContext();
var aa = _inContext? 1 : 0.9;
var _node_y = _node.dopesheet_y;
if(!show_node_outside_context && !_inContext) continue;
var _node_y_start = _node_y;
_node_y += dope_sheet_node_padding;
if(pHOVER && point_in_rectangle(msx, msy, ui(20), _node_y - ui(10), lable_w, _node_y + ui(10))) {
draw_sprite_stretched_ext(THEME.ui_label_bg, 0, 0, _node_y - ui(10), lable_w, ui(20), COLORS.panel_animation_dope_bg_hover, aa);
if(mouse_press(mb_left, pFOCUS))
node_ordering = _node;
} else
draw_sprite_stretched_ext(THEME.ui_label_bg, 0, 0, _node_y - ui(10), lable_w, ui(20), COLORS.panel_animation_dope_bg, aa);
if(_node == PANEL_INSPECTOR.inspecting)
draw_sprite_stretched_ext(THEME.node_active, 0, 0, _node_y - ui(10), lable_w, ui(20), COLORS._main_accent, 1);
var tx = tool_width - ui(16);
if(pHOVER && point_in_circle(msx, msy, tx, _node_y - 1, ui(10))) {
draw_sprite_ui_uniform(THEME.animate_node_go, 0, tx, _node_y - 1, 1, COLORS._main_icon_light, 1);
TOOLTIP = __txtx("panel_animation_goto", "Go to node");
if(mouse_press(mb_left, pFOCUS))
graphFocusNode(_node);
} else
draw_sprite_ui_uniform(THEME.animate_node_go, 0, tx, _node_y - 1, 1, COLORS._main_icon, 0.75);
if(pHOVER && point_in_rectangle(msx, msy, 0, _node_y - ui(10), ui(20), _node_y + ui(10))) {
draw_sprite_ui_uniform(THEME.arrow, _node.anim_show? 3 : 0, ui(10), _node_y, 1, COLORS._main_icon_light, 1);
if(mouse_press(mb_left, pFOCUS))
_node.anim_show = !_node.anim_show;
} else
draw_sprite_ui_uniform(THEME.arrow, _node.anim_show? 3 : 0, ui(10), _node_y, 1, COLORS._main_icon, 0.75);
var nodeName = "[" + _node.name + "] ";
var tw = string_width(nodeName);
draw_set_color(node_ordering == _node? COLORS._main_text_accent : COLORS._main_text);
var txx = ui(20);
if(node_name_type == 0 || node_name_type == 1 || _node.display_name == "") {
draw_set_alpha(0.4);
draw_text_add(txx, _node_y - ui(2), nodeName);
txx += tw;
}
if(node_name_type == 0 || node_name_type == 2) {
draw_set_alpha(0.9);
draw_text_add(txx, _node_y - ui(2), _node.display_name);
}
draw_set_alpha(1);
if(!_node.anim_show) {
if(pHOVER && point_in_rectangle(msx, msy, 0, _node_y_start, lable_w, _node_y + ui(22)))
hovering = _node;
continue;
}
var ty = 0;
for( var j = 0; j < ds_list_size(_node.inputs); j++ ) {
var prop = _node.inputs[| j];
if(!prop.is_anim) continue;
if(prop.sep_axis) {
for( var i = 0; i < array_length(prop.animators); i++ ) {
drawDopesheetAnimator(_node, prop.animators[i], msx, msy);
ty = prop.animators[i].dopesheet_y - 1;
}
} else {
drawDopesheetAnimator(_node, prop.animator, msx, msy);
ty = prop.animator.dopesheet_y - 1;
}
} //end prop loop
if(pHOVER && point_in_rectangle(msx, msy, 0, _node_y_start, lable_w, ty))
hovering = _node;
} //end node loop
if(hovering == noone && _node != noone)
hovering = _node;
if(hovering != noone && node_ordering != noone) {
hoverIndex = hovering.anim_priority;
rearrange_priority(node_ordering, hoverIndex);
if(mouse_release(mb_left))
node_ordering = noone;
}
surface_reset_target();
}
function drawDopesheetAnimatorKeysBG(animator, msx, msy) {
var prop_dope_y = animator.dopesheet_y;
var key_hover = noone;
@ -1125,6 +913,221 @@ function Panel_Animation() : PanelContent() constructor {
return key_hover;
}
#region label
function drawDopesheetLabelAnimator(_node, animator, msx, msy) {
var aa = _node.group == PANEL_GRAPH.getCurrentContext()? 1 : 0.9;
var tx = tool_width;
var ty = animator.dopesheet_y - 1;
#region keyframe control
tx = tool_width - ui(20 + 16 * 3);
if(buttonInstant(noone, tx - ui(6), ty - ui(6), ui(12), ui(12), [msx, msy], pFOCUS, pHOVER, "", THEME.prop_keyframe, 0, [COLORS._main_icon, COLORS._main_icon_on_inner]) == 2) {
var _t = -1;
for(var k = 0; k < ds_list_size(animator.values); k++) {
var _key = animator.values[| k];
if(_key.time < PROJECT.animator.current_frame)
_t = _key.time;
}
if(_t > -1) PROJECT.animator.setFrame(_t);
}
tx = tool_width - ui(20 + 16 * 1);
if(buttonInstant(noone, tx - ui(6), ty - ui(6), ui(12), ui(12), [msx, msy], pFOCUS, pHOVER, "", THEME.prop_keyframe, 2, [COLORS._main_icon, COLORS._main_icon_on_inner]) == 2) {
for(var k = 0; k < ds_list_size(animator.values); k++) {
var _key = animator.values[| k];
if(_key.time > PROJECT.animator.current_frame) {
PROJECT.animator.setFrame(_key.time);
break;
}
}
}
#endregion
#region add keyframe
tx = tool_width - ui(20 + 16 * 2);
if(buttonInstant(noone, tx - ui(6), ty - ui(6), ui(12), ui(12), [msx, msy], pFOCUS, pHOVER, "", THEME.prop_keyframe, 1, [COLORS._main_accent, COLORS._main_icon_on_inner]) == 2) {
var _add = false;
for(var k = 0; k < ds_list_size(animator.values); k++) {
var _key = animator.values[| k];
if(_key.time == PROJECT.animator.current_frame) {
if(ds_list_size(animator.values) > 1)
ds_list_delete(animator.values, k);
_add = true;
break;
} else if(_key.time > PROJECT.animator.current_frame) {
ds_list_insert(animator.values, k, new valueKey(PROJECT.animator.current_frame, animator.getValue(), animator));
_add = true;
break;
}
}
if(!_add) ds_list_add(animator.values, new valueKey(PROJECT.animator.current_frame, animator.getValue(, false), animator));
}
#endregion
if(isGraphable(animator.prop)) {
tx = tool_width - ui(16);
if(pHOVER && point_in_circle(msx, msy, tx, ty, ui(8))) {
draw_sprite_ui_uniform(THEME.timeline_graph, 1, tx, ty, 1, COLORS._main_icon_on_inner, 1);
TOOLTIP = __txtx("panel_animation_show_graph", "Show graph");
if(mouse_press(mb_left, pFOCUS))
animator.prop.show_graph = !animator.prop.show_graph;
} else
draw_sprite_ui_uniform(THEME.timeline_graph, 1, tx, ty, 1, animator.prop.show_graph? COLORS._main_accent : COLORS._main_icon);
}
tx = tool_width - ui(20 + 16 * 4.5);
if(pHOVER && point_in_circle(msx, msy, tx, ty, ui(6))) {
draw_sprite_ui_uniform(THEME.prop_on_end, animator.prop.on_end, tx, ty, 1, COLORS._main_icon_on_inner, 1);
TOOLTIP = __txtx("panel_animation_looping_mode", "Looping mode") + ": " + ON_END_NAME[animator.prop.on_end];
if(mouse_press(mb_left, pFOCUS))
animator.prop.on_end = safe_mod(animator.prop.on_end + 1, sprite_get_number(THEME.prop_on_end));
} else
draw_sprite_ui_uniform(THEME.prop_on_end, animator.prop.on_end, tx, ty, 1, COLORS._main_icon);
if(pHOVER && point_in_circle(msx, msy, ui(22), ty - 1, ui(10))) {
draw_sprite_ui_uniform(THEME.timeline_clock, 1, ui(22), ty - 1, 1, COLORS._main_icon_on_inner, 1);
if(mouse_press(mb_left, pFOCUS)) {
animator.prop.setAnim(!animator.prop.is_anim);
updatePropertyList();
}
} else
draw_sprite_ui_uniform(THEME.timeline_clock, 1, ui(22), ty - 1, 1, COLORS._main_icon);
var hov = pHOVER && point_in_rectangle(msx, msy, 0, ty - ui(8), w, ty + ui(8));
if(hov) {
value_hovering = animator.prop;
if(mouse_click(mb_left, pFOCUS))
value_focusing = animator.prop;
}
var cc = animator.prop.sep_axis? COLORS.axis[animator.index] : COLORS._main_text_inner;
if(hov) cc = COLORS._main_text_accent;
draw_set_color(cc);
draw_set_alpha(aa);
draw_text_add(ui(32), ty - 2, animator.getName());
draw_set_alpha(1);
}
function drawDopesheetLabel() {
surface_set_target(ds_name_surface);
draw_clear_alpha(COLORS.panel_bg_clear, 0);
var msx = mx - ui(8);
var msy = my - ui(8);
var lable_w = tool_width;
var _node = noone;
var _node_y = 0;
draw_set_text(f_p2, fa_left, fa_center);
var hovering = noone;
var hoverIndex = 0;
value_hovering = noone;
if(mouse_click(mb_left, pFOCUS))
value_focusing = noone;
for( var i = 0; i < ds_list_size(anim_properties); i++ ) {
_node = anim_properties[| i];
var _inContext = _node == PROJECT.globalNode || _node.group == PANEL_GRAPH.getCurrentContext();
var aa = _inContext? 1 : 0.9;
var _node_y = _node.dopesheet_y;
if(!show_node_outside_context && !_inContext) continue;
var _node_y_start = _node_y;
_node_y += dope_sheet_node_padding;
if(pHOVER && point_in_rectangle(msx, msy, ui(20), _node_y - ui(10), lable_w, _node_y + ui(10))) {
draw_sprite_stretched_ext(THEME.ui_label_bg, 0, 0, _node_y - ui(10), lable_w, ui(20), COLORS.panel_animation_dope_bg_hover, aa);
if(mouse_press(mb_left, pFOCUS))
node_ordering = _node;
} else
draw_sprite_stretched_ext(THEME.ui_label_bg, 0, 0, _node_y - ui(10), lable_w, ui(20), COLORS.panel_animation_dope_bg, aa);
if(_node == PANEL_INSPECTOR.inspecting)
draw_sprite_stretched_ext(THEME.node_active, 0, 0, _node_y - ui(10), lable_w, ui(20), COLORS._main_accent, 1);
var tx = tool_width - ui(10);
if(buttonInstant(THEME.button_hide, tx - ui(8), _node_y - ui(8), ui(16), ui(16), [msx, msy], pFOCUS, pHOVER,
__txtx("panel_animation_goto", "Go to node"), THEME.animate_node_go, 0, COLORS._main_icon) == 2) {
graphFocusNode(_node);
}
if(pHOVER && point_in_rectangle(msx, msy, 0, _node_y - ui(10), ui(20), _node_y + ui(10))) {
draw_sprite_ui_uniform(THEME.arrow, _node.anim_show? 3 : 0, ui(10), _node_y, 1, COLORS._main_icon_light, 1);
if(mouse_press(mb_left, pFOCUS))
_node.anim_show = !_node.anim_show;
} else
draw_sprite_ui_uniform(THEME.arrow, _node.anim_show? 3 : 0, ui(10), _node_y, 1, COLORS._main_icon, 0.75);
draw_set_font(f_p3);
var nodeName = "[" + _node.name + "] ";
var tw = string_width(nodeName);
draw_set_color(node_ordering == _node? COLORS._main_text_accent : COLORS._main_text);
var txx = ui(20);
if(node_name_type == 0 || node_name_type == 1 || _node.display_name == "") {
draw_set_alpha(0.4);
draw_text_add(txx, _node_y - ui(2), nodeName);
txx += tw;
}
draw_set_font(f_p2);
if(node_name_type == 0 || node_name_type == 2) {
draw_set_alpha(0.9);
draw_text_add(txx, _node_y - ui(2), _node.display_name);
}
draw_set_alpha(1);
if(!_node.anim_show) {
if(pHOVER && point_in_rectangle(msx, msy, 0, _node_y_start, lable_w, _node_y + ui(22)))
hovering = _node;
continue;
}
var ty = 0;
for( var j = 0; j < ds_list_size(_node.inputs); j++ ) {
var prop = _node.inputs[| j];
if(!prop.is_anim) continue;
if(prop.sep_axis) {
for( var i = 0; i < array_length(prop.animators); i++ ) {
drawDopesheetLabelAnimator(_node, prop.animators[i], msx, msy);
ty = prop.animators[i].dopesheet_y - 1;
}
} else {
drawDopesheetLabelAnimator(_node, prop.animator, msx, msy);
ty = prop.animator.dopesheet_y - 1;
}
} //end prop loop
if(pHOVER && point_in_rectangle(msx, msy, 0, _node_y_start, lable_w, ty))
hovering = _node;
} //end node loop
if(hovering == noone && _node != noone)
hovering = _node;
if(hovering != noone && node_ordering != noone) {
hoverIndex = hovering.anim_priority;
rearrange_priority(node_ordering, hoverIndex);
if(mouse_release(mb_left))
node_ordering = noone;
}
surface_reset_target();
}
#endregion
function drawDopesheet() {
var bar_x = tool_width + ui(16);
var bar_y = h - timeline_h - ui(10);
@ -1189,7 +1192,7 @@ function Panel_Animation() : PanelContent() constructor {
draw_sprite_stretched_ext(THEME.ui_panel_bg, 2, 0, 0, _bg_w, dope_sheet_h, COLORS.panel_animation_timeline_blend, 1);
dope_sheet_y_max = 0;
var key_y = ui(24) + dope_sheet_y;
var key_y = ui(32) + dope_sheet_y;
for( var i = 0; i < ds_list_size(anim_properties); i++ ) {
var _node = anim_properties[| i];
@ -1397,12 +1400,69 @@ function Panel_Animation() : PanelContent() constructor {
}
#endregion
var key_hover = noone;
#region drag dopesheet
//if(dopesheet_dragging != noone) {
// var dx = floor((msx - dopesheet_drag_mx) / timeline_scale);
// if(abs(dx) >= 1) {
// switch(dopesheet_dragging[1]) {
// case 0 : //move both
// break;
// case 1 : //move start
// break;
// case 2 : //move end
// break;
// }
// dopesheet_drag_mx = msx;
// }
// if(mouse_release(mb_left))
// dopesheet_dragging = noone;
//}
#endregion
#region draw graph, easing line
var key_hover = noone;
for( var i = 0; i < ds_list_size(anim_properties); i++ ) {
var _node = anim_properties[| i];
if(!show_node_outside_context && _node.group != PANEL_GRAPH.getCurrentContext()) continue;
if(_node.active_index > -1) {
var active_inp = _node.inputs[| _node.active_index];
var node_y = _node.dopesheet_y + ui(2);
var ot = 0, ov = true;
var x0 = 0, x1 = 0;
for( var i = 0; i < ds_list_size(active_inp.animator.values); i++ ) {
var k = active_inp.animator.values[| i];
var t = k.time;
var v = k.value;
if(t > ot && ov) {
x0 = (ot + 1) * ui(timeline_scale) + timeline_shift;
x1 = ( t + 1) * ui(timeline_scale) + timeline_shift;
var aa = 0.25;
draw_sprite_stretched_ext(THEME.timeline_dopesheet_bg, 0, x0, node_y - ui(4), x1 - x0, ui(8), _node.dopesheet_color, aa);
}
ot = t;
ov = v;
}
t = PROJECT.animator.frames_total - 1;
if(t > ot && ov) {
x0 = (ot + 1) * ui(timeline_scale) + timeline_shift;
x1 = ( t + 1) * ui(timeline_scale) + timeline_shift;
var aa = 0.25;
draw_sprite_stretched_ext(THEME.timeline_dopesheet_bg, 0, x0, node_y - ui(4), x1 - x0, ui(8), _node.dopesheet_color, aa);
}
}
if(!_node.anim_show) continue;
for( var j = 0; j < ds_list_size(_node.inputs); j++ ) {
var prop = _node.inputs[| j];
@ -1459,7 +1519,7 @@ function Panel_Animation() : PanelContent() constructor {
}
}
#endregion
if(pHOVER && point_in_rectangle(msx, msy, 0, ui(18), dope_sheet_w, dope_sheet_h)) {
if(mouse_press(mb_left, pFOCUS) || mouse_press(mb_right, pFOCUS)) {
if(key_hover == noone) {
@ -1488,12 +1548,14 @@ function Panel_Animation() : PanelContent() constructor {
}
} else if(stagger_mode == 2) {
stagger_mode = 0;
} else if(key_hover == noone) {
} else if(key_hover == noone && keyframe_boxable) {
keyframe_boxing = true;
keyframe_box_sx = msx;
keyframe_box_sy = msy;
}
}
keyframe_boxable = true;
}
if(mouse_press(mb_right, pFOCUS)) {
@ -1524,10 +1586,68 @@ function Panel_Animation() : PanelContent() constructor {
draw_set_text(f_p2, fa_right, fa_top, COLORS._main_text_sub);
draw_text_add(bar_line_x - ui(2), PANEL_PAD, string(i));
}
if(PROJECT.onion_skin.enabled) { //ONION SKIN
var rang = PROJECT.onion_skin.range;
var colr = PROJECT.onion_skin.color;
var fr = PROJECT.animator.current_frame + 1;
var tx = fr * ui(timeline_scale) + timeline_shift;
var sx = (fr + rang[0]) * ui(timeline_scale) + timeline_shift;
var ex = (fr + rang[1]) * ui(timeline_scale) + timeline_shift;
var y0 = PANEL_PAD;
var y1 = hh;
var yc = (y0 + y1) / 2;
draw_sprite_stretched_ext(THEME.timeline_onion_skin, 0, sx, y0, tx - sx, y1 - y0, colr[0], 1);
draw_sprite_stretched_ext(THEME.timeline_onion_skin, 1, tx, y0, ex - tx, y1 - y0, colr[1], 1);
var _sx = (fr + rang[0]) * ui(timeline_scale) + timeline_shift - ui(8);
var _ex = (fr + rang[1]) * ui(timeline_scale) + timeline_shift + ui(8);
if(point_in_circle(msx, msy, _sx, yc, ui(8))) {
draw_sprite_ext(THEME.arrow, 2, _sx, yc, 1, 1, 0, colr[0], 1);
if(mouse_press(mb_left, pFOCUS))
onion_dragging = 0;
timeline_draggable = false;
} else
draw_sprite_ext(THEME.arrow, 2, _sx, yc, 1, 1, 0, colr[0], 0.5);
if(point_in_circle(msx, msy, _ex, yc, ui(8))) {
draw_sprite_ext(THEME.arrow, 0, _ex, yc, 1, 1, 0, colr[1], 1);
if(mouse_press(mb_left, pFOCUS))
onion_dragging = 1;
timeline_draggable = false;
} else
draw_sprite_ext(THEME.arrow, 0, _ex, yc, 1, 1, 0, colr[1], 0.5);
if(onion_dragging != noone) {
if(onion_dragging == 0) {
var mf = round((msx - timeline_shift + ui(8)) / ui(timeline_scale)) - fr;
mf = min(mf, 0);
if(PROJECT.onion_skin.range[0] != mf) {
PROJECT.onion_skin.range[0] = mf;
}
} else if(onion_dragging == 1) {
var mf = round((msx - timeline_shift - ui(8)) / ui(timeline_scale)) - fr;
mf = max(mf, 0);
if(PROJECT.onion_skin.range[1] != mf) {
PROJECT.onion_skin.range[1] = mf;
}
}
if(mouse_release(mb_left))
onion_dragging = noone;
}
}
var bar_line_x = (PROJECT.animator.current_frame + 1) * ui(timeline_scale) + timeline_shift;
var cc = PROJECT.animator.is_playing? COLORS._main_value_positive : COLORS._main_accent;
draw_set_color(cc);
draw_set_font(f_p2);
draw_line(bar_line_x, PANEL_PAD, bar_line_x, dope_sheet_h);
@ -1545,7 +1665,7 @@ function Panel_Animation() : PanelContent() constructor {
gpu_set_blendmode(bm_normal);
surface_reset_target();
drawDopesheetName();
drawDopesheetLabel();
draw_sprite_stretched(THEME.ui_panel_bg, 1, ui(8), ui(8), tool_width, dope_sheet_h);
draw_surface_safe(ds_name_surface, ui(8), ui(8));
@ -1661,15 +1781,42 @@ function Panel_Animation() : PanelContent() constructor {
txt = __txtx("panel_animation_keyframe_override", "Override Keyframe");
if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(24), [mx, my], pFOCUS, pHOVER, txt, THEME.keyframe_override, global.FLAG.keyframe_override) == 2)
global.FLAG.keyframe_override = !global.FLAG.keyframe_override;
by += ui(28);
txt = __txt("Onion skin");
if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(24), [mx, my], pFOCUS, pHOVER, txt, THEME.onion_skin,, PROJECT.onion_skin.enabled? c_white : COLORS._main_icon) == 2)
PROJECT.onion_skin.enabled = !PROJECT.onion_skin.enabled;
}
function drawContent(panel) {
draw_clear_alpha(COLORS.panel_bg_clear, 0);
if(tool_width_drag) {
CURSOR = cr_size_we;
tool_width = tool_width_start + (mx - tool_width_mx);
tool_width = clamp(tool_width, ui(224), w - ui(128));
onResize();
if(mouse_release(mb_left))
tool_width_drag = false;
}
if(w >= ui(348)) {
drawTimeline();
if(dope_sheet_h > 8)
if(dope_sheet_h > 8) {
drawDopesheet();
if(pHOVER && point_in_rectangle(mx, my, tool_width + ui(10), ui(8), tool_width + ui(12), ui(8) + dope_sheet_h)) {
CURSOR = cr_size_we;
if(mouse_press(mb_left, pFOCUS)) {
tool_width_drag = true;
tool_width_start = tool_width;
tool_width_mx = mx;
}
}
}
}
drawAnimationControl();

View file

@ -541,7 +541,7 @@ function Panel_Inspector() : PanelContent() constructor {
);
if(jun.extract_node != "") {
array_insert(_menuItem, 2, menuItem(__txtx("panel_inspector_extract", "Extract to node"), function() {
array_insert(_menuItem, 2, menuItem(__txtx("panel_inspector_extract", "Extract..."), function() {
__dialog_junction.extractNode();
}));
}

View file

@ -127,6 +127,15 @@ function Panel_Preview() : PanelContent() constructor {
gs.anchor = ANCHOR.bottom | ANCHOR.left;
}
],
[
THEME.onion_skin,
function() { return 0; },
function() { return __txt("Onion Skin") },
function(param) {
var gs = dialogCall(o_dialog_preview_onion_skin, param.x, param.y);
gs.anchor = ANCHOR.bottom | ANCHOR.left;
}
],
];
actions = [
@ -320,6 +329,48 @@ function Panel_Preview() : PanelContent() constructor {
right_menu_y += ui(40);
}
/**
* Function Description
* @param {Struct.Node} node Description
* @param {any*} psx Description
* @param {any*} psy Description
* @param {any*} ss Description
*/
function drawOnionSkin(node, psx, psy, ss) {
var _surf = preview_surface[0];
var _rang = PROJECT.onion_skin.range;
var _alph = PROJECT.onion_skin.alpha;
var _colr = PROJECT.onion_skin.color;
var _step = PROJECT.onion_skin.step;
var _top = PROJECT.onion_skin.on_top;
var fr = PROJECT.animator.current_frame;
var st = min(_rang[0], _rang[1]);
var ed = max(_rang[0], _rang[1]);
st = sign(st) * floor(abs(st) / _step) * _step;
ed = sign(ed) * floor(abs(ed) / _step) * _step;
st += fr;
ed += fr;
for( var i = st; i <= ed; i += _step ) {
var surf = node.getCacheFrame(i);
if(!is_surface(surf)) continue;
var aa = power(_alph, abs((i - fr) / _step));
var cc = c_white;
if(i < fr) cc = _colr[0];
else if(i > fr) cc = _colr[1];
draw_surface_ext_safe(surf, psx, psy, ss, ss, 0, cc, aa);
}
if(_top) draw_surface_ext_safe(_surf, psx, psy, ss, ss);
}
function drawNodePreview() {
var ss = canvas_s;
var psx = 0, psy = 0;
@ -355,16 +406,23 @@ function Panel_Preview() : PanelContent() constructor {
if(_node)
title = _node.display_name == ""? _node.name : _node.display_name;
if(splitView == 0 && tileMode == 0 && is_surface(preview_surface[0])) {
var node = preview_node[0];
node.previewing = 1;
var aa = node.preview_alpha;
if(PROJECT.onion_skin.enabled) {
drawOnionSkin(node, psx, psy, ss);
} else
draw_surface_ext_safe(preview_surface[0], psx, psy, ss, ss, 0, c_white, aa);
}
switch(splitView) {
case 0 :
if(is_surface(preview_surface[0])) {
preview_node[0].previewing = 1;
switch(tileMode) {
case 0 :
var aa = preview_node[0].preview_alpha;
draw_surface_ext_safe(preview_surface[0], psx, psy, ss, ss, 0, c_white, aa);
break;
case 1 :
tile_surface = surface_verify(tile_surface, w, surface_get_height(preview_surface[0]) * ss);
surface_set_target(tile_surface);

View file

@ -34,6 +34,7 @@ function save_serialize(project = PROJECT) {
_map.metadata = METADATA.serialize();
_map.global_node = project.globalNode.serialize();
_map.onion_skin = project.onion_skin;
var prev = PANEL_PREVIEW.getNodePreviewSurface();
if(!is_surface(prev)) _map.preview = "";

View file

@ -12,6 +12,7 @@ function Theme() constructor {
add = noone;
animate_clock = noone;
animate_node_go = noone;
animate_onion_skin = noone;
animation_setting = noone;
animation_timing = noone;
animation_stretch = noone;
@ -143,6 +144,7 @@ function Theme() constructor {
bone = noone;
tab_exit = noone;
icon_save_all = noone;
onion_skin = noone;
inspector_area = noone;
inspector_area_type = noone;
@ -204,6 +206,7 @@ function Theme() constructor {
ui_label_bg = noone;
toolbar = noone;
ui_selection = noone;
timeline_dopesheet_bg = noone;
cursor_path_add = noone;
cursor_path_anchor = noone;
@ -226,6 +229,8 @@ function Theme() constructor {
timeline_keyframe_selecting = noone;
timeline_key_halign = noone;
timeline_key_valign = noone;
timeline_onion_skin = noone;
obj_distribute_h = noone;
obj_distribute_v = noone;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,74 @@
{
"resourceType": "GMSprite",
"resourceVersion": "1.0",
"name": "s_node_rate_remap",
"bbox_bottom": 58,
"bbox_left": 3,
"bbox_right": 60,
"bbox_top": 5,
"bboxMode": 0,
"collisionKind": 1,
"collisionTolerance": 0,
"DynamicTexturePage": false,
"edgeFiltering": false,
"For3D": false,
"frames": [
{"resourceType":"GMSpriteFrame","resourceVersion":"1.1","name":"acd93f8b-8e04-48f8-ac8e-845ce0d9b1d1",},
],
"gridX": 0,
"gridY": 0,
"height": 64,
"HTile": false,
"layers": [
{"resourceType":"GMImageLayer","resourceVersion":"1.0","name":"c3131a1f-9f99-4129-8e11-3eff1e96b972","blendMode":0,"displayName":"default","isLocked":false,"opacity":100.0,"visible":true,},
],
"nineSlice": null,
"origin": 4,
"parent": {
"name": "animation",
"path": "folders/nodes/icons/animation.yy",
},
"preMultiplyAlpha": false,
"sequence": {
"resourceType": "GMSequence",
"resourceVersion": "1.4",
"name": "s_node_rate_remap",
"autoRecord": true,
"backdropHeight": 768,
"backdropImageOpacity": 0.5,
"backdropImagePath": "",
"backdropWidth": 1366,
"backdropXOffset": 0.0,
"backdropYOffset": 0.0,
"events": {"resourceType":"KeyframeStore<MessageEventKeyframe>","resourceVersion":"1.0","Keyframes":[],},
"eventStubScript": null,
"eventToFunction": {},
"length": 1.0,
"lockOrigin": false,
"moments": {"resourceType":"KeyframeStore<MomentsEventKeyframe>","resourceVersion":"1.0","Keyframes":[],},
"playback": 1,
"playbackSpeed": 30.0,
"playbackSpeedType": 0,
"showBackdrop": true,
"showBackdropImage": false,
"timeUnits": 1,
"tracks": [
{"resourceType":"GMSpriteFramesTrack","resourceVersion":"1.0","name":"frames","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"resourceType":"KeyframeStore<SpriteFrameKeyframe>","resourceVersion":"1.0","Keyframes":[
{"resourceType":"Keyframe<SpriteFrameKeyframe>","resourceVersion":"1.0","Channels":{"0":{"resourceType":"SpriteFrameKeyframe","resourceVersion":"1.0","Id":{"name":"acd93f8b-8e04-48f8-ac8e-845ce0d9b1d1","path":"sprites/s_node_rate_remap/s_node_rate_remap.yy",},},},"Disabled":false,"id":"d1361911-0b2f-4ad4-86ef-0a1e6da538ea","IsCreationKey":false,"Key":0.0,"Length":1.0,"Stretch":false,},
],},"modifiers":[],"spriteId":null,"trackColour":0,"tracks":[],"traits":0,},
],
"visibleRange": null,
"volume": 1.0,
"xorigin": 32,
"yorigin": 32,
},
"swatchColours": null,
"swfPrecision": 2.525,
"textureGroupId": {
"name": "Default",
"path": "texturegroups/Default",
},
"type": 0,
"VTile": false,
"width": 64,
}