mirror of
https://gitee.com/dgflash/oops-plugin-framework.git
synced 2026-05-07 19:07:30 +08:00
299 lines
9.2 KiB
TypeScript
299 lines
9.2 KiB
TypeScript
import { Button, CCInteger, Color, Enum, Node, Sprite, UIOpacity, UIRenderer, _decorator, color } from 'cc';
|
||
import { VMBase } from './VMBase';
|
||
import { VM } from './ViewModel';
|
||
|
||
const { ccclass, property, menu, help } = _decorator;
|
||
|
||
/** 比较条件 */
|
||
enum CONDITION {
|
||
"==", // 正常计算,比较 等于
|
||
"!=", // 正常计算,比较 不等于
|
||
">", // 正常计算,比较>
|
||
">=", // 正常计算,比较>=
|
||
"<", // 正常计算,比较<
|
||
"<=", // 正常计算,比较>=
|
||
"range" // 计算在范围内
|
||
}
|
||
|
||
enum ACTION {
|
||
NODE_ACTIVE, // 满足条件的节点激活,不满足的不激活(只对子节点的激活有效果,当前节点active = false时,组件就失去效果了,如果设置当前节点可用NODE_VISIBLE代替)
|
||
NODE_VISIBLE, // 满足条件的节点显示,不满足的不显示
|
||
NODE_OPACITY, // 满足条件的节点改变不透明度,不满足的还原255
|
||
NODE_COLOR, // 满足条件的节点改变颜色,不满足的恢复白色
|
||
COMPONENT_CUSTOM, // 自定义控制组件模式
|
||
SPRITE_GRAYSCALE, // 满足条件的节点cc.Sprite组件,纹理变黑白
|
||
BUTTON_INTERACTABLE, // 满足条件的节点cc.BUTTON组件,
|
||
}
|
||
|
||
enum CHILD_MODE_TYPE {
|
||
NODE_INDEX,
|
||
NODE_NAME
|
||
}
|
||
|
||
/**
|
||
* [VM-State]
|
||
* 监听数值状态,根据数值条件设置节点是否激活
|
||
*/
|
||
@ccclass
|
||
@menu('OopsFramework/Mvvm/VM-State (状态控制)')
|
||
@help('https://gitee.com/dgflash/oops-framework/wikis/pages?sort_id=12037846&doc_id=2873565')
|
||
export default class VMState extends VMBase {
|
||
@property
|
||
watchPath: string = "";
|
||
|
||
@property({
|
||
tooltip: '遍历子节点,根据子节点的名字或名字转换为值,判断值满足条件 来激活'
|
||
})
|
||
foreachChildMode: boolean = false;
|
||
|
||
@property({
|
||
type: Enum(CONDITION),
|
||
})
|
||
condition: CONDITION = CONDITION["=="];
|
||
|
||
@property({
|
||
type: Enum(CHILD_MODE_TYPE),
|
||
tooltip: '遍历子节点,根据子节点的名字转换为值,判断值满足条件 来激活',
|
||
visible: function () {
|
||
// @ts-ignore
|
||
return this.foreachChildMode === true;
|
||
}
|
||
})
|
||
foreachChildType: CHILD_MODE_TYPE = CHILD_MODE_TYPE.NODE_INDEX;
|
||
|
||
@property({
|
||
displayName: 'Value: a',
|
||
visible: function () {
|
||
// @ts-ignore
|
||
return this.foreachChildMode === false;
|
||
}
|
||
})
|
||
valueA: number = 0;
|
||
|
||
@property({
|
||
displayName: 'Value: b',
|
||
visible: function () {
|
||
// @ts-ignore
|
||
return this.foreachChildMode === false && this.condition === CONDITION.range;
|
||
}
|
||
})
|
||
valueB: number = 0;
|
||
|
||
@property({
|
||
type: Enum(ACTION),
|
||
tooltip: '一旦满足条件就对节点执行操作'
|
||
})
|
||
valueAction: ACTION = ACTION.NODE_ACTIVE;
|
||
|
||
@property({
|
||
visible: function () {
|
||
// @ts-ignore
|
||
return this.valueAction === ACTION.NODE_OPACITY;
|
||
},
|
||
range: [0, 255],
|
||
type: CCInteger,
|
||
displayName: 'Action Opacity'
|
||
})
|
||
valueActionOpacity: number = 0;
|
||
|
||
@property({
|
||
visible: function () {
|
||
// @ts-ignore
|
||
return this.valueAction === ACTION.NODE_COLOR
|
||
},
|
||
displayName: 'Action Color'
|
||
})
|
||
valueActionColor: Color = color(155, 155, 155);
|
||
|
||
@property({
|
||
visible: function () {
|
||
// @ts-ignore
|
||
return this.valueAction === ACTION.COMPONENT_CUSTOM
|
||
},
|
||
displayName: 'Component Name'
|
||
})
|
||
valueComponentName: string = '';
|
||
|
||
@property({
|
||
visible: function () {
|
||
// @ts-ignore
|
||
return this.valueAction === ACTION.COMPONENT_CUSTOM
|
||
},
|
||
displayName: 'Component Property'
|
||
})
|
||
valueComponentProperty: string = '';
|
||
|
||
@property({
|
||
visible: function () {
|
||
// @ts-ignore
|
||
return this.valueAction === ACTION.COMPONENT_CUSTOM
|
||
},
|
||
displayName: 'Default Value'
|
||
})
|
||
valueComponentDefaultValue: string = '';
|
||
|
||
@property({
|
||
visible: function () {
|
||
// @ts-ignore
|
||
return this.valueAction === ACTION.COMPONENT_CUSTOM;
|
||
},
|
||
displayName: 'Action Value'
|
||
})
|
||
valueComponentActionValue: string = '';
|
||
|
||
@property({
|
||
type: [Node],
|
||
tooltip: '需要执行条件的节点,如果不填写则默认会执行本节点以及本节点的所有子节点 的状态'
|
||
})
|
||
watchNodes: Node[] = [];
|
||
|
||
onLoad() {
|
||
super.onLoad();
|
||
// 如果数组里没有监听值,那么默认把所有子节点给监听了
|
||
if (this.watchNodes.length == 0) {
|
||
if (this.valueAction !== ACTION.NODE_ACTIVE && this.foreachChildMode === false) {
|
||
this.watchNodes.push(this.node);
|
||
}
|
||
this.watchNodes = this.watchNodes.concat(this.node.children);
|
||
}
|
||
}
|
||
|
||
start() {
|
||
if (this.enabled) {
|
||
this.onValueInit();
|
||
}
|
||
}
|
||
|
||
// 当值初始化时
|
||
protected onValueInit() {
|
||
let value = VM.getValue(this.watchPath);
|
||
this.checkNodeFromValue(value);
|
||
}
|
||
|
||
// 当值被改变时
|
||
protected onValueChanged(newVar: any, oldVar: any, pathArr: any[]) {
|
||
this.checkNodeFromValue(newVar);
|
||
}
|
||
|
||
// 检查节点值更新
|
||
private checkNodeFromValue(value: any) {
|
||
if (this.foreachChildMode) {
|
||
this.watchNodes.forEach((node, index) => {
|
||
let v = (this.foreachChildType === CHILD_MODE_TYPE.NODE_INDEX) ? index : node.name;
|
||
let check = this.conditionCheck(value, v);
|
||
// log('遍历模式', value, node.name, check);
|
||
this.setNodeState(node, check);
|
||
})
|
||
}
|
||
else {
|
||
let check = this.conditionCheck(value, this.valueA, this.valueB);
|
||
this.setNodesStates(check);
|
||
}
|
||
}
|
||
|
||
// 更新 多个节点 的 状态
|
||
private setNodesStates(checkState?: boolean) {
|
||
let nodes = this.watchNodes;
|
||
let check = checkState;
|
||
nodes.forEach((node) => {
|
||
this.setNodeState(node, check);
|
||
})
|
||
}
|
||
|
||
/** 更新单个节点的状态 */
|
||
private setNodeState(node: Node, checkState?: boolean) {
|
||
let n = this.valueAction;
|
||
let check = checkState;
|
||
switch (n) {
|
||
case ACTION.NODE_ACTIVE:
|
||
node.active = check ? true : false;
|
||
break;
|
||
case ACTION.NODE_VISIBLE: {
|
||
let opacity = node.getComponent(UIOpacity);
|
||
if (opacity == null)
|
||
opacity = node.addComponent(UIOpacity);
|
||
|
||
if (opacity) {
|
||
opacity.opacity = check ? 255 : 0;
|
||
}
|
||
break;
|
||
}
|
||
case ACTION.NODE_OPACITY: {
|
||
let opacity = node.getComponent(UIOpacity);
|
||
if (opacity == null)
|
||
opacity = node.addComponent(UIOpacity);
|
||
|
||
if (opacity) {
|
||
opacity.opacity = check ? this.valueActionOpacity : 255;
|
||
}
|
||
break;
|
||
}
|
||
case ACTION.NODE_COLOR: {
|
||
let uir = node.getComponent(UIRenderer);
|
||
if (uir) {
|
||
uir.color = check ? this.valueActionColor : color(255, 255, 255);
|
||
}
|
||
break;
|
||
}
|
||
case ACTION.COMPONENT_CUSTOM:
|
||
let comp: any = node.getComponent(this.valueComponentName);
|
||
if (comp == null) return;
|
||
if (this.valueComponentProperty in comp) {
|
||
comp[this.valueComponentProperty] = check ? this.valueComponentActionValue : this.valueComponentDefaultValue;
|
||
}
|
||
break;
|
||
case ACTION.SPRITE_GRAYSCALE: {
|
||
let sprite = node.getComponent(Sprite);
|
||
if (sprite) {
|
||
sprite.grayscale = check!;
|
||
}
|
||
break;
|
||
}
|
||
case ACTION.BUTTON_INTERACTABLE: {
|
||
let sprite = node.getComponent(Button);
|
||
if (sprite) {
|
||
sprite.interactable = check!;
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/** 条件检查 */
|
||
private conditionCheck(v: any, a: any, b?: any): boolean {
|
||
let cod = CONDITION;
|
||
switch (this.condition) {
|
||
case cod["=="]:
|
||
if (v == a) return true;
|
||
break;
|
||
case cod["!="]:
|
||
if (v != a) return true;
|
||
break;
|
||
case cod["<"]:
|
||
if (v < a) return true;
|
||
break;
|
||
case cod[">"]:
|
||
if (v > a) return true;
|
||
break;
|
||
case cod[">="]:
|
||
if (v >= a) return true;
|
||
break;
|
||
case cod["<"]:
|
||
if (v < a) return true;
|
||
break;
|
||
case cod["<="]:
|
||
if (v <= a) return true;
|
||
break;
|
||
case cod["range"]:
|
||
if (v >= a && v <= b) return true;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
}
|