Files
oops-plugin-framework/assets/libs/model-view/VMState.ts
dgflash ee47857f2b 1. 整理框架中所有组件在属性检查器中显示路径
2. 框架部分源码关联在线文档
2024-10-13 12:55:33 +08:00

299 lines
9.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
}