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
12 changes: 8 additions & 4 deletions src/components/modebar/buttons.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,15 +347,19 @@ function handleCamera3d(gd, ev) {
var key = sceneId + '.camera';
var scene = fullLayout[sceneId]._scene;

if(attr === 'resetDefault' || attr === 'resetLastSave') {
aobj[key] = Lib.extendDeep({}, scene.viewInitial);

aobj[key].projection = {
Copy link
Contributor

Choose a reason for hiding this comment

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

We shouldn't need this after 9e1aa7a

Copy link
Contributor

@etpinard etpinard Mar 4, 2019

Choose a reason for hiding this comment

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

Actually, you'll need to tweak aobj / key logic. In the end, aobj should look like:

aobj = {
  'scene.camera.up': {/**/},
  'scene.camera.eye': {/**/},
  'scene.camera.center': {/**/}
}

as opposed to

aobj = {
  'scene.camera': {
    up: {/**/},
    eye: {/**/},
    center: {/**/}
  }
}

type: (scene.camera._ortho) ? 'orthographic' : 'perspective'
};
}

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);
}
}

Registry.call('_guiRelayout', gd, aobj);
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: sceneLayout.camera.up.x,
y: sceneLayout.camera.up.y,
z: sceneLayout.camera.up.z
},
eye: {
x: sceneLayout.camera.eye.x,
y: sceneLayout.camera.eye.y,
z: sceneLayout.camera.eye.z
},
center: {
x: sceneLayout.camera.center.x,
y: sceneLayout.camera.center.y,
z: sceneLayout.camera.center.z
}
};
}

scene.plot(fullSceneData, fullLayout, gd.layout);
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