-
-
Notifications
You must be signed in to change notification settings - Fork 310
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
feat: add ortho control for camera #278
Changes from 14 commits
9e9d6d9
53fe76a
fea984a
ba38c08
6795be8
ce6999f
0f6145a
dd4d0ed
2eda587
153259e
d70d076
3a0f84f
2c8e72b
9545492
bb8e393
557ee76
73f558e
47c8267
6f11a70
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
import { Camera, Entity, Script, UpdateFlag, Vector2, Vector3 } from "oasis-engine"; | ||
|
||
/** | ||
* The camera's 2D controller, can zoom and pan. | ||
*/ | ||
export class OrthoControl extends Script { | ||
camera: Entity; | ||
cameraComp: Camera; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Useless for the class |
||
cameraMatrixDirty: UpdateFlag; | ||
|
||
private _position: Vector3 = new Vector3(); | ||
private _zoomSpeed: number = 1.0; | ||
private _zoomScale: number = 1.0; | ||
private _zoomScaleUnit: number = 25.0; | ||
private _zoomMinSize: number = 0.0; | ||
private _zoomMaxSize: number = Infinity; | ||
private _isPanStart: boolean = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. _isPanMove |
||
private _panStart: Vector2 = new Vector2(); | ||
private _panEnd: Vector2 = new Vector2(); | ||
private _panDelta: Vector2 = new Vector2(); | ||
|
||
/** | ||
* The zoom speed. | ||
*/ | ||
get zoomSpeed(): number { | ||
return this._zoomSpeed; | ||
} | ||
|
||
set zoomSpeed(value: number) { | ||
this._zoomSpeed = value; | ||
} | ||
|
||
constructor(entity: Entity) { | ||
super(entity); | ||
|
||
this.camera = entity; | ||
this.cameraComp = entity.getComponent(Camera); | ||
this.cameraMatrixDirty = entity.transform.registerWorldChangeFlag(); | ||
this.cameraMatrixDirty.flag = false; | ||
|
||
const position = this.camera.transform.position; | ||
position.cloneTo(this._position); | ||
|
||
// // @ts-ignore | ||
// this.mainElement = this.engine.canvas._webCanvas; | ||
// this.mainElement.addEventListener( | ||
// "wheel", | ||
// (e) => { | ||
// if (e.deltaY < 0) { | ||
// this.zoomIn(); | ||
// } else { | ||
// this.zoomOut(); | ||
// } | ||
// }, | ||
// false | ||
// ); | ||
// this.mainElement.addEventListener("mousedown", (e) => { | ||
// this.panStart(e.clientX, e.clientY); | ||
// }); | ||
// this.mainElement.addEventListener("mousemove", (e) => { | ||
// this.panMove(e.clientX, e.clientY); | ||
// }); | ||
// this.mainElement.addEventListener("mouseup", (e) => { | ||
// this.panEnd(); | ||
// }); | ||
} | ||
|
||
onDestroy(): void { | ||
this.cameraMatrixDirty.destroy(); | ||
} | ||
|
||
onUpdate(dt: number): void { | ||
if (!this.enabled) return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need for |
||
|
||
if (this._zoomScale !== 1) { | ||
const { cameraComp } = this; | ||
const sizeDiff = this._zoomScaleUnit * (this._zoomScale - 1); | ||
const size = cameraComp.orthographicSize + sizeDiff; | ||
cameraComp.orthographicSize = Math.max(this._zoomMinSize, Math.min(this._zoomMaxSize, size)); | ||
} | ||
|
||
this._zoomScale = 1; | ||
|
||
if (this.cameraMatrixDirty.flag) { | ||
const position = this.camera.transform.position; | ||
position.cloneTo(this._position); | ||
this.cameraMatrixDirty.flag = false; | ||
} | ||
} | ||
|
||
/** | ||
* Zoom in. | ||
*/ | ||
zoomIn(): void { | ||
this._zoomScale *= this._getZoomScale(); | ||
} | ||
|
||
/** | ||
* Zoom out. | ||
*/ | ||
zoomOut(): void { | ||
this._zoomScale /= this._getZoomScale(); | ||
} | ||
|
||
/** | ||
* Start pan. | ||
* @param x - The x-axis coordinate (unit: pixel) | ||
* @param y - The y-axis coordinate (unit: pixel) | ||
*/ | ||
panStart(x: number, y: number): void { | ||
if (this.enabled === false) return; | ||
|
||
this._isPanStart = true; | ||
this._panStart.setValue(x, y); | ||
} | ||
|
||
/** | ||
* Panning. | ||
* @param x - The x-axis coordinate (unit: pixel) | ||
* @param y - The y-axis coordinate (unit: pixel) | ||
*/ | ||
panMove(x: number, y: number): void { | ||
if (this.enabled === false || this._isPanStart === false) return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
const { _panStart: panStart, _panEnd: panEnd } = this; | ||
panEnd.setValue(x, y); | ||
Vector2.subtract(panEnd, panStart, this._panDelta); | ||
this._handlePan(); | ||
panEnd.cloneTo(panStart); | ||
} | ||
|
||
/** | ||
* End pan. | ||
*/ | ||
panEnd(): void { | ||
if (this.enabled === false) return; | ||
this._isPanStart = false; | ||
} | ||
|
||
private _getZoomScale(): number { | ||
return Math.pow(0.95, this.zoomSpeed); | ||
} | ||
|
||
private _handlePan(): void { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should update camera transform in |
||
const { width, height } = this.engine.canvas; | ||
const { x, y } = this._panDelta; | ||
const { cameraComp } = this; | ||
const doubleOrthographicSize = cameraComp.orthographicSize * 2; | ||
const width3D = doubleOrthographicSize * cameraComp.aspectRatio; | ||
const height3D = doubleOrthographicSize; | ||
const pos = this._position; | ||
pos.x -= (x * width3D) / width; | ||
pos.y += (y * height3D) / height; | ||
this.camera.transform.position = pos; | ||
this.cameraMatrixDirty.flag = false; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { FreeControl } from "./FreeControl"; | ||
export { OrbitControl } from "./OrbitControl"; | ||
export { OrthoControl } from "./OrthoControl"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need comment for class