From 7b85039b17019fdc3079fb2c7c62c3491a9aec6d Mon Sep 17 00:00:00 2001 From: YHH <359807859@qq.com> Date: Tue, 8 Jul 2025 08:55:55 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0mvvm=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 3 + .../cocos/cocos-ecs/assets/scenes/scene.scene | 2013 ++++++++++++++++- .../cocos/cocos-ecs/assets/scripts/mvvm.meta | 9 + .../cocos-ecs/assets/scripts/mvvm/TestView.ts | 87 + .../assets/scripts/mvvm/TestView.ts.meta | 9 + .../assets/scripts/mvvm/TestViewModel.ts | 38 + .../assets/scripts/mvvm/TestViewModel.ts.meta | 9 + .../assets/scripts/mvvm/UserInfoView.ts | 257 +++ .../assets/scripts/mvvm/UserInfoView.ts.meta | 9 + .../assets/scripts/mvvm/UserInfoViewModel.ts | 128 ++ .../scripts/mvvm/UserInfoViewModel.ts.meta | 9 + extensions/cocos/cocos-ecs/package-lock.json | 41 +- extensions/cocos/cocos-ecs/package.json | 5 +- thirdparty/BehaviourTree-ai | 2 +- thirdparty/mvvm-ui-framework | 1 + 15 files changed, 2599 insertions(+), 21 deletions(-) create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/mvvm.meta create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestView.ts create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestView.ts.meta create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestViewModel.ts create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestViewModel.ts.meta create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoView.ts create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoView.ts.meta create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoViewModel.ts create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoViewModel.ts.meta create mode 160000 thirdparty/mvvm-ui-framework diff --git a/.gitmodules b/.gitmodules index 45ae2206..2158ccf3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "examples/lawn-mower-demo"] path = examples/lawn-mower-demo url = https://github.com/esengine/lawn-mower-demo.git +[submodule "thirdparty/mvvm-ui-framework"] + path = thirdparty/mvvm-ui-framework + url = https://github.com/esengine/mvvm-ui-framework.git diff --git a/extensions/cocos/cocos-ecs/assets/scenes/scene.scene b/extensions/cocos/cocos-ecs/assets/scenes/scene.scene index 7771bbc5..cc65a2ce 100644 --- a/extensions/cocos/cocos-ecs/assets/scenes/scene.scene +++ b/extensions/cocos/cocos-ecs/assets/scenes/scene.scene @@ -24,6 +24,15 @@ }, { "__id__": 7 + }, + { + "__id__": 9 + }, + { + "__id__": 51 + }, + { + "__id__": 53 } ], "_active": true, @@ -58,7 +67,7 @@ }, "autoReleaseAssets": false, "_globals": { - "__id__": 9 + "__id__": 55 }, "_id": "fcbf2917-6d43-4528-8829-7ee089594879" }, @@ -308,30 +317,2008 @@ "_id": "a5SvVlMsZCrIJB1jr083gX" }, { - "__type__": "cc.SceneGlobals", - "ambient": { + "__type__": "cc.Node", + "_name": "Canvas", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 1 + }, + "_children": [ + { + "__id__": 10 + }, + { + "__id__": 12 + }, + { + "__id__": 15 + }, + { + "__id__": 18 + }, + { + "__id__": 25 + }, + { + "__id__": 28 + }, + { + "__id__": 31 + }, + { + "__id__": 38 + }, + { + "__id__": 41 + } + ], + "_active": true, + "_components": [ + { + "__id__": 48 + }, + { + "__id__": 49 + }, + { + "__id__": 50 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 640, + "y": 360, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "1cmYwsQnBPl7bierzKaJim" + }, + { + "__type__": "cc.Node", + "_name": "Camera", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 9 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 11 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 1000 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "7envQZVKNKVKTLpiFpigaB" + }, + { + "__type__": "cc.Camera", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { "__id__": 10 }, - "shadows": { - "__id__": 11 + "_enabled": true, + "__prefab": null, + "_projection": 0, + "_priority": 1073741824, + "_fov": 45, + "_fovAxis": 0, + "_orthoHeight": 360, + "_near": 1, + "_far": 2000, + "_color": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 }, - "_skybox": { + "_depth": 1, + "_stencil": 0, + "_clearFlags": 6, + "_rect": { + "__type__": "cc.Rect", + "x": 0, + "y": 0, + "width": 1, + "height": 1 + }, + "_aperture": 19, + "_shutter": 7, + "_iso": 0, + "_screenScale": 1, + "_visibility": 41943040, + "_targetTexture": null, + "_postProcess": null, + "_usePostProcess": false, + "_cameraType": -1, + "_trackingType": 0, + "_id": "c7ku0LPhFMxb0OGWOiND/d" + }, + { + "__type__": "cc.Node", + "_name": "Label", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 9 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 13 + }, + { + "__id__": 14 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "e8i8akpF9L15AGufnpTILW" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { "__id__": 12 }, - "fog": { - "__id__": 13 + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 42.255859375, + "height": 50.4 }, - "octree": { - "__id__": 14 + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 }, - "skin": { + "_id": "d3Wm3kTdVPhqGb4MSMVz70" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 12 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_string": "label", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 20, + "_fontSize": 20, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 0, + "_enableWrapText": true, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": false, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 2, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "02ZI1mD4lNe6sGyPLVQm3P" + }, + { + "__type__": "cc.Node", + "_name": "Label-001", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 9 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 16 + }, + { + "__id__": 17 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 109.294, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "56sORerhxEvZgvw9Q+60TF" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { "__id__": 15 }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 42.255859375, + "height": 50.4 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "6fb5nAWn9Azalsn2nLEcvL" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 15 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_string": "label", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 20, + "_fontSize": 20, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 0, + "_enableWrapText": true, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": false, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 2, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "c1xH6PVUdLDYe3yLOezquI" + }, + { + "__type__": "cc.Node", + "_name": "Button", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 9 + }, + "_children": [ + { + "__id__": 19 + } + ], + "_active": true, + "_components": [ + { + "__id__": 22 + }, + { + "__id__": 23 + }, + { + "__id__": 24 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": -80.591, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "d47CctbAVCZJ4WqsaTwpGd" + }, + { + "__type__": "cc.Node", + "_name": "Label", + "_objFlags": 512, + "__editorExtras__": {}, + "_parent": { + "__id__": 18 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 20 + }, + { + "__id__": 21 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "58PpI3+3NFpbdRd5GdjQQF" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 19 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 100, + "height": 40 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "5d+JlXtnBGdYGFL6GbIimZ" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 19 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_string": "button", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 20, + "_fontSize": 20, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 1, + "_enableWrapText": false, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": false, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 2, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "2cO7CckqtCHaDo3D/jDAL2" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 18 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 100, + "height": 40 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "c2jgfqnbNBzrqK0hbbASR/" + }, + { + "__type__": "cc.Sprite", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 18 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_spriteFrame": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_type": 1, + "_fillType": 0, + "_sizeMode": 0, + "_fillCenter": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_fillStart": 0, + "_fillRange": 0, + "_isTrimmedMode": true, + "_useGrayscale": false, + "_atlas": null, + "_id": "68YHIuaxFAO5mhYLZKwG0x" + }, + { + "__type__": "cc.Button", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 18 + }, + "_enabled": true, + "__prefab": null, + "clickEvents": [], + "_interactable": true, + "_transition": 2, + "_normalColor": { + "__type__": "cc.Color", + "r": 214, + "g": 214, + "b": 214, + "a": 255 + }, + "_hoverColor": { + "__type__": "cc.Color", + "r": 211, + "g": 211, + "b": 211, + "a": 255 + }, + "_pressedColor": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_disabledColor": { + "__type__": "cc.Color", + "r": 124, + "g": 124, + "b": 124, + "a": 255 + }, + "_normalSprite": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_hoverSprite": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_pressedSprite": { + "__uuid__": "544e49d6-3f05-4fa8-9a9e-091f98fc2ce8@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_disabledSprite": { + "__uuid__": "951249e0-9f16-456d-8b85-a6ca954da16b@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_duration": 0.1, + "_zoomScale": 1.2, + "_target": { + "__id__": 18 + }, + "_id": "d9VTa5QMxDq5VHnbaB7Dni" + }, + { + "__type__": "cc.Node", + "_name": "Label-002", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 9 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 26 + }, + { + "__id__": 27 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 203.133, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "b6mg+fIttLMpJp3xNrNTZf" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 25 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 42.255859375, + "height": 50.4 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "16qJTqnzhDNooZaYJE5m/h" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 25 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_string": "label", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 20, + "_fontSize": 20, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 0, + "_enableWrapText": true, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": false, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 2, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "86W9LOLGxGBZUtSXpeQd9M" + }, + { + "__type__": "cc.Node", + "_name": "Label-003", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 9 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 29 + }, + { + "__id__": 30 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 280.412, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "eafDMXmLNFf6Vzl1fR0xWy" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 28 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 42.255859375, + "height": 50.4 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "26juNCywRKQZvJp28g6+Xv" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 28 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_string": "label", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 20, + "_fontSize": 20, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 0, + "_enableWrapText": true, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": false, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 2, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "35X+mpxitNFq/igqZGEjfw" + }, + { + "__type__": "cc.Node", + "_name": "Button-001", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 9 + }, + "_children": [ + { + "__id__": 32 + } + ], + "_active": true, + "_components": [ + { + "__id__": 35 + }, + { + "__id__": 36 + }, + { + "__id__": 37 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 114.814, + "y": -80.591, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "21cfQqfdNJc4AXsKC4RF23" + }, + { + "__type__": "cc.Node", + "_name": "Label", + "_objFlags": 512, + "__editorExtras__": {}, + "_parent": { + "__id__": 31 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 33 + }, + { + "__id__": 34 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "ae7apqU89KPZ1Enel0WTUp" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 32 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 100, + "height": 40 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "fbNhi55IRI2J7tQvaxJHgJ" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 32 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_string": "button", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 20, + "_fontSize": 20, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 1, + "_enableWrapText": false, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": false, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 2, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "14ZCtVbGZBHal1QK3EAe0s" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 31 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 100, + "height": 40 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "d7HQUgeApGCpL/NZglnJzO" + }, + { + "__type__": "cc.Sprite", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 31 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_spriteFrame": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_type": 1, + "_fillType": 0, + "_sizeMode": 0, + "_fillCenter": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_fillStart": 0, + "_fillRange": 0, + "_isTrimmedMode": true, + "_useGrayscale": false, + "_atlas": null, + "_id": "e9KkhF8TVBwbhEjVhNHJuM" + }, + { + "__type__": "cc.Button", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 31 + }, + "_enabled": true, + "__prefab": null, + "clickEvents": [], + "_interactable": true, + "_transition": 2, + "_normalColor": { + "__type__": "cc.Color", + "r": 214, + "g": 214, + "b": 214, + "a": 255 + }, + "_hoverColor": { + "__type__": "cc.Color", + "r": 211, + "g": 211, + "b": 211, + "a": 255 + }, + "_pressedColor": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_disabledColor": { + "__type__": "cc.Color", + "r": 124, + "g": 124, + "b": 124, + "a": 255 + }, + "_normalSprite": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_hoverSprite": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_pressedSprite": { + "__uuid__": "544e49d6-3f05-4fa8-9a9e-091f98fc2ce8@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_disabledSprite": { + "__uuid__": "951249e0-9f16-456d-8b85-a6ca954da16b@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_duration": 0.1, + "_zoomScale": 1.2, + "_target": { + "__id__": 31 + }, + "_id": "09rcw9tSNKVLT5G6GQX379" + }, + { + "__type__": "cc.Node", + "_name": "Label-004", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 9 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 39 + }, + { + "__id__": 40 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 280.412, + "y": -239.565, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "5doj7uQHlNabsuccWxoDqP" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 38 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 42.255859375, + "height": 50.4 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "91tAaDhvlGWKKHT2V9qmwV" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 38 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_string": "label", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 20, + "_fontSize": 20, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 0, + "_enableWrapText": true, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": false, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 2, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "bdmZE7nohKIb+n0QmKa1dG" + }, + { + "__type__": "cc.Node", + "_name": "Button-002", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 9 + }, + "_children": [ + { + "__id__": 42 + } + ], + "_active": true, + "_components": [ + { + "__id__": 45 + }, + { + "__id__": 46 + }, + { + "__id__": 47 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 385.29, + "y": -237.357, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "80nP8NDrxLBKZT0pkkCtl5" + }, + { + "__type__": "cc.Node", + "_name": "Label", + "_objFlags": 512, + "__editorExtras__": {}, + "_parent": { + "__id__": 41 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 43 + }, + { + "__id__": 44 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "13982sanxLvIgB/RKDodfG" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 42 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 100, + "height": 40 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "499H6swhZNqaP3lJNZfKZo" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 42 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_string": "button", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 20, + "_fontSize": 20, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 1, + "_enableWrapText": false, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": false, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 2, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "c9NR60s8NPFrXF46mOi5qa" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 41 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 100, + "height": 40 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "291Y66nspC86lPDwj4w9VD" + }, + { + "__type__": "cc.Sprite", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 41 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_spriteFrame": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_type": 1, + "_fillType": 0, + "_sizeMode": 0, + "_fillCenter": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_fillStart": 0, + "_fillRange": 0, + "_isTrimmedMode": true, + "_useGrayscale": false, + "_atlas": null, + "_id": "1f/zgmhD9EUoGX8nmxpZca" + }, + { + "__type__": "cc.Button", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 41 + }, + "_enabled": true, + "__prefab": null, + "clickEvents": [], + "_interactable": true, + "_transition": 2, + "_normalColor": { + "__type__": "cc.Color", + "r": 214, + "g": 214, + "b": 214, + "a": 255 + }, + "_hoverColor": { + "__type__": "cc.Color", + "r": 211, + "g": 211, + "b": 211, + "a": 255 + }, + "_pressedColor": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_disabledColor": { + "__type__": "cc.Color", + "r": 124, + "g": 124, + "b": 124, + "a": 255 + }, + "_normalSprite": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_hoverSprite": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_pressedSprite": { + "__uuid__": "544e49d6-3f05-4fa8-9a9e-091f98fc2ce8@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_disabledSprite": { + "__uuid__": "951249e0-9f16-456d-8b85-a6ca954da16b@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_duration": 0.1, + "_zoomScale": 1.2, + "_target": { + "__id__": 41 + }, + "_id": "d8xw994+tKfp7rT5BevlNJ" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 9 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 1280, + "height": 720 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "9eENxfIbtHJbmdU+3yyzcW" + }, + { + "__type__": "cc.Canvas", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 9 + }, + "_enabled": true, + "__prefab": null, + "_cameraComponent": { + "__id__": 11 + }, + "_alignCanvasWithScreen": true, + "_id": "d0DTDMMPNAELzW/5Zb52+u" + }, + { + "__type__": "cc.Widget", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 9 + }, + "_enabled": true, + "__prefab": null, + "_alignFlags": 45, + "_target": null, + "_left": 0, + "_right": 0, + "_top": 0, + "_bottom": 0, + "_horizontalCenter": 0, + "_verticalCenter": 0, + "_isAbsLeft": true, + "_isAbsRight": true, + "_isAbsTop": true, + "_isAbsBottom": true, + "_isAbsHorizontalCenter": true, + "_isAbsVerticalCenter": true, + "_originalWidth": 0, + "_originalHeight": 0, + "_alignMode": 2, + "_lockFlags": 0, + "_id": "c3rKvYnj1PPLdmYbEKSLTr" + }, + { + "__type__": "cc.Node", + "_name": "UserInfoView", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 1 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 52 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "c0j9jHfY1B675Mz9CsYtU0" + }, + { + "__type__": "0a147ZbIWVPurKGALpIXKoR", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 51 + }, + "_enabled": true, + "__prefab": null, + "userNameLabel": { + "__id__": 14 + }, + "levelLabel": { + "__id__": 17 + }, + "scoreLabel": { + "__id__": 27 + }, + "coinsLabel": { + "__id__": 30 + }, + "onlineStatusLabel": null, + "displayNameLabel": null, + "totalAssetsLabel": null, + "addScoreButton": { + "__id__": 37 + }, + "addCoinsButton": null, + "levelUpButton": { + "__id__": 24 + }, + "toggleOnlineButton": null, + "resetButton": null, + "_id": "c2pehTFT9BQJnAwfi+n6tP" + }, + { + "__type__": "cc.Node", + "_name": "TestView", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 1 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 54 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "ffrenA2klFpZuGccvjc2Rt" + }, + { + "__type__": "667e0XE/fdLCIxlV+CFRlIQ", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 53 + }, + "_enabled": true, + "__prefab": null, + "testLabel": { + "__id__": 40 + }, + "testButton": { + "__id__": 47 + }, + "_id": "03MT/vNyVE0YyCqO+EUB/o" + }, + { + "__type__": "cc.SceneGlobals", + "ambient": { + "__id__": 56 + }, + "shadows": { + "__id__": 57 + }, + "_skybox": { + "__id__": 58 + }, + "fog": { + "__id__": 59 + }, + "octree": { + "__id__": 60 + }, + "skin": { + "__id__": 61 + }, "lightProbeInfo": { - "__id__": 16 + "__id__": 62 }, "postSettings": { - "__id__": 17 + "__id__": 63 }, "bakedWithStationaryMainLight": false, "bakedWithHighpLightmap": false diff --git a/extensions/cocos/cocos-ecs/assets/scripts/mvvm.meta b/extensions/cocos/cocos-ecs/assets/scripts/mvvm.meta new file mode 100644 index 00000000..876d6920 --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/mvvm.meta @@ -0,0 +1,9 @@ +{ + "ver": "1.2.0", + "importer": "directory", + "imported": true, + "uuid": "ab8a85e4-962f-49ac-843a-b57d534f27c5", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestView.ts b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestView.ts new file mode 100644 index 00000000..3195ca9a --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestView.ts @@ -0,0 +1,87 @@ +import { _decorator, Component, Label, Button } from 'cc'; +import { DataBinding, BindingType, BindingMode } from '@esengine/mvvm-ui-framework'; +import { TestViewModel } from './TestViewModel'; + +const { ccclass, property } = _decorator; + +@ccclass('TestView') +export class TestView extends Component { + + @property(Label) + testLabel: Label = null!; + + @property(Button) + testButton: Button = null!; + + private viewModel: TestViewModel; + private dataBinding: DataBinding; + private bindingId: string = ''; + + onLoad() { + console.log('TestView onLoad'); + + // 初始化数据绑定系统 + this.dataBinding = DataBinding.getInstance(); + + // 创建 ViewModel + this.viewModel = new TestViewModel(); + console.log('创建 ViewModel:', this.viewModel); + + // 手动添加观察者来测试 + this.viewModel.addObserver('testValue', (newValue, oldValue, property) => { + console.log(`属性 ${property} 变化: ${oldValue} -> ${newValue}`); + if (this.testLabel) { + this.testLabel.string = '测试值: ' + newValue; + console.log('手动更新 Label 文本:', this.testLabel.string); + } + }); + + // 设置数据绑定 + this.setupDataBinding(); + + // 设置按钮事件 + this.setupButtonEvent(); + + // 测试初始值 + console.log('初始值:', this.viewModel.testValue); + } + + private setupDataBinding(): void { + if (this.testLabel) { + console.log('设置数据绑定'); + console.log('Label 对象:', this.testLabel); + console.log('Label 初始文本:', this.testLabel.string); + + this.bindingId = this.dataBinding.bind(this.viewModel, this.testLabel, { + type: BindingType.ONE_WAY, + mode: BindingMode.FORMAT, + source: 'testValue', + target: 'string', + format: '测试值: {0}' + }); + console.log('绑定ID:', this.bindingId); + + // 手动测试一下绑定是否工作 + this.testLabel.string = '测试值: ' + this.viewModel.testValue; + console.log('手动设置后的文本:', this.testLabel.string); + } + } + + private setupButtonEvent(): void { + if (this.testButton) { + this.testButton.node.on(Button.EventType.CLICK, () => { + console.log('按钮点击'); + this.viewModel.addValue(); + }); + } + } + + onDestroy() { + if (this.bindingId) { + this.dataBinding.unbind(this.bindingId); + } + if (this.viewModel) { + this.viewModel.destroy(); + } + } +} \ No newline at end of file diff --git a/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestView.ts.meta b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestView.ts.meta new file mode 100644 index 00000000..2bd655e4 --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestView.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "667e05c4-fdf7-4b08-8c65-57e085465210", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestViewModel.ts b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestViewModel.ts new file mode 100644 index 00000000..b516052f --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestViewModel.ts @@ -0,0 +1,38 @@ +import 'reflect-metadata'; +import { ViewModel, observable } from '@esengine/mvvm-ui-framework'; + +/** + * 简单的测试 ViewModel + */ +export class TestViewModel extends ViewModel { + + public get name(): string { + return 'TestViewModel'; + } + + @observable + testValue: number = 0; + + public addValue(): void { + console.log('添加值之前:', this.testValue); + console.log('notifyObservers 方法存在吗?', typeof this.notifyObservers); + + // 检查属性描述符 + const descriptor = Object.getOwnPropertyDescriptor(this, 'testValue') || + Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this), 'testValue'); + console.log('testValue 属性描述符:', descriptor); + + // 检查私有属性 + console.log('_testValue 私有属性:', (this as any)._testValue); + + this.testValue += 1; + console.log('添加值之后:', this.testValue); + console.log('_testValue 私有属性 (之后):', (this as any)._testValue); + + // 手动触发通知测试 + if (this.notifyObservers) { + console.log('手动触发通知'); + this.notifyObservers('testValue', this.testValue, this.testValue - 1); + } + } +} \ No newline at end of file diff --git a/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestViewModel.ts.meta b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestViewModel.ts.meta new file mode 100644 index 00000000..1af1a688 --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/TestViewModel.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "28999657-2992-4293-839b-101ae666b364", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoView.ts b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoView.ts new file mode 100644 index 00000000..7375cb75 --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoView.ts @@ -0,0 +1,257 @@ +import { _decorator, Component, Node, Label, Button } from 'cc'; +import { DataBinding, BindingType, BindingMode } from '@esengine/mvvm-ui-framework'; +import { UserInfoViewModel } from './UserInfoViewModel'; + +const { ccclass, property } = _decorator; + +/** + * 用户信息视图组件 + * 展示如何使用 MVVM 框架进行 Label 数据绑定 + */ +@ccclass('UserInfoView') +export class UserInfoView extends Component { + + @property(Label) + userNameLabel: Label = null!; + + @property(Label) + levelLabel: Label = null!; + + @property(Label) + scoreLabel: Label = null!; + + @property(Label) + coinsLabel: Label = null!; + + @property(Label) + onlineStatusLabel: Label = null!; + + @property(Label) + displayNameLabel: Label = null!; + + @property(Label) + totalAssetsLabel: Label = null!; + + @property(Button) + addScoreButton: Button = null!; + + @property(Button) + addCoinsButton: Button = null!; + + @property(Button) + levelUpButton: Button = null!; + + @property(Button) + toggleOnlineButton: Button = null!; + + @property(Button) + resetButton: Button = null!; + + private viewModel: UserInfoViewModel; + private dataBinding: DataBinding; + private bindingIds: string[] = []; + + onLoad() { + // 初始化数据绑定系统 + this.dataBinding = DataBinding.getInstance(); + + // 创建 ViewModel + this.viewModel = new UserInfoViewModel(); + + // 设置数据绑定 + this.setupDataBindings(); + + // 设置按钮事件 + this.setupButtonEvents(); + } + + /** + * 设置数据绑定 + */ + private setupDataBindings(): void { + // 用户名绑定 + if (this.userNameLabel) { + const bindingId = this.dataBinding.bind(this.viewModel, this.userNameLabel, { + type: BindingType.ONE_WAY, + mode: BindingMode.REPLACE, + source: 'userName', + target: 'string' + }); + this.bindingIds.push(bindingId); + + + this.dataBinding.bind(this.viewModel, this.coinsLabel, { + type: BindingType.ONE_WAY, + mode: BindingMode.REPLACE, + source: 'price', + target: 'string', + converter: 'currency', // 货币转换器 + converterParams: ['USD', 2], // 美元,2位小数 + format: '价格: {0}' + }); + + this.dataBinding.registerConverter('currency', { + convert: (value: number) => `${(value * 100).toFixed(1)}%`, + convertBack: (value: string) => parseFloat(value) / 100 + }); + } + + // 等级绑定(使用格式化) + if (this.levelLabel) { + const bindingId = this.dataBinding.bind(this.viewModel, this.levelLabel, { + type: BindingType.ONE_WAY, + mode: BindingMode.FORMAT, + source: 'level', + target: 'string', + format: '等级: {0}' + }); + this.bindingIds.push(bindingId); + } + + // 分数绑定(使用数字转换器) + if (this.scoreLabel) { + const bindingId = this.dataBinding.bind(this.viewModel, this.scoreLabel, { + type: BindingType.ONE_WAY, + mode: BindingMode.FORMAT, + source: 'score', + target: 'string', + converter: 'number', + format: '分数: {0}' + }); + this.bindingIds.push(bindingId); + } + + // 金币绑定(使用数字转换器) + if (this.coinsLabel) { + const bindingId = this.dataBinding.bind(this.viewModel, this.coinsLabel, { + type: BindingType.ONE_WAY, + mode: BindingMode.FORMAT, + source: 'coins', + target: 'string', + converter: 'number', + format: '金币: {0}' + }); + this.bindingIds.push(bindingId); + } + + // 在线状态绑定 + if (this.onlineStatusLabel) { + const bindingId = this.dataBinding.bind(this.viewModel, this.onlineStatusLabel, { + type: BindingType.ONE_WAY, + mode: BindingMode.FORMAT, + source: 'onlineStatusText', + target: 'string', + format: '状态: {0}' + }); + this.bindingIds.push(bindingId); + } + + // 显示名称绑定(计算属性) + if (this.displayNameLabel) { + const bindingId = this.dataBinding.bind(this.viewModel, this.displayNameLabel, { + type: BindingType.ONE_WAY, + mode: BindingMode.REPLACE, + source: 'displayName', + target: 'string' + }); + this.bindingIds.push(bindingId); + } + + // 总资产绑定(计算属性) + if (this.totalAssetsLabel) { + const bindingId = this.dataBinding.bind(this.viewModel, this.totalAssetsLabel, { + type: BindingType.ONE_WAY, + mode: BindingMode.FORMAT, + source: 'totalAssets', + target: 'string', + converter: 'number', + format: '总资产: {0}' + }); + this.bindingIds.push(bindingId); + } + } + + /** + * 设置按钮事件 + */ + private setupButtonEvents(): void { + // 增加分数按钮 - 直接调用方法 + if (this.addScoreButton) { + this.addScoreButton.node.on(Button.EventType.CLICK, () => { + this.viewModel.executeCommand('addScore'); + }); + } + + // 增加金币按钮 - 使用命令系统,支持 canExecute 检查 + if (this.addCoinsButton) { + this.addCoinsButton.node.on(Button.EventType.CLICK, () => { + // 检查命令是否可以执行 + if (this.viewModel.canExecuteCommand('addCoins')) { + this.viewModel.executeCommand('addCoins'); + } else { + console.log('等级太低,无法获得金币!'); + } + }); + } + + // 升级按钮 - 使用命令系统,支持 canExecute 检查 + if (this.levelUpButton) { + this.levelUpButton.node.on(Button.EventType.CLICK, () => { + // 检查命令是否可以执行 + if (this.viewModel.canExecuteCommand('levelUp')) { + this.viewModel.executeCommand('levelUp'); + } else { + console.log('分数不足,无法升级!'); + } + }); + } + + // 切换在线状态按钮 - 直接调用方法 + if (this.toggleOnlineButton) { + this.toggleOnlineButton.node.on(Button.EventType.CLICK, () => { + this.viewModel.toggleOnlineStatus(); + }); + } + + // 重置按钮 - 直接调用方法 + if (this.resetButton) { + this.resetButton.node.on(Button.EventType.CLICK, () => { + this.viewModel.resetUserData(); + }); + + } + } + + /** + * 手动更新用户信息(演示用) + */ + public updateUserInfo(): void { + // 可以通过代码直接修改 ViewModel 的属性 + // 绑定的 Label 会自动更新 + this.viewModel.userName = '测试用户' + Math.floor(Math.random() * 1000); + this.viewModel.level = Math.floor(Math.random() * 50) + 1; + this.viewModel.score = Math.floor(Math.random() * 10000); + this.viewModel.coins = Math.floor(Math.random() * 1000); + this.viewModel.isOnline = Math.random() > 0.5; + } + + /** + * 获取当前 ViewModel + */ + public getViewModel(): UserInfoViewModel { + return this.viewModel; + } + + onDestroy() { + // 清理绑定 + for (const bindingId of this.bindingIds) { + this.dataBinding.unbind(bindingId); + } + this.bindingIds = []; + + // 销毁 ViewModel + if (this.viewModel) { + this.viewModel.destroy(); + } + } +} \ No newline at end of file diff --git a/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoView.ts.meta b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoView.ts.meta new file mode 100644 index 00000000..37338ee8 --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoView.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "0a14765b-2165-4fba-b286-00ba485caa11", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoViewModel.ts b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoViewModel.ts new file mode 100644 index 00000000..c650872e --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoViewModel.ts @@ -0,0 +1,128 @@ +import { ViewModel, observable, computed, command, viewModel } from '@esengine/mvvm-ui-framework'; + +/** + * 用户信息视图模型 + * 展示如何使用 MVVM 框架进行数据绑定 + */ +@viewModel +export class UserInfoViewModel extends ViewModel { + + public get name(): string { + return 'UserInfoViewModel'; + } + + /** + * 用户名 - 使用 @observable 装饰器自动处理数据绑定 + */ + @observable + userName: string = '未知用户'; + + /** + * 用户等级 + */ + level: number = 1; + + /** + * 用户分数 + */ + @observable + score: number = 0; + + /** + * 用户金币 + */ + @observable + coins: number = 100; + + /** + * 是否在线 + */ + @observable + isOnline: boolean = false; + + /** + * 计算属性:用户显示名称(格式化) + */ + @computed(['userName', 'level']) + get displayName(): string { + return `${this.userName} (Lv.${this.level})`; + } + + /** + * 计算属性:在线状态文本 + */ + @computed(['isOnline']) + get onlineStatusText(): string { + return this.isOnline ? '在线' : '离线'; + } + + /** + * 计算属性:总资产(分数 + 金币) + */ + @computed(['score', 'coins']) + get totalAssets(): number { + return this.score + this.coins; + } + + /** + * 增加分数 - 使用 @command 装饰器,可以通过 executeCommand('addScore') 调用 + */ + @command() + public addScore(amount: number = 10): void { + this.score += amount; + } + + + + /** + * 增加金币 - 带有 canExecute 逻辑的命令 + */ + @command('canAddCoins') + public addCoins(amount: number = 5): void { + this.coins += amount; + } + + /** + * 检查是否可以增加金币(例如:等级必须大于 1) + */ + public canAddCoins(): boolean { + return this.level > 1; + } + + /** + * 升级 - 带有复杂 canExecute 逻辑的命令 + */ + @command('canLevelUp') + public levelUp(): void { + this.level += 1; + this.score += this.level * 100; // 升级奖励 + } + + /** + * 检查是否可以升级(例如:需要足够的分数) + */ + public canLevelUp(): boolean { + return this.score >= this.level * 100; + } + + /** + * 切换在线状态 + */ + @command() + public toggleOnlineStatus(): void { + this.isOnline = !this.isOnline; + } + + /** + * 重置用户数据 + */ + public resetUserData(): void { + this.batchUpdate({ + userName: '新用户', + level: 1, + score: 0, + coins: 100, + isOnline: false + }); + } +} \ No newline at end of file diff --git a/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoViewModel.ts.meta b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoViewModel.ts.meta new file mode 100644 index 00000000..e06399ac --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/mvvm/UserInfoViewModel.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "0e90a89e-1c64-4c47-ab61-9093f9964678", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/extensions/cocos/cocos-ecs/package-lock.json b/extensions/cocos/cocos-ecs/package-lock.json index 9046e0b4..948f7c8f 100644 --- a/extensions/cocos/cocos-ecs/package-lock.json +++ b/extensions/cocos/cocos-ecs/package-lock.json @@ -6,9 +6,29 @@ "": { "name": "cocos-ecs", "dependencies": { - "@esengine/ai": "^2.0.15", + "@esengine/ai": "^2.0.17", "@esengine/cocos-nexus": "^1.0.1", - "@esengine/ecs-framework": "^2.1.23" + "@esengine/ecs-framework": "^2.1.23", + "@esengine/mvvm-ui-framework": "^1.0.3" + } + }, + "../../../thirdparty/mvvm-ui-framework": { + "name": "@esengine/mvvm-ui-framework", + "version": "1.0.2", + "extraneous": true, + "license": "MIT", + "dependencies": { + "reflect-metadata": "^0.1.13" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^28.0.3", + "@rollup/plugin-node-resolve": "^16.0.1", + "@rollup/plugin-terser": "^0.4.4", + "@types/node": "^20.19.0", + "rimraf": "^5.0.0", + "rollup": "^4.42.0", + "rollup-plugin-dts": "^6.2.1", + "typescript": "^5.8.3" } }, "node_modules/@cocos/creator-types": { @@ -18,9 +38,9 @@ "peer": true }, "node_modules/@esengine/ai": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@esengine/ai/-/ai-2.0.15.tgz", - "integrity": "sha512-n6z66aWtVvIvwmJSXNeMbnfi63AUgXV7ZSrLmVeUMQGxtGjHbbnMwAdk2IN+ab6yTk0Gw4p5eA1UiXP2+r1wqA==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@esengine/ai/-/ai-2.0.17.tgz", + "integrity": "sha512-ek19BGzW4VmkZsCr6N0SDJthzU6q+FTjb5wMwc3dEU1PdDRxPeSaD5wwhPfnTkgMXuGkncnM3NGuboz915LWyg==", "dependencies": { "@esengine/ecs-framework": "^2.1.20" }, @@ -48,6 +68,17 @@ "node": ">=16.0.0" } }, + "node_modules/@esengine/mvvm-ui-framework": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@esengine/mvvm-ui-framework/-/mvvm-ui-framework-1.0.3.tgz", + "integrity": "sha512-6WSY5PwE5du9H6xXfOmqPdscE4Lyf4lCwoEHQVGEJW3Dqhhb5O0ZuShF1XGpfJY/fONoLPTdL6Jln4japm432w==", + "dependencies": { + "reflect-metadata": "^0.1.13" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/reflect-metadata": { "version": "0.1.14", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", diff --git a/extensions/cocos/cocos-ecs/package.json b/extensions/cocos/cocos-ecs/package.json index 8c6562dc..00a74323 100644 --- a/extensions/cocos/cocos-ecs/package.json +++ b/extensions/cocos/cocos-ecs/package.json @@ -5,8 +5,9 @@ "version": "3.8.6" }, "dependencies": { - "@esengine/ai": "^2.0.15", + "@esengine/ai": "^2.0.17", + "@esengine/cocos-nexus": "^1.0.1", "@esengine/ecs-framework": "^2.1.23", - "@esengine/cocos-nexus": "^1.0.1" + "@esengine/mvvm-ui-framework": "^1.0.3" } } diff --git a/thirdparty/BehaviourTree-ai b/thirdparty/BehaviourTree-ai index 4da406cf..76bde069 160000 --- a/thirdparty/BehaviourTree-ai +++ b/thirdparty/BehaviourTree-ai @@ -1 +1 @@ -Subproject commit 4da406cf0263027abffbf184cc9347c04ca67dbe +Subproject commit 76bde0698857a00d0574a08075028c3797dccfe3 diff --git a/thirdparty/mvvm-ui-framework b/thirdparty/mvvm-ui-framework new file mode 160000 index 00000000..9c28abce --- /dev/null +++ b/thirdparty/mvvm-ui-framework @@ -0,0 +1 @@ +Subproject commit 9c28abce280a8ee655af5d3fdfe3185fe95f7179