Add clickable keyframes to motion trails

This commit is contained in:
JannisX11 2020-10-10 18:31:56 +02:00
parent dd3bfd1873
commit 7a60e64771
6 changed files with 74 additions and 11 deletions

View File

@ -732,6 +732,11 @@ class BoneAnimator extends GeneralAnimator {
if (group_is_selected !== true && this.group) {
this.group.select();
}
Group.all.forEach(group => {
if (group.name == group.selected.name && group != Group.selected) {
duplicates = true;
}
})
function iterate(arr) {
arr.forEach((it) => {
if (it.type === 'group' && !duplicates) {
@ -1229,6 +1234,11 @@ const Animator = {
if (g.parent instanceof Group) iterate(g.parent);
}
iterate(target)
let keyframes = {};
let ba = Animation.selected.getBoneAnimator();
ba.position.forEach(kf => {
keyframes[Math.round(kf.time / step)] = kf;
})
function displayTime(time) {
Timeline.time = time;
@ -1258,11 +1268,32 @@ const Animator = {
Animator.motion_trail.add(line);
let dot_geo = new THREE.OctahedronGeometry(0.2);
let keyframe_geo = new THREE.OctahedronGeometry(1.0);
let dot_material = new THREE.MeshBasicMaterial({color: gizmo_colors.outline});
geometry.vertices.forEach(vertex => {
let mesh = new THREE.Mesh(dot_geo, dot_material);
mesh.position.copy(vertex);
Animator.motion_trail.add(mesh);
geometry.vertices.forEach((vertex, i) => {
let keyframe = keyframes[i];
if (keyframe) {
let mesh = new THREE.Mesh(keyframe_geo, dot_material);
mesh.position.copy(vertex);
Animator.motion_trail.add(mesh);
mesh.isKeyframe = true;
mesh.keyframeUUID = keyframe.uuid;
} else {
let mesh = new THREE.Mesh(dot_geo, dot_material);
mesh.position.copy(vertex);
Animator.motion_trail.add(mesh);
}
})
Animator.updateMotionTrailScale();
},
updateMotionTrailScale() {
Animator.motion_trail.children.forEach((object) => {
if (object.isLine) return;
var scaleVector = new THREE.Vector3();
var scale = scaleVector.subVectors(object.position, Preview.selected.camera.position).length() / 500;
scale = (Math.sqrt(scale)/3 + scale/1.4) * 3.8
if (Blockbench.isMobile) scale *= 4;
object.scale.set(scale, scale, scale)
})
},
preview() {
@ -1544,6 +1575,11 @@ const Animator = {
}
}
}
Blockbench.on('update_camera_position', e => {
if (Animator.open && settings.motion_trails.value && Group.selected) {
Animator.updateMotionTrailScale();
}
})
Animator.MolangParser.global_variables = {
'true': 1,

View File

@ -420,7 +420,7 @@ function updateKeyframeSelection() {
BarItems.slider_keyframe_time.update()
BarItems.keyframe_interpolation.set(Timeline.selected[0].interpolation)
}
if (settings.motion_trails.value && Group.selected) {
if (settings.motion_trails.value && Modes.animate && Animation.selected && Group.selected) {
Animator.showMotionTrail();
}
BARS.updateConditions()
@ -612,6 +612,7 @@ BARS.defineActions(function() {
if (kf.transform) kf.interpolation = sel.value;
})
Undo.finishEdit('change keyframes interpolation')
updateKeyframeSelection();
}
})
new Action('reset_keyframe', {

View File

@ -136,7 +136,7 @@ window.BedrockEntityManager = {
},
initAnimations() {
var anim_list = BedrockEntityManager.client_entity.description.animations
var anim_list = BedrockEntityManager?.client_entity?.description?.animations
if (anim_list instanceof Object) {
let animation_names = [];
for (var key in anim_list) {

View File

@ -76,9 +76,7 @@ THREE.OrbitControls = function ( object, preview ) {
scope.preview.updateBackground()
}
Transformer.update()
if (Toolbox && Toolbox.selected.id == 'vertex_snap_tool') {
Vertexsnap.updateVertexSize();
}
Blockbench.dispatchEvent('update_camera_position', {preview: scope.preview})
};
this.onUpdate = function(call) {

View File

@ -304,6 +304,13 @@ class Preview {
}
})
}
if (Animator.open && settings.motion_trails.value && Group.selected) {
Animator.motion_trail.children.forEach(object => {
if (object.isKeyframe === true) {
objects.push(object)
}
})
}
var intersects = this.raycaster.intersectObjects( objects );
if (intersects.length > 0) {
if (intersects.length > 1 && Toolbox.selected.id == 'vertex_snap_tool') {
@ -338,6 +345,14 @@ class Preview {
cube: intersect.cube,
vertex: intersect
}
} else if (intersect.isKeyframe) {
let keyframe = Timeline.keyframes.find(kf => kf.uuid == intersect.keyframeUUID);
return {
event: event,
type: 'keyframe',
intersects: intersects,
keyframe: keyframe
}
}
} else {
return false;
@ -562,7 +577,7 @@ class Preview {
this.rclick_cooldown = true;
}, 420)
}
quad_previews.current = this;
Preview.selected = this;
if (Transformer.hoverAxis !== null || (!Keybinds.extra.preview_select.keybind.isTriggered(event) && event.which !== 0)) return;
var data = this.raycast(event);
@ -595,6 +610,11 @@ class Preview {
} else {
data.cube.select(event)
}
} else if (Animator.open && data.type == 'keyframe') {
if (data.keyframe instanceof Keyframe) {
data.keyframe.select(event).callPlayhead();
updateSelection();
}
}
if (typeof Toolbox.selected.onCanvasClick === 'function') {
Toolbox.selected.onCanvasClick(data)
@ -983,7 +1003,7 @@ class Preview {
if (quad_previews.current) {
quad_previews.current.controls.stopMovement()
}
quad_previews.current = this;
Preview.selected = this;
quad_previews.enabled = false;
$('#preview').empty()
@ -1517,6 +1537,9 @@ function initCanvas() {
updateShading()
quad_previews = {
get current() {return Preview.selected},
set current(p) {Preview.selected = p},
one: new Preview({id: 'one'}).loadAnglePreset(DefaultCameraPresets[1]),
two: main_preview,
three: new Preview({id: 'three'}).loadAnglePreset(DefaultCameraPresets[3]),

View File

@ -392,6 +392,11 @@ const Vertexsnap = {
})
}
}
Blockbench.on('update_camera_position', e => {
if (Toolbox && Toolbox.selected.id == 'vertex_snap_tool') {
Vertexsnap.updateVertexSize();
}
})
//Scale
function scaleAll(save, size) {
if (save === true) {