Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix reset camera buttons to work after switching projection between perspective and orthographic #3597

Merged
merged 8 commits into from
Mar 5, 2019
Merged
18 changes: 10 additions & 8 deletions src/components/modebar/buttons.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,8 @@ modeBarButtons.resetCameraLastSave3d = {
function handleCamera3d(gd, ev) {
var button = ev.currentTarget;
var attr = button.getAttribute('data-attr');
if(attr !== 'resetLastSave' && attr !== 'resetDefault') return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When does this happen?


var fullLayout = gd._fullLayout;
var sceneIds = fullLayout._subplots.gl3d;
var aobj = {};
Expand All @@ -347,14 +349,14 @@ function handleCamera3d(gd, ev) {
var key = sceneId + '.camera';
var scene = fullLayout[sceneId]._scene;

if(attr === 'resetDefault') {
aobj[key] = Lib.extendDeep({}, scene.cameraInitial);
aobj[key].up = null;
aobj[key].eye = null;
aobj[key].center = null;
}
else if(attr === 'resetLastSave') {
aobj[key] = Lib.extendDeep({}, scene.cameraInitial);
if(attr === 'resetLastSave') {
aobj[key + '.up'] = scene.viewInitial.up;
aobj[key + '.eye'] = scene.viewInitial.eye;
aobj[key + '.center'] = scene.viewInitial.center;
} else if(attr === 'resetDefault') {
aobj[key + '.up'] = null;
aobj[key + '.eye'] = null;
aobj[key + '.center'] = null;
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -1589,7 +1589,7 @@ function _restyle(gd, aobj, traces) {
// and figure out what kind of graphics update we need to do
for(var ai in aobj) {
if(helpers.hasParent(aobj, ai)) {
throw new Error('cannot set ' + ai + 'and a parent attribute simultaneously');
throw new Error('cannot set ' + ai + ' and a parent attribute simultaneously');
}

var vi = aobj[ai];
Expand Down Expand Up @@ -2095,7 +2095,7 @@ function _relayout(gd, aobj) {
// alter gd.layout
for(var ai in aobj) {
if(helpers.hasParent(aobj, ai)) {
throw new Error('cannot set ' + ai + 'and a parent attribute simultaneously');
throw new Error('cannot set ' + ai + ' and a parent attribute simultaneously');
}

var p = layoutNP(layout, ai);
Expand Down
22 changes: 19 additions & 3 deletions src/plots/gl3d/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,25 @@ exports.plot = function plotGl3d(gd) {
sceneLayout._scene = scene;
}

// save 'initial' camera settings for modebar button
if(!scene.cameraInitial) {
scene.cameraInitial = Lib.extendDeep({}, sceneLayout.camera);
// save 'initial' camera view settings for modebar button
if(!scene.viewInitial) {
scene.viewInitial = {
up: {
x: camera.up.x,
y: camera.up.y,
z: camera.up.z
},
eye: {
x: camera.eye.x,
y: camera.eye.y,
z: camera.eye.z
},
center: {
x: camera.center.x,
y: camera.center.y,
z: camera.center.z
}
};
}

scene.plot(fullSceneData, fullLayout, gd.layout);
Expand Down
8 changes: 4 additions & 4 deletions src/plots/gl3d/scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ function initializeGLPlot(scene, camera, pixelRatio, canvas, gl) {
if(scene.fullSceneLayout.dragmode === false) return;

var update = {};
update[scene.id + '.camera'] = getLayoutCamera(scene.camera, scene.camera._ortho);
update[scene.id + '.camera'] = getLayoutCamera(scene.camera);
scene.saveCamera(gd.layout);
scene.graphDiv.emit('plotly_relayout', update);
};
Expand Down Expand Up @@ -758,19 +758,19 @@ function getOrbitCamera(camera) {

// getLayoutCamera :: orbit_camera_coords -> plotly_coords
// inverse of getOrbitCamera
function getLayoutCamera(camera, isOrtho) {
function getLayoutCamera(camera) {
return {
up: {x: camera.up[0], y: camera.up[1], z: camera.up[2]},
center: {x: camera.center[0], y: camera.center[1], z: camera.center[2]},
eye: {x: camera.eye[0], y: camera.eye[1], z: camera.eye[2]},
projection: {type: (isOrtho === true) ? 'orthographic' : 'perspective'}
projection: {type: (camera._ortho === true) ? 'orthographic' : 'perspective'}
};
}

// get camera position in plotly coords from 'orbit-camera' coords
proto.getCamera = function getCamera() {
this.glplot.camera.view.recalcMatrix(this.camera.view.lastT());
return getLayoutCamera(this.glplot.camera, this.glplot.camera._ortho);
return getLayoutCamera(this.glplot.camera);
};

// set camera position with a set of plotly coords
Expand Down
105 changes: 101 additions & 4 deletions test/jasmine/tests/gl3d_plot_interact_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1043,8 +1043,8 @@ describe('Test gl3d modebar handlers', function() {
it('@gl button resetCameraDefault3d should reset camera to default', function(done) {
var buttonDefault = selectButton(modeBar, 'resetCameraDefault3d');

expect(gd._fullLayout.scene._scene.cameraInitial.eye).toEqual({ x: 0.1, y: 0.1, z: 1 });
expect(gd._fullLayout.scene2._scene.cameraInitial.eye).toEqual({ x: 2.5, y: 2.5, z: 2.5 });
expect(gd._fullLayout.scene._scene.viewInitial.eye).toEqual({ x: 0.1, y: 0.1, z: 1 });
expect(gd._fullLayout.scene2._scene.viewInitial.eye).toEqual({ x: 2.5, y: 2.5, z: 2.5 });

gd.once('plotly_relayout', function() {
assertScenes(gd._fullLayout, 'camera.eye.x', 1.25);
Expand Down Expand Up @@ -1099,8 +1099,8 @@ describe('Test gl3d modebar handlers', function() {
assertCameraEye(gd._fullLayout.scene, 0.1, 0.1, 1);
assertCameraEye(gd._fullLayout.scene2, 2.5, 2.5, 2.5);

delete gd._fullLayout.scene._scene.cameraInitial;
delete gd._fullLayout.scene2._scene.cameraInitial;
delete gd._fullLayout.scene._scene.viewInitial;
delete gd._fullLayout.scene2._scene.viewInitial;

Plotly.relayout(gd, {
'scene.bgcolor': '#d3d3d3',
Expand Down Expand Up @@ -1489,6 +1489,103 @@ describe('Test gl3d relayout calls', function() {
.catch(failTest)
.then(done);
});

it('@gl should maintain projection type when resetCamera buttons clicked after switching projection type from perspective to orthographic', function(done) {
Plotly.plot(gd, {
data: [{
type: 'surface',
x: [0, 1],
y: [0, 1],
z: [[0, 1], [1, 0]]
}],
layout: {
width: 300,
height: 200,
scene: {
camera: {
eye: {
x: 2,
y: 1,
z: 0.5
}
}
}
}
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective');
})
.then(function() {
return Plotly.relayout(gd, 'scene.camera.projection.type', 'orthographic');
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic');
})
.then(function() {
return selectButton(gd._fullLayout._modeBar, 'resetCameraLastSave3d').click();
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic');
})
.then(function() {
return selectButton(gd._fullLayout._modeBar, 'resetCameraDefault3d').click();
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic');
})
.catch(failTest)
.then(done);
});

it('@gl should maintain projection type when resetCamera buttons clicked after switching projection type from orthographic to perspective', function(done) {
Plotly.plot(gd, {
data: [{
type: 'surface',
x: [0, 1],
y: [0, 1],
z: [[0, 1], [1, 0]]
}],
layout: {
width: 300,
height: 200,
scene: {
camera: {
eye: {
x: 2,
y: 1,
z: 0.5
},
projection: {
type: 'orthographic'
}
}
}
}
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic');
})
.then(function() {
return Plotly.relayout(gd, 'scene.camera.projection.type', 'perspective');
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective');
})
.then(function() {
return selectButton(gd._fullLayout._modeBar, 'resetCameraLastSave3d').click();
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective');
})
.then(function() {
return selectButton(gd._fullLayout._modeBar, 'resetCameraDefault3d').click();
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective');
})
.catch(failTest)
.then(done);
});
});

describe('Test gl3d annotations', function() {
Expand Down