mirror of
https://github.com/galacean/engine.git
synced 2026-06-02 00:31:57 +08:00
Fix UICanvas adaptation issues (#2580)
* fix: the UICanvas.renderMode is CanvasRenderMode.ScreenSpaceCamera bug * fix: the issue with incorrect cache value of UICanvas._getCenter * fix: the issue that UICanvas did not refresh in time when setting the camera multiple times
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
DisorderedArray,
|
||||
Entity,
|
||||
EntityModifyFlags,
|
||||
Logger,
|
||||
MathUtil,
|
||||
Matrix,
|
||||
Ray,
|
||||
@@ -153,9 +154,22 @@ export class UICanvas extends Component implements IElement {
|
||||
set renderCamera(value: Camera) {
|
||||
const preCamera = this._renderCamera;
|
||||
if (preCamera !== value) {
|
||||
this._isSameOrChildEntity(value.entity) &&
|
||||
Logger.warn(
|
||||
"Camera entity matching or nested within the canvas entity disables canvas auto-adaptation in ScreenSpaceCamera mode."
|
||||
);
|
||||
this._renderCamera = value;
|
||||
this._updateCameraObserver();
|
||||
this._setRealRenderMode(this._getRealRenderMode());
|
||||
const preRenderMode = this._realRenderMode;
|
||||
const curRenderMode = this._getRealRenderMode();
|
||||
if (preRenderMode === curRenderMode) {
|
||||
if (curRenderMode === CanvasRenderMode.ScreenSpaceCamera) {
|
||||
this._adapterPoseInScreenSpace();
|
||||
this._adapterSizeInScreenSpace();
|
||||
}
|
||||
} else {
|
||||
this._setRealRenderMode(curRenderMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,8 +332,9 @@ export class UICanvas extends Component implements IElement {
|
||||
case CanvasRenderMode.WorldSpace:
|
||||
const boundsCenter = this._getCenter();
|
||||
if (isOrthographic) {
|
||||
Vector3.subtract(boundsCenter, cameraPosition, boundsCenter);
|
||||
this._sortDistance = Vector3.dot(boundsCenter, cameraForward);
|
||||
const distance = UICanvas._tempVec3;
|
||||
Vector3.subtract(boundsCenter, cameraPosition, distance);
|
||||
this._sortDistance = Vector3.dot(distance, cameraForward);
|
||||
} else {
|
||||
this._sortDistance = Vector3.distanceSquared(boundsCenter, cameraPosition);
|
||||
}
|
||||
@@ -382,15 +397,18 @@ export class UICanvas extends Component implements IElement {
|
||||
const transform = this.entity.transform;
|
||||
const realRenderMode = this._realRenderMode;
|
||||
if (realRenderMode === CanvasRenderMode.ScreenSpaceCamera) {
|
||||
const { transform: cameraTransform } = this._renderCamera.entity;
|
||||
const { worldPosition: cameraWorldPosition, worldForward: cameraWorldForward } = cameraTransform;
|
||||
const distance = this._distance;
|
||||
transform.setWorldPosition(
|
||||
cameraWorldPosition.x + cameraWorldForward.x * distance,
|
||||
cameraWorldPosition.y + cameraWorldForward.y * distance,
|
||||
cameraWorldPosition.z + cameraWorldForward.z * distance
|
||||
);
|
||||
transform.worldRotationQuaternion.copyFrom(cameraTransform.worldRotationQuaternion);
|
||||
const cameraEntity = this._renderCamera.entity;
|
||||
if (!this._isSameOrChildEntity(cameraEntity)) {
|
||||
const { transform: cameraTransform } = cameraEntity;
|
||||
const { worldPosition: cameraWorldPosition, worldForward: cameraWorldForward } = cameraTransform;
|
||||
const distance = this._distance;
|
||||
transform.setWorldPosition(
|
||||
cameraWorldPosition.x + cameraWorldForward.x * distance,
|
||||
cameraWorldPosition.y + cameraWorldForward.y * distance,
|
||||
cameraWorldPosition.z + cameraWorldForward.z * distance
|
||||
);
|
||||
transform.worldRotationQuaternion.copyFrom(cameraTransform.worldRotationQuaternion);
|
||||
}
|
||||
} else {
|
||||
const { canvas } = this.engine;
|
||||
transform.setWorldPosition(canvas.width * 0.5, canvas.height * 0.5, 0);
|
||||
@@ -646,6 +664,15 @@ export class UICanvas extends Component implements IElement {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _isSameOrChildEntity(cameraEntity: Entity): boolean {
|
||||
const canvasEntity = this.entity;
|
||||
while (cameraEntity) {
|
||||
if (cameraEntity === canvasEntity) return true;
|
||||
cameraEntity = cameraEntity.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -95,6 +95,49 @@ describe("UICanvas", async () => {
|
||||
expect(rootCanvas._isRootCanvas).to.eq(true);
|
||||
});
|
||||
|
||||
// Pose
|
||||
it("Pose Fit", () => {
|
||||
const canvasTransform = <UITransform>canvasEntity.transform;
|
||||
const canvasPosition = canvasTransform.position;
|
||||
rootCanvas.referenceResolution = new Vector2(800, 600);
|
||||
rootCanvas.renderMode = CanvasRenderMode.ScreenSpaceCamera;
|
||||
rootCanvas.distance = 10;
|
||||
canvasPosition.set(0, 0, 0);
|
||||
expect(canvasPosition.x).to.eq(0);
|
||||
expect(canvasPosition.y).to.eq(0);
|
||||
expect(canvasPosition.z).to.eq(0);
|
||||
|
||||
// Same entity
|
||||
const cameraSame = canvasEntity.addComponent(Camera);
|
||||
rootCanvas.renderCamera = cameraSame;
|
||||
expect(canvasPosition.x).to.eq(0);
|
||||
expect(canvasPosition.y).to.eq(0);
|
||||
expect(canvasPosition.z).to.eq(0);
|
||||
rootCanvas.distance = 100;
|
||||
expect(canvasPosition.x).to.eq(0);
|
||||
expect(canvasPosition.y).to.eq(0);
|
||||
expect(canvasPosition.z).to.eq(0);
|
||||
|
||||
// Not same entity or child entity
|
||||
rootCanvas.renderCamera = camera;
|
||||
expect(canvasPosition.x).to.eq(0);
|
||||
expect(canvasPosition.y).to.eq(0);
|
||||
expect(canvasPosition.z).to.eq(-100);
|
||||
rootCanvas.distance = 10;
|
||||
expect(canvasPosition.x).to.eq(0);
|
||||
expect(canvasPosition.y).to.eq(0);
|
||||
expect(canvasPosition.z).to.eq(-10);
|
||||
|
||||
// Child entity
|
||||
const cameraEntityChild = canvasEntity.createChild("cameraChild");
|
||||
const cameraChild = cameraEntityChild.addComponent(Camera);
|
||||
cameraEntityChild.transform.setPosition(2, 2, 2);
|
||||
rootCanvas.renderCamera = cameraChild;
|
||||
expect(canvasPosition.x).to.eq(0);
|
||||
expect(canvasPosition.y).to.eq(0);
|
||||
expect(canvasPosition.z).to.eq(-10);
|
||||
});
|
||||
|
||||
// Size
|
||||
it("Size Fit", () => {
|
||||
rootCanvas.referenceResolution = new Vector2(800, 600);
|
||||
|
||||
Reference in New Issue
Block a user