Files
MatchMaster/assets/Script/RainbowOldVisual.ts
T

82 lines
3.7 KiB
TypeScript

import RainbowScroll from "./prop/RainbowScroll";
const { ccclass, property } = cc._decorator;
/** C 方案只覆盖底色,方块及其附件仍使用原节点。 */
@ccclass
export default class RainbowOldVisual extends cc.Component {
@property([cc.SpriteFrame])
shapeFrames: cc.SpriteFrame[] = [];
@property([cc.SpriteFrame])
maskFrames: cc.SpriteFrame[] = [];
apply(block: any): void {
const icon: cc.Node = block.node.getChildByName("icon");
const frame = this.shapeFrames[block.block_Info.block];
const maskFrame = this.maskFrames[block.block_Info.block];
const bg = this.node.getChildByName("bg");
const mask = this.node.getChildByName("mask");
this.node.setPosition(icon.position);
this.node.setAnchorPoint(icon.getAnchorPoint());
this.node.setContentSize(icon.getContentSize());
this.node.setScale(icon.scaleX, icon.scaleY);
this.node.angle = icon.angle;
this.node.setSiblingIndex(icon.getSiblingIndex());
const sprite = bg.getComponent(cc.Sprite);
sprite.sizeMode = cc.Sprite.SizeMode.CUSTOM;
sprite.trim = false;
sprite.spriteFrame = frame;
mask.getComponent(cc.Mask).spriteFrame = maskFrame;
this.alignFrame(bg, frame, icon);
// 共用 bg 的原画布布局,保留 mask 图片中的内收边距。
this.alignFrame(mask, frame, icon);
this.fitColors(mask);
const scroll = this.node.getComponent(RainbowScroll);
if (scroll) scroll.refreshGeometry();
icon.active = false;
}
/** Mask 按原画布绘制,Sprite 默认按裁剪矩形绘制,先还原透明边距。 */
private alignFrame(node: cc.Node, frame: cc.SpriteFrame, icon: cc.Node): void {
const rect = frame.getRect();
const original = frame.getOriginalSize();
const offset = frame.getOffset();
const sx = icon.width / rect.width;
const sy = icon.height / rect.height;
const left = -icon.anchorX * icon.width - (offset.x + (original.width - rect.width) / 2) * sx;
const bottom = -icon.anchorY * icon.height - (offset.y + (original.height - rect.height) / 2) * sy;
node.setAnchorPoint(0.5, 0.5);
node.setContentSize(original.width * sx, original.height * sy);
node.setPosition(left + node.width / 2, bottom + node.height / 2);
node.setScale(1, 1);
}
/** 两张镜像大纹理首尾相接;每一张都足以覆盖遮罩沿滚动轴的投影。 */
private fitColors(mask: cc.Node): void {
const colors = [mask.getChildByName("color1"), mask.getChildByName("color2")];
const radians = colors[0].angle * Math.PI / 180;
const cos = Math.cos(radians), sin = Math.sin(radians);
const direction = cc.v2(-sin, cos);
const width = Math.abs(mask.width * cos) + Math.abs(mask.height * sin) + 2;
const length = Math.abs(mask.width * sin) + Math.abs(mask.height * cos) + 2;
colors.forEach(color => {
const scale = Math.max(1, width / (color.width * Math.abs(color.scaleX)),
length / (color.height * Math.abs(color.scaleY)));
color.setScale(color.scaleX * scale, color.scaleY * scale);
});
let end = length / 2;
colors.forEach(color => {
const colorLength = color.height * Math.abs(color.scaleY);
const center = end - colorLength / 2;
const ox = (0.5 - color.anchorX) * color.width * color.scaleX;
const oy = (0.5 - color.anchorY) * color.height * color.scaleY;
color.setPosition(direction.x * center - (cos * ox - sin * oy),
direction.y * center - (sin * ox + cos * oy));
end -= colorLength;
});
}
}