Files
2025-12-13 23:32:56 +08:00

107 lines
3.4 KiB
TypeScript

import type { EventTouch, Vec3 } from 'cc';
import { Camera, Component, Node, RenderTexture, Sprite, SpriteFrame, UITransform, _decorator, gfx } from 'cc';
const { ccclass, property } = _decorator;
/** 三维模型显示到二维精灵上 */
@ccclass('RtToSprite')
export class RtToSprite extends Component {
@property({
type: Camera,
tooltip: '渲染模型的三维摄像机'
})
camera: Camera | null = null;
@property({
type: Sprite,
tooltip: '显示模型的二维精灵组件'
})
sprite: Sprite | null = null;
@property({
tooltip: '是否触摸控制旋转'
})
rotation = false;
@property({
type: Node,
tooltip: '三维模型',
visible: function () {
//@ts-ignore
return this.rotation === true;
},
})
model: Node | null = null;
private rt: RenderTexture = new RenderTexture();
private touched = false; // 是否触摸节点
start() {
const size = this.sprite!.getComponent(UITransform)!;
this.refreshRenderTexture(size.width, size.height);
if (this.rotation) {
this.sprite!.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.sprite!.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
this.sprite!.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
this.sprite!.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
}
}
protected onTouchStart(event: EventTouch) {
this.touched = true;
}
protected onTouchMove(event: EventTouch) {
if (this.touched) {
const eulerAngles: Vec3 = this.model!.eulerAngles;
const deltaX = event.touch!.getDelta().x!;
eulerAngles.y += -deltaX;
this.model!.eulerAngles = eulerAngles;
}
}
protected onTouchEnd(event: EventTouch) {
this.touched = false;
}
/** 刷新纹理内容 */
refreshRenderTexture(w: number, h: number): void {
const colorAttachment = new gfx.ColorAttachment();
const depthStencilAttachment = new gfx.DepthStencilAttachment();
const pi = new gfx.RenderPassInfo([colorAttachment], depthStencilAttachment);
this.rt.reset({
width: w,
height: h,
passInfo: pi
});
const spriteframe: SpriteFrame = this.sprite!.spriteFrame!;
const sp: SpriteFrame = new SpriteFrame();
sp.reset({
originalSize: spriteframe.originalSize,
rect: spriteframe.rect,
offset: spriteframe.offset,
isRotate: spriteframe.rotated,
borderTop: spriteframe.insetTop,
borderLeft: spriteframe.insetLeft,
borderBottom: spriteframe.insetBottom,
borderRight: spriteframe.insetRight,
});
this.camera!.targetTexture = this.rt;
sp.texture = this.rt;
this.sprite!.spriteFrame = sp;
}
onDestroy() {
if (this.rotation) {
this.sprite!.node.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.sprite!.node.off(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
this.sprite!.node.off(Node.EventType.TOUCH_END, this.onTouchEnd, this);
this.sprite!.node.off(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
}
this.rt.destroy();
}
}