Merge pull request #12 from potato47/dev

使用 vuetify 重构
This commit is contained in:
potato47 2020-04-14 21:42:11 +08:00 committed by GitHub
commit 9751d8cfb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 42460 additions and 12800 deletions

View File

@ -1,52 +1,57 @@
# ccc-devtools v2.3.3 # ccc-devtools v3.0.0
Cocos Creator 网页调试工具,运行时查看、修改节点树,实时更新节点属性,可视化显示缓存资源。 Cocos Creator 网页调试工具,运行时查看、修改节点树,实时更新节点属性,可视化缓存资源。
## 预览 ## 功能
v1.0.0 - 场景节点树实时显示,节点、组件属性实时显示更改
![preview](./screenshots/preview.gif)
v1.1.0: 拖拽节点,增加开关 ![preview](./screenshots/preview1.gif)
![t5](./screenshots/t4.gif) - 可视化缓存资源
v1.2.0: 控制台输出节点信息 ![preview](./screenshots/preview2.png)
![t6](./screenshots/t5.png) - 标记场景中节点位置
v2.0.0: 节点信息自动同步避免手动刷新。增加组件信息显示。增加内存、FPS、渲染时间显示。更新提醒。 ![preview](./screenshots/preview3.png)
![preview2](./screenshots/preview2.png) - 输出节点、组件引用到控制台
v2.1.0: 区分手动刷新和自动刷新两种模式手动刷新时支持搜索和拖拽节点添加圈出节点位置功能添加控制台节点树cc.tree(); ![preview](./screenshots/preview4.png)
![preview3](./screenshots/preview3.png) - cc控制台功能扩展
v2.2.0: 新增黑色主题(感谢[@wheatup](https://github.com/wheatup) ) ![preview](./screenshots/preview5.png)
![dark-theme](./screenshots/dark-theme.png)
v2.3.0: 添加缓存资源查看面板;简化调试信息显示,新增纹理内存挂件。 ## 全局使用
![cache](./screenshots/preview_cache.png)
## 使用
1. 点击 Creator 右上角进入编辑器 resources 目录,再依次进入`static/preview-templates`目录 1. 点击 Creator 右上角进入编辑器 resources 目录,再依次进入`static/preview-templates`目录
![t1](./screenshots/t1.png) ![t1](./screenshots/t1.png)
2. 将本项目clone到上面的目录下,**如果使用下载压缩包的方式记得把后缀名-master去掉** 2. 将本项目clone到上面的目录下**如果使用下载压缩包的方式记得把后缀名-master去掉**
![t2](./screenshots/t2.png) ![t2](./screenshots/t2.png)
3. 打开`index.jade`,找到`body`里最后一个`div`,在下面添加`include ./ccc-devtools/index.html`**注意用tab键与上面的div对齐** 3. 打开 `index.jade`,找到 `body` 将中间部分替换为 `include ./ccc-devtools/index.html`**注意用tab键对齐**
![t3](./screenshots/t3.png) ![t3](./screenshots/t3.png)
## 项目使用
## 已知问题 Cocos Creator 从 v2.2 开始新增了自定义网页预览功能。
- 当升级 Cococs Creator 时会清空resources目录需要重新下载配置如自定义了一些配置请做好备份。 1. 重复上面的操作步骤,将修改后的 `preview-templates` 目录拷贝到项目根目录
- 开启节点树会增加渲染消耗,非调试阶段请关闭。
2. 将 `ccc-devtools/index.html` 里所有引用的资源路径 `app/editor/static/preview-templates/ccc-devtools/...` 替换为 `ccc-devtools/...`
3. 重启 Cocos Creator
## 自定义
- 本项目使用了 vue 和 vuetify可根据 [vuetify 文档](https://vuetifyjs.com/en/getting-started/quick-start/) 对页面进行修改
- 节点、组件显示属性可在 `config.js` 里配置,目前支持 textnumbertextareacolorbool 几种类型
## 需求、更新 ## 需求、更新
@ -59,17 +64,13 @@ https://github.com/potato47/ccc-devtools
## 贡献指南 ## 贡献指南
- 版本号命名规则 https://semver.org/lang/zh-CN/ ,简单来讲新功能第二位加一修复bug第三位加一 - 版本号命名规则 https://semver.org/lang/zh-CN/ ,简单来讲新功能第二位加一修复bug第三位加一
- 如果新增功能请在README中添加预览截图说明 - 如果新增功能请在README中添加预览截图说明
- 记得更新version.json中的版本号 - 记得更新version.json中的版本号
## 本项目依赖以下开源项目 ## 前人种树
https://github.com/vuejs/vue - https://github.com/vuejs/vue
https://github.com/ElemeFE/element - https://github.com/vuetifyjs/vuetify
https://github.com/iview/iview
https://github.com/FE-Driver/vue-beauty
https://github.com/mrdoob/stats.js

540
config.js
View File

@ -4,350 +4,24 @@ const NEX_CONFIG = {
title: 'Node', title: 'Node',
key: 'cc.Node', key: 'cc.Node',
rows: [ rows: [
// Position { name: 'Name', key: 'name', type: 'text' },
[{ { name: 'X', key: 'x', type: 'number' },
type: 'label', { name: 'Y', key: 'y', type: 'number' },
span: 6, { name: 'Width', key: 'width', type: 'number' },
field: 'Position' { name: 'Height', key: 'height', type: 'number' },
}, { { name: 'Angle', key: 'angle', type: 'number' },
type: 'label', { name: 'ScaleX', key: 'scaleX', type: 'number' },
span: 1, { name: 'ScaleY', key: 'scaleY', type: 'number' },
field: 'X' { name: 'Opacity', key: 'opacity', type: 'number' },
}, { { name: 'Color', key: 'hex_color', type: 'color' },
type: 'number', { name: 'Group', key: 'group', type: 'text' },
span: 8,
field: 'x'
}, {
type: 'label',
span: 1,
field: 'Y'
}, {
type: 'number',
span: 8,
field: 'y'
}],
// Angle
[{
type: 'label',
span: 6,
field: 'Angle'
}, {
type: 'number',
span: 18,
field: 'angle'
}],
// Scale
[{
type: 'label',
span: 6,
field: 'Scale'
}, {
type: 'label',
span: 1,
field: 'X'
}, {
type: 'number',
span: 8,
field: 'scaleX'
}, {
type: 'label',
span: 1,
field: 'Y'
}, {
type: 'number',
span: 8,
field: 'scaleY'
}],
// Anchor
[{
type: 'label',
span: 6,
field: 'Anchor'
}, {
type: 'label',
span: 1,
field: 'X'
}, {
type: 'number',
span: 8,
field: 'anchorX'
}, {
type: 'label',
span: 1,
field: 'Y'
}, {
type: 'number',
span: 8,
field: 'anchorY'
}],
// Size
[{
type: 'label',
span: 6,
field: 'Size'
}, {
type: 'label',
span: 1,
field: 'W'
}, {
type: 'number',
span: 8,
field: 'width'
}, {
type: 'label',
span: 1,
field: 'H'
}, {
type: 'number',
span: 8,
field: 'height'
}],
// Color
[{
type: 'label',
span: 6,
field: 'Color',
}, {
type: 'color',
span: 18,
field: 'hex_color',
rawField: 'color',
}],
// Opacity
[{
type: 'label',
span: 6,
field: 'Opacity'
}, {
type: 'number',
span: 18,
field: 'opacity'
}],
// Skew
[{
type: 'label',
span: 6,
field: 'Skew'
}, {
type: 'label',
span: 1,
field: 'X'
}, {
type: 'number',
span: 8,
field: 'skewX'
}, {
type: 'label',
span: 1,
field: 'Y'
}, {
type: 'number',
span: 8,
field: 'skewY'
}],
// Group
[{
type: 'label',
span: 6,
field: 'Group'
}, {
type: 'input',
span: 18,
field: 'group'
}]
] ]
}, },
node3d: { node3d: {
title: 'Node', title: 'Node',
key: 'cc.Node', key: 'cc.Node',
rows: [ rows: [
// Position // TODO:
[{
type: 'label',
span: 6,
field: 'Position'
}, {
type: 'label',
span: 1,
field: 'X'
}, {
type: 'number',
span: 5,
field: 'x'
}, {
type: 'label',
span: 1,
field: 'Y'
}, {
type: 'number',
span: 5,
field: 'y'
}, {
type: 'label',
span: 1,
field: 'Z'
}, {
type: 'number',
span: 5,
field: 'z'
}],
// Angle
[{
type: 'label',
span: 6,
field: 'Rotation'
}, {
type: 'label',
span: 1,
field: 'X'
}, {
type: '3DAngle',
span: 5,
field: 'x'
}, {
type: 'label',
span: 1,
field: 'Y'
}, {
type: '3DAngle',
span: 5,
field: 'y'
}, {
type: 'label',
span: 1,
field: 'Z'
}, {
type: '3DAngle',
span: 5,
field: 'z'
}],
// Scale
[{
type: 'label',
span: 6,
field: 'Scale'
}, {
type: 'label',
span: 1,
field: 'X'
}, {
type: 'number',
span: 5,
field: 'scaleX'
}, {
type: 'label',
span: 1,
field: 'Y'
}, {
type: 'number',
span: 5,
field: 'scaleY'
}, {
type: 'label',
span: 1,
field: 'Z'
}, {
type: 'number',
span: 5,
field: 'scaleZ'
}],
// Anchor
[{
type: 'label',
span: 6,
field: 'Anchor'
}, {
type: 'label',
span: 1,
field: 'X'
}, {
type: 'number',
span: 8,
field: 'anchorX'
}, {
type: 'label',
span: 1,
field: 'Y'
}, {
type: 'number',
span: 8,
field: 'anchorY'
}],
// Size
[{
type: 'label',
span: 6,
field: 'Size'
}, {
type: 'label',
span: 1,
field: 'W'
}, {
type: 'number',
span: 8,
field: 'width'
}, {
type: 'label',
span: 1,
field: 'H'
}, {
type: 'number',
span: 8,
field: 'height'
}],
// Color
[{
type: 'label',
span: 6,
field: 'Color',
}, {
type: 'color',
span: 18,
field: 'hex_color',
rawField: 'color',
}],
// Opacity
[{
type: 'label',
span: 6,
field: 'Opacity'
}, {
type: 'number',
span: 18,
field: 'opacity'
}],
// Skew
[{
type: 'label',
span: 6,
field: 'Skew'
}, {
type: 'label',
span: 1,
field: 'X'
}, {
type: 'number',
span: 8,
field: 'skewX'
}, {
type: 'label',
span: 1,
field: 'Y'
}, {
type: 'number',
span: 8,
field: 'skewY'
}],
// Group
[{
type: 'label',
span: 6,
field: 'Group'
}, {
type: 'input',
span: 18,
field: 'group'
}]
] ]
}, },
}, },
@ -356,198 +30,24 @@ const NEX_CONFIG = {
title: 'cc.Camera', title: 'cc.Camera',
key: 'cc.Camera', key: 'cc.Camera',
rows: [ rows: [
// Zoom Ratio { name: 'Zoom Ratio', key: 'zoomRatio', type: 'number' },
[{ { name: 'Depth', key: 'depth', type: 'number' },
type: 'label', { name: 'Bacground Color', key: 'hex_backgroundColor', rawKey: 'backgroundColor', type: 'color' },
span: 6, { name: 'Align with Screen', key: 'alignWithScreen', type: 'bool' },
field: 'Zoom Ratio'
}, {
type: 'number',
span: 18,
field: 'zoomRatio'
}],
// Background Color
[{
type: 'label',
span: 6,
field: 'Bg Color'
}, {
type: 'color',
span: 18,
field: 'hex_backgroundColor',
rawField: 'backgroundColor'
}],
// Depth
[{
type: 'label',
span: 6,
field: 'Depth'
}, {
type: 'number',
span: 18,
field: 'depth'
}],
] ]
}, },
'cc.Sprite': { 'cc.Sprite': {
key: 'cc.Sprite', key: 'cc.Sprite',
title: 'cc.Sprite', title: 'cc.Sprite',
rows: [ rows: []
// Type
[{
type: 'label',
span: 6,
field: 'Type'
}, {
type: 'select',
span: 18,
field: 'type',
options: [{
label: 'SIMPLE',
value: 0
}, {
label: 'SLICED',
value: 1
}, {
label: 'TILED',
vlaue: 2
}, {
label: 'FILLED',
value: 3
}, {
label: 'MESH',
value: 4
}]
}],
// Size Mode
[{
type: 'label',
span: 6,
field: 'Size Mode'
}, {
type: 'select',
span: 18,
field: 'sizeMode',
options: [{
label: 'CUSTOM',
value: 0
}, {
label: 'TRIMMED',
value: 1
}, {
label: 'RAW',
vlaue: 2
}]
}],
// Trim
[{
type: 'label',
span: 6,
field: 'Trim'
}, {
type: 'bool',
span: 18,
field: 'trim'
}],
]
}, },
'cc.Label': { 'cc.Label': {
title: 'cc.Label', title: 'cc.Label',
key: 'cc.Label', key: 'cc.Label',
rows: [ rows: [
// String { name: 'String', key: 'string', type: 'textarea' },
[{ { name: 'Font Size', key: 'fontSize', type: 'number' },
type: 'label', { name: 'Line Height', key: 'lineHeight', type: 'number' },
span: 6,
field: 'String'
}, {
type: 'textarea',
span: 18,
field: 'string'
}],
// Horizontal Align
[{
type: 'label',
span: 6,
field: 'Horizontal'
}, {
type: 'select',
span: 18,
field: 'horizontalAlign',
options: [{
label: 'LEFT',
value: 0
}, {
label: 'CENTER',
value: 1
}, {
label: 'RIGHT',
value: 2
}]
}],
// Vertical Align
[{
type: 'label',
span: 6,
field: 'Vertical'
}, {
type: 'select',
span: 18,
field: 'verticalAlign',
options: [{
label: 'TOP',
value: 0
}, {
label: 'CENTER',
value: 1
}, {
label: 'BOTTOM',
value: 2
}]
}],
// Font Size
[{
type: 'label',
span: 6,
field: 'Font Size'
}, {
type: 'number',
span: 18,
field: 'fontSize'
}],
// Line Height
[{
type: 'label',
span: 6,
field: 'Line Height',
}, {
type: 'number',
span: 18,
field: 'lineHeight'
}],
// Overflow
[{
type: 'label',
span: 6,
field: 'Overflow'
}, {
type: 'select',
span: 18,
field: 'overflow',
options: [{
label: 'NONE',
value: 0
}, {
label: 'CLAMP',
value: 1
}, {
label: 'SHRINK',
value: 2
}, {
label: 'RESIZE_HEIGHT',
value: 3
}]
}],
] ]
} }
} }

View File

@ -1,36 +0,0 @@
body {
background-color: #333;
}
.el-color-picker, .el-color-picker__trigger {
width: 100% !important;
}
.el-input-number .el-input__inner {
text-align: left;
}
.el-input-number.is-controls-right .el-input__inner {
padding-left: 5px;
padding-right: 5px;
}
.el-card__body {
padding-left: 20px;
padding-right: 10px;
}
.ivu-collapse-content {
color: #515a6e;
padding: 0 5px 0 16px;
background-color: #fff;
}
.el-input-number--mini .el-input-number__decrease, .el-input-number--mini .el-input-number__increase {
width: 12px;
font-size: 12px;
}
.el-select.el-select--mini {
width: 100%;
}

View File

@ -1,78 +0,0 @@
.ivu-split-trigger {
background: #444 !important;
}
.right-panel *,
.ivu-split-trigger,
.el-color-dropdown,
.el-color-dropdown *:not(.el-button--text),
.el-popover,
.el-popover * ,
#panelCtl .el-button{
border-color: #333 !important;
color: #bbb !important;
}
.el-popover,
.el-color-dropdown input,
.right-panel input,
.right-panel textarea,
.right-panel .el-checkbox__inner:not(.is-checked) {
background-color: #333 !important;
color: #bbb !important;
}
.right-panel button,
.right-panel span[role='button'],
.right-panel .ant-tree,
.right-panel .demo-split-pane,
.right-panel .el-card,
.right-panel .el-tree,
.el-color-dropdown,
.el-popover {
background-color: #222 !important;
}
.right-panel .el-button {
padding-left: 10px !important;
padding-right: 10px !important;
}
.right-panel .top-pane span,
.right-panel .ant-tree,
.right-panel .demo-split-pane,
.right-panel .el-card,
.right-panel .el-tree {
color: #aaa !important;
}
.right-panel .ant-tree-node-selected {
background-color: #456 !important;
}
.right-panel .ant-tree-node-content-wrapper:hover,
.right-panel .el-tree-node .el-tree-node__content:hover {
background-color: #567 !important;
}
.el-switch.is-checked .el-switch__core,
.el-tree-node.is-current .el-tree-node__content,
.el-checkbox__input.is-checked .el-checkbox__inner {
background-color: #367 !important;
}
.right-panel .el-checkbox__label,
.right-panel .el-button,
.el-color-dropdown, button {
color: #59a !important;
background-color: #222 !important;
}
.tree-panel,
.prop-panel,
.ivu-modal-content,
.ivu-table-column-center,
.ivu-modal-header-inner {
background-color: #222 !important;
color: #bbb !important;
}

View File

@ -1,222 +1,204 @@
<link rel="stylesheet" type="text/css" href="app/editor/static/preview-templates/ccc-devtools/libs/vue-beauty/css/vue-beauty.min.css"> <link href="app/editor/static/preview-templates/ccc-devtools/libs/css/materialdesignicons.min.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" type="text/css" href="app/editor/static/preview-templates/ccc-devtools/libs/element/css/element-ui.css"> <link href="app/editor/static/preview-templates/ccc-devtools/libs/css/vuetify.min.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" type="text/css" href="app/editor/static/preview-templates/ccc-devtools/libs/iview/css/iview.css"> <style>
<link rel="stylesheet" type="text/css" href="app/editor/static/preview-templates/ccc-devtools/css/style.css"> html {
overflow-y: auto;
}
</style>
<div id="app"> <v-app id="app">
<div v-if="isDevMode" style="display: flex;min-height: 100vh;"> <v-app-bar app clipped-left color="gray" dense v-if="true">
<!-- 左边游戏预览区域 --> <v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
<div id="game_panel" <div id="recompiling"><span>Recompiling...</span></div>
style="display:flex;flex:auto;flex-direction: column;"> <v-spacer></v-spacer>
<div id="top" style="flex: none"></div> <div class="toolbar">
</div> <div class="item">
<!-- 右边节点树和属性区域 --> <select id="opts-device">
<div class="right-panel" style="flex: none;display: block;width: 400px;"> <option value="0">Default</option>
<!-- 节点树面板 --> </select>
<div class="tree-panel" style="height: 50vh;overflow: auto;border-bottom: 1px solid #2d2d2d;"> </div>
<el-input v-if="!isAutoRefreshTree" placeholder="搜索节点" v-model="filterText" size="mini" <div class="item">
id="searchInput"></el-input> <v-btn id="btn-rotate" small height="25"><span style="color: #aaa;">Rotate</span></v-btn>
<v-tree v-if="isDevMode&&isAutoRefreshTree" :data="sceneTreeData" ref="sceneTree" </div>
@select="handleNodesSelect" <span style="font-size: small;display: none;" class="item">Debug Mode:</span>
style="min-width: 250px;height: 100%;overflow-x:hidden;overflow-y:auto;background: white;"> <div class="item" style="display: none;">
</v-tree> <select id="opts-debug-mode">
<el-tree v-if="isDevMode&&!isAutoRefreshTree" :data="sceneTreeData" :draggable="true" <option value="0">None</option>
:props="nodeProps" :default-expanded-keys="defaultExpandedKeys" empty-text="暂无数据..." <option value="1">Info</option>
:node-key="'_id'" :expand-on-click-node="false" :filter-node-method="filterNode" <option value="2">Warn</option>
ref="sceneTree" @node-click="handleNodeClick" <option value="3">Error</option>
style="min-width: 250px;height: 100%;overflow-x:hidden;overflow-y:auto;"> <option value="4">Info For Web Page</option>
<span class="custom-tree-node" slot-scope="{ node, data }"> <option value="5">Warn For Web Page</option>
<span <option value="6">Error For Web Page</option>
v-bind:style="{color: data.activeInHierarchy?'#606266':'#C0C4CC'}">{{ node.label }}</span> </select>
</span> </div>
</el-tree> <div class="item">
<el-button v-if="!isAutoRefreshTree" @click="handleRefreshTree" icon="el-icon-refresh" <v-btn id="btn-show-fps" small height="25"><span style="color: #aaa;">Show FPS</span></v-btn>
size="mini" style="position: absolute;right:0;top:0;"></el-button> </div>
<div style="position: absolute;right:0;bottom:51vh;width: 100px;height:20px;"> <div class="item">
<span style="line-height:20px;">自动刷新</span> <span style="font-size: small;color: #aaa;" class="item">FPS:</span><input id="input-set-fps"
<el-switch v-model="isAutoRefreshTree" active-color="#0099ff" inactive-color="gray"> type="number" />
</el-switch> </div>
</div> <div style="margin-right: 0px;" class="item">
<v-btn id="btn-pause" small height="25"><span style="color: #aaa;">Pause</span></v-btn>
</div>
<div class="item">
<v-btn id="btn-step" style="display: none;" small height="25">
<span style="color: #aaa;">Step</span>
</v-btn>
</div>
<div class="item">
<v-btn id="btn-recompile" small height="25"><span style="color: #aaa;">Recompile</span></v-btn>
</div>
<v-icon @click="openCocosDocs" small>mdi-cloud-search</v-icon>
<v-icon @click="openCocosForum" small>mdi-forum</v-icon>
<v-icon @click="openCacheDialog" small>mdi-table</v-icon>
<v-icon @click="openGithub" small>mdi-home</v-icon>
</div>
</v-app-bar>
<!-- <el-button @click="handleSwitchTreeMode" icon="el-icon-refresh" size="mini" style="position: absolute;right:0;bottom:0;"></el-button> --> <v-navigation-drawer v-model="drawer" app clipped fixed width="512">
</div> <v-container style="height: 50%;overflow: auto;">
<!-- 节点属性面板 --> <v-text-field v-model="treeSearchText" dense label="Search Node or Component" dark flat solo-inverted
<div class="prop-panel" style="background: white;height: 50vh;overflow:auto;"> hide-details clearable clear-icon="mdi-close-circle-outline"></v-text-field>
<div v-if="node"> <v-treeview :items="treeData" item-key="id" dense activatable :search="treeSearchText"
<el-row style="margin:5px 0;"> :active.sync="selectedNodes">
<el-col :span="2" style="text-align:center;padding-top:7px;padding-left:5px;"> <template v-slot:label="{ item, active }">
<el-checkbox v-model="node.active"></el-checkbox> <label v-if="item.active" style="color: white;">{{ item.name }}</label>
</el-col> <label v-else style="color: gray;">{{ item.name }}</label>
<el-col :span="18"> </template>
<el-input v-model="node.name" size="mini"></el-input> </v-treeview>
</el-col> </v-container>
<el-col :span="4"> <v-container style="border-top: 2px solid darkgray;height: 50%;overflow-y: auto;">
<div style="width: 100%;height:28px;border: solid 1px rgb(220, 223, 230);border-radius: 4px;text-align: center;" <template v-if="selectedNode">
@click="handleChangeNodeSchema"><span style="line-height: 28px;" <!-- Node -->
:style="{color: is3DNode?'#409EFF':'#606266'}">2.5d</span></div> <table style="width: 100%;color: white;" border="1">
</el-col> <thead>
<tr>
<th colspan="2" style="text-align: left; padding: 10px;">
<div class="float-left" style="display:inline-flex;">
<v-simple-checkbox v-model="selectedNode.active"></v-simple-checkbox>
<span style="margin-left: 10px;">{{ nodeSchema.title }}</span>
</div>
<div class="float-right">
<v-icon style="margin-left: 10px;margin-right: 10px;" @click="drawNodeRect()">
mdi-adjust</v-icon>
<v-icon @click="outputNodeHandler()">mdi-send</v-icon>
</div>
</th>
</tr>
</thead>
<tbody>
<tr v-for="row in nodeSchema.rows" :key="row.key">
<td style="padding: 10px;width: 40%;">{{ row.name }}</td>
<td style="width: 60%;">
<v-color-picker v-if="row.type == 'color'" class="ma-2" canvas-height="80" width="259"
hide-inputs v-model="selectedNode[row.key]"></v-color-picker>
<v-simple-checkbox v-else-if="row.type == 'bool'" v-model="selectedNode[row.key]"
style="padding: 10px;width: 100%;"></v-simple-checkbox>
<input v-else :type="row.type" v-model="selectedNode[row.key]"
style="padding: 10px;width: 100%;"></input>
</td>
</tr>
</tbody>
</table>
<!-- Components -->
<table v-for="component in componentsSchema" style="width: 100%;color: white;" border="1">
<thead>
<tr>
<th colspan="2" style="text-align: left; padding: 10px;">
<div class="float-left" style="display:inline-flex;">
<v-simple-checkbox v-model="selectedNode[component.key].enabled">
</v-simple-checkbox>
<span style="margin-left: 10px;">{{ component.title }}</span>
</div>
<div class="float-right">
<v-icon @click="outputComponentHandler(component.key)">mdi-send</v-icon>
</div>
</th>
</tr>
</thead>
<tbody>
<tr v-for="row in component.rows" :key="row.key">
<td style="padding: 10px;width: 40%;">{{ row.name }}</td>
<td style="width: 60%;">
<v-color-picker v-if="row.type == 'color'" class="ma-2" canvas-height="80" width="259"
hide-inputs v-model="selectedNode[component.key][row.key]"></v-color-picker>
<textarea v-else-if="row.type == 'textarea'" rows="1"
v-model="selectedNode[component.key][row.key]" style="padding: 10px;width: 100%;">
</textarea>
<v-simple-checkbox v-else-if="row.type == 'bool'"
v-model="selectedNode[component.key][row.key]" style="padding: 10px;width: 100%;">
</v-simple-checkbox>
<input v-else :type="row.type" v-model="selectedNode[component.key][row.key]"
style="padding: 10px;width: 100%;"></input>
</td>
</tr>
</tbody>
</table>
</template>
</v-container>
</v-navigation-drawer>
</el-row> <v-content>
<el-card v-if="nodeSchema"> <v-container fill-height>
<div> <div id="content" class="content">
<span>{{ nodeSchema.title }}</span> <div class="contentWrap">
<el-button style="float: right; padding: 3px 0;" type="text" <div id="GameDiv" class="wrapper"><canvas id="GameCanvas"></canvas>
@click="outputNodeHandler">输出引用</el-button> <div id="splash">
<el-button style="float: right; padding: 3px 0;margin-right: 10px;" type="text" <div class="progress-bar stripes"><span></span></div>
@click="drawNodeRect">标记位置</el-button> </div>
</div> <div id="bulletin">
<hr style="margin: 10px 0;" /> <div id="sceneIsEmpty" class="inner">预览场景中啥都没有,加点什么,或在编辑器中打开其它场景吧</div>
<div> </div>
<el-row style="height: 28px;margin-bottom:3px;" v-for="(row, ri) in nodeSchema.rows" </div>
:key="ri"> </div>
<el-col v-for="(col, ci) in row" :key="ci" :span="col.span" </div>
style="text-align: left;line-height: 28px;"> </v-container>
<span v-if="col.type == 'label'">{{col.field}}</span> </v-content>
<el-input-number v-if="col.type == 'number'" v-model="node[col.field]"
controls-position="right" size="mini" style="width: 100%;">
</el-input-number>
<el-input-number v-if="col.type == '3DAngle'"
v-model="node.eulerAngles[col.field]" controls-position="right"
size="mini" style="width: 100%;"></el-input-number>
<el-input v-if="col.type == 'input'" v-model="node[col.field]" size="mini">
</el-input>
<el-color-picker v-if="col.type == 'color'" :ref="col.key" size="mini"
v-model="node[col.field]"></el-color-picker>
</el-col>
</el-row>
</div>
</el-card>
<el-card v-for="(section,index) in componentsSchema" :key="section.key"
style="margin: 10px 0;">
<div>
<el-checkbox v-model="node[section.key].enabled">{{ section.title }}</el-checkbox>
<el-button style="float: right; padding: 3px 0" type="text"
@click="outputComponentHandler(section.key)">输出引用</el-button>
</div>
<hr v-if="section.rows" style="margin: 10px 0;" />
<div>
<el-row style="height: 28px;margin-bottom:3px;" v-for="(row,ri) in section.rows"
:key="ri">
<el-col v-for="(col,ci) in row" :key="ci" :span="col.span"
style="text-align: left;line-height: 28px;">
<span v-if="col.type == 'label'">{{col.field}}</span>
<el-input-number v-if="col.type == 'number'"
v-model="node[section.key][col.field]" controls-position="right"
size="mini" style="width: 100%;"></el-input-number>
<el-input v-if="col.type == 'input'" v-model="node[section.key][col.field]"
size="mini"></el-input>
<el-input v-if="col.type == 'textarea'" type="textarea" :rows="1"
v-model="node[section.key][col.field]" size="mini">
</el-input>
<el-color-picker v-if="col.type == 'color'" :ref="col.key" size="mini"
v-model="node[section.key][col.field]"></el-color-picker>
<el-checkbox v-if="col.type == 'bool'"
v-model="node[section.key][col.field]"></el-checkbox>
<el-select v-if="col.type == 'select'"
v-model="node[section.key][col.field]" size="mini">
<el-option v-for="item in col.options" :key="item.value"
:label="item.label" :value="item.value">
</el-option>
</el-select>
</el-col>
</el-row>
</div>
</el-card>
</div>
</div>
</div>
</div>
<!-- 控制按钮 -->
<div id="panelCtl" style="position:absolute;left:5px;top:50px;height: 50px;display: flex;align-items: center;">
<el-popover width="150" placement="top-start" trigger="click">
<el-button type="info" icon="el-icon-setting" circle slot="reference" size="mini"></el-button>
<div>
<el-row style="margin:5px 0;">
<el-col :span="12" style="text-align:left;padding-top:7px;padding-left:5px;">
节点树
</el-col>
<el-col :span="12">
<el-switch style="margin: 5px;" v-model="isDevMode" @change="handleChangeMode"
active-color="#0099ff" inactive-color="gray">
</el-switch>
</el-col>
</el-row>
<el-row style="margin:5px 0;">
<el-col :span="12" style="text-align:left;padding-top:7px;padding-left:5px;">
调试信息
</el-col>
<el-col :span="12">
<el-switch style="margin: 5px;" v-model="isShowProfile" @change="handleChangeStats"
active-color="#0099ff" inactive-color="gray">
</el-switch>
</el-col>
</el-row>
<el-row style="margin:5px 0;">
<el-col :span="12" style="text-align:left;padding-top:7px;padding-left:5px;">
缓存
</el-col>
<el-col :span="12">
<el-switch style="margin: 5px;" v-model="isShowCache" @change="handleChangeCachePanel"
active-color="#0099ff" inactive-color="gray">
</el-switch>
</el-col>
</el-row>
<el-row style="margin:5px 0;">
<el-col :span="12" style="text-align:left;padding-top:7px;padding-left:5px;">
暗黑主题
</el-col>
<el-col :span="12">
<el-switch style="margin: 5px;" v-model="isDarkTheme" @change="handleChangeTheme"
active-color="#0099ff" inactive-color="gray">
</el-switch>
</el-col>
</el-row>
<el-row style="margin:5px 0;">
<el-col :span="12" style="text-align:left;padding-top:7px;padding-left:5px;">
检查版本
</el-col>
<el-col :span="12">
<el-switch style="margin: 5px;" v-model="isCheckVersion" @change="handleChangeCheckVersion"
active-color="#0099ff" inactive-color="gray">
</el-switch>
</el-col>
</el-row>
<el-row style="margin:5px 0;">
<el-col :span="12" style="text-align:left;padding-top:7px;padding-left:5px;">
源码
</el-col>
<el-col :span="12">
<el-badge value="new" :hidden="!needUpdate">
<Icon style="margin: 5px;" type="logo-github" size="24" @click="openGithub" />
</el-badge>
</el-col>
</el-row>
</div>
</el-popover>
</div>
<!-- 缓存面板弹窗 -->
<Modal v-model="isShowCache" width="800" :mask-closable="false" :mask="false" scrollable @on-cancel="closeCachePanel()" :title="cacheTitle" footer-hide="true">
<i-table border :columns="cacheColumns" height="600" size="small" :data="cacheData" :loading="cacheDataLoading">
<template slot-scope="{ row, index }" slot="cache_preview">
<img :src="window.location.protocol + '//' + window.location.host + '/' + row.preview" style="max-height: 40px;max-width: 120px;" v-if="row.preview">
<div v-if="!row.preview" style="max-height: 40px;">_</div>
</template>
<template slot-scope="{ row, index }" slot="cache_action">
<i-button type="primary" size="small" @click="showCacheItem(row.id)">Detail</i-button>
<i-button type="error" size="small" @click="releaseCacheItem(row.id)">Release</i-button>
</template>
<template slot-scope="{ row, index }" slot="cache_size">
{{row.size !== -1 ? row.size + 'MB' : '_'}}
</template>
</i-table>
</Modal>
</div>
<script type="text/javascript" charset="utf-8" src="app/editor/static/preview-templates/ccc-devtools/libs/vue/vue.min.js"></script> <v-dialog v-model="cacheDialog" persistent scrollable>
<script type="text/javascript" charset="utf-8" src="app/editor/static/preview-templates/ccc-devtools/libs/vue-beauty/js/vue-beauty.min.js"></script> <v-card>
<script type="text/javascript" charset="utf-8" src="app/editor/static/preview-templates/ccc-devtools/libs/element/js/element-ui.js"></script> <v-card-title>
<script type="text/javascript" charset="utf-8" src="app/editor/static/preview-templates/ccc-devtools/libs/iview/js/iview.js"></script> {{ cacheTitle }}
<script type="text/javascript" charset="utf-8" src="app/editor/static/preview-templates/ccc-devtools/libs/stats/Stats.js"></script> <v-spacer></v-spacer>
<script type="text/javascript" charset="utf-8" src="app/editor/static/preview-templates/ccc-devtools/config.js"></script> <v-text-field v-model="cacheSearchText" append-icon="mdi-magnify" label="Search" single-line
<script type="text/javascript" charset="utf-8" src="app/editor/static/preview-templates/ccc-devtools/js/app.js"></script> hide-details>
</v-text-field>
</v-card-title>
<v-divider></v-divider>
<v-card-text>
<v-data-table :headers="cacheHeaders" :items="cacheData" :search="cacheSearchText" :sort-by="['size']"
:sort-desc="[true]" :footer-props="{
showFirstLastPage: true,
firstIcon: 'mdi-chevron-double-left',
lastIcon: 'mdi-chevron-double-right',
}">
<template v-slot:item.size="{ item }">
{{ item.size == -1 ? '_' : (item.size +'MB') }}
</template>
<template v-slot:item.preview="{ item }">
<div style="height: 60px;display: flex;align-items: center;">
<img :src="window.location.protocol + '//' + window.location.host + '/' + item.preview"
style="max-height: 60px;max-width: 120px;" v-if="item.preview">
<template v-else>_</template>
</div>
</template>
</v-data-table>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-btn color="blue darken-1" text @click="cacheDialog = false">Close</v-btn>
<v-spacer></v-spacer>
<v-switch v-model="cacheOnlyTexture" label="只显示纹理"></v-switch>
</v-card-actions>
</v-card>
</v-dialog>
</v-app>
<script src="app/editor/static/preview-templates/ccc-devtools/libs/js/vue.min.js"></script>
<script src="app/editor/static/preview-templates/ccc-devtools/libs/js/vuetify.js"></script>
<script src="app/editor/static/preview-templates/ccc-devtools/config.js"></script>
<script src="app/editor/static/preview-templates/ccc-devtools/libs/js/cc-console-utils.js"></script>
<script src="app/editor/static/preview-templates/ccc-devtools/preview.js"></script>

596
js/app.js
View File

@ -1,596 +0,0 @@
let app = new Vue({
el: '#app',
data: {
needUpdate: false,
is3DNode: false,
isDevMode: false,
isShowProfile: false,
isShowCache: false,
isAutoRefreshTree: true,
isDarkTheme: false,
isCheckVersion: false,
filterText: '',
splitLeft: 0.7,
splitRight: 0.5,
defaultExpandedKeys: [],
sceneTreeData: [],
nodeProps: {
children: 'children',
label: 'name',
isLeaf: 'leaf'
},
node: null,
nodeSchema: {},
componentsSchema: [],
intervalId: -1,
cacheTitle: '缓存',
cacheColumns: [{
title: 'Type',
key: 'content',
width: 150,
align: 'center',
filters: [{
label: 'png',
value: 'png'
}, {
label: 'jpg',
value: 'jpg'
}, {
label: 'cc.Texture2D',
value: 'cc.Texture2D'
}, {
label: 'cc.SpriteFrame',
value: 'cc.SpriteFrame'
}, {
label: 'cc.Sprite',
value: 'cc.Sprite'
}, {
label: 'cc.Prefab',
value: 'cc.Prefab'
}, {
label: 'cc.AnimationClip',
value: 'cc.AnimationClip'
}],
filterMultiple: false,
filterMethod(value, row) {
return row.content === value;
}
}, {
title: 'Name',
key: 'name',
width: 220,
align: 'center',
sortable: true
}, {
title: 'Size',
slot: 'cache_size',
key: 'size',
align: 'center',
width: 120,
sortable: true
}, {
title: 'Preview',
slot: 'cache_preview',
align: 'center',
width: 150
}, {
title: 'Queue',
key: 'queueId',
sortable: true,
width: 120,
align: 'center'
}, {
title: 'Action',
slot: 'cache_action',
width: 150,
align: 'center',
fixed: 'right'
}],
cacheData: [],
cacheDataLoading: false
},
methods: {
api: function (url, cb) {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
let response = xhr.responseText;
cb(JSON.parse(xhr.responseText));
}
};
xhr.open("GET", url, true);
xhr.send();
},
compareVersion: function (localVersion, remoteVersion) {
let vL = localVersion.split('.');
let vR = remoteVersion.split('.');
for (let i = 0; i < vL.length; ++i) {
let a = parseInt(vL[i], 10);
let b = parseInt(vR[i] || '0', 10);
if (a === b) {
continue;
} else if (a > b) {
return false;
} else if (a < b) {
return true;
}
}
if (vR.length > vL.length) {
return true;
} else {
return false;
}
},
checkVersion: function () {
this.api('https://raw.githubusercontent.com/potato47/ccc-devtools/master/version.json', (
data) => {
let remoteVersion = data.version;
this.api('app/editor/static/preview-templates/ccc-devtools/version.json', (
data) => {
let localVersion = data.version;
versionStatus = this.compareVersion(localVersion, remoteVersion);
this.$data.needUpdate = versionStatus;
console.groupCollapsed('ccc-devtoos')
console.log('本地版本:' + localVersion);
console.log('远程版本:' + remoteVersion);
console.log('更新地址:' + 'https://github.com/potato47/ccc-devtools.git');
console.groupEnd('ccc-devtoos');
});
});
},
handleRefreshTree() {
this.$data.sceneTreeData = [];
setTimeout(() => {
this.updateTreeData();
}, 0);
},
handleSwitchTreeMode() {
},
updateTreeData() {
this.$data.sceneTreeData = cc.director.getScene().children;
this.defaultExpandedKeys = [this.$data.sceneTreeData[0]._id];
},
handleNodesSelect(nodes) {
if (nodes.length === 1) {
this.handleNodeClick(nodes[0]);
} else {
this.handleNodeClick(null);
}
},
handleNodeClick(node) {
if (node) {
this.$data.node = node;
if (!node.hex_color) {
cc.js.getset(node, 'hex_color', () => {
return '#' + node.color.toHEX('#rrggbb');
}, (hex) => {
node.color = new cc.Color().fromHEX(hex);
}, false, true);
}
let superPreLoad = node._onPreDestroy;
node._onPreDestroy = () => {
superPreLoad.apply(node);
if (this.$data && this.$data.node === node) {
this.$data.node = null;
}
}
this.$data.nodeSchema = this.$data.is3DNode ? NEX_CONFIG.nodeSchema.node3d : NEX_CONFIG
.nodeSchema.node2d;
let componentsSchema = [];
for (let component of node._components) {
let schema = NEX_CONFIG.componentsSchema[component.__classname__];
if (schema) {
node[schema.key] = node.getComponent(schema.key);
for (let i = 0; i < schema.rows.length; i++) {
for (let j = 0; j < schema.rows[i].length; j++) {
if (schema.rows[i][j].type === 'color') {
if (!node[schema.key][schema.rows[i][j].field]) {
cc.js.getset(node[schema.key], schema.rows[i][j].field, () => {
return '#' + node.getComponent(schema.key)[schema.rows[i][j]
.rawField].toHEX('#rrggbb');
}, (hex) => {
node.getComponent(schema.key)[schema.rows[i][j].rawField] =
new cc.Color().fromHEX(hex);
}, false, true);
}
}
}
}
} else {
schema = {
title: component.__classname__,
key: component.__classname__
};
node[schema.key] = node.getComponent(schema.key);
}
componentsSchema.push(schema);
}
this.$data.componentsSchema = componentsSchema;
} else {
this.$data.node = null;
}
},
outputNodeHandler(target) {
let i = 1;
while (window['temp' + i] !== undefined) {
i++;
}
window['temp' + i] = this.$data.node;
console.log('temp' + i);
console.log(window['temp' + i]);
},
outputComponentHandler(data) {
let i = 1;
while (window['temp' + i] !== undefined) {
i++;
}
window['temp' + i] = this.$data.node.getComponent(data);
console.log('temp' + i);
console.log(window['temp' + i]);
},
drawNodeRect(node) {
cc.where(this.$data.node);
},
releaseCacheItem(id) {
console.log('resease item ', id);
cc.loader.release(id);
},
showCacheItem(id) {
console.log(cc.loader._cache[id]);
},
openGithub() {
window.open('https://github.com/potato47/ccc-devtools');
},
filterNode(value, node) {
if (!value) return true;
return node.name.toLowerCase().indexOf(value.toLowerCase()) !== -1;
},
openCachePanel() {
this.$data.cacheDataLoading = true;
setTimeout(() => {
let rawCacheData = cc.loader._cache;
let cacheData = [];
let totalTextureSize = 0;
for (let k in rawCacheData) {
let item = rawCacheData[k];
// console.log(item)
if (item.type !== 'js' && item.type !== 'json') {
let itemName = '_';
let preview = '';
let content = item.content.__classname__ ? item.content.__classname__ : item.type;
let formatSize = -1;
if (item.type === 'png' || item.type === 'jpg') {
let texture = rawCacheData[k.replace('.' + item.type, '.json')];
if (texture && texture._owner && texture._owner._name) {
itemName = texture._owner._name;
preview = texture.content.url;
}
} else {
if (item.content.name && item.content.name.length > 0) {
itemName = item.content.name;
} else if (item._owner) {
itemName = item._owner.name || '_';
}
if (content === 'cc.Texture2D') {
let texture = item.content;
preview = texture.url;
let textureSize = texture.width * texture.height * ((texture._native === '.jpg' ? 3 : 4) / 1024 / 1024);
totalTextureSize += textureSize;
// sizeStr = textureSize.toFixed(3) + 'M';
formatSize = Math.round(textureSize * 1000) / 1000;
} else if (content === 'cc.SpriteFrame') {
preview = item.content._texture.url;
}
}
cacheData.push({
queueId: item.queueId,
type: item.type,
name: itemName,
preview: preview,
id: item.id,
content: content,
size: formatSize
});
}
}
this.$data.cacheData = cacheData;
this.$data.cacheTitle = `缓存 [文件总数:${cacheData.length}][纹理缓存:${totalTextureSize.toFixed(2) + 'M'}]`;
this.$data.cacheDataLoading = false;
}, 0);
},
closeCachePanel() {
this.$data.cacheData = [];
this.$data.cacheTitle = `缓存`;
},
openDevMode() {
setTimeout(() => {
if (!cc.Node.prototype.isLeaf) {
cc.js.getset(cc.Node.prototype, 'isLeaf', function () {
return !this.children || this.childrenCount === 0;
}, function (value) {
}, false, true);
}
let top = document.getElementById('top');
top.appendChild(document.getElementsByClassName('toolbar')[0]);
document.getElementById('game_panel').appendChild(document.getElementById('content'));
let scene = cc.director.getScene();
if (scene) {
this.updateTreeData();
}
cc.director.on(cc.Director.EVENT_AFTER_SCENE_LAUNCH, () => {
this.updateTreeData();
}, this);
cc.director.on(cc.Director.EVENT_BEFORE_SCENE_LOADING, () => {
this.$data.node = null;
this.$data.sceneTreeData = [];
this.$data.treeParam = [];
}, this);
localStorage.setItem('isDevMode', 1);
}, 0);
},
closeDevMode() {
this.$data.node = null;
this.$data.sceneTreeData = [];
cc.director.targetOff(this);
clearInterval(this.$data.intervalId);
document.body.appendChild(document.getElementsByClassName('toolbar')[0]);
document.body.appendChild(document.getElementById('content'));
localStorage.setItem('isDevMode', 0);
},
handleChangeNodeSchema() {
if (this.is3DNode) {
this.is3DNode = false;
} else {
this.is3DNode = true;
}
this.$data.nodeSchema = this.$data.is3DNode ? NEX_CONFIG.nodeSchema.node3d : NEX_CONFIG.nodeSchema
.node2d;
},
handleChangeMode(data) {
data ? this.openDevMode() : this.closeDevMode();
},
handleChangeCachePanel(data) {
data ? this.openCachePanel() : this.closeCachePanel();
},
handleChangeStats() {
if (this.$data.isShowProfile) {
let addStats = function (stats) {
stats.dom.style.position = 'relative';
stats.dom.style.float = 'right';
stats.dom.style.marginLeft = '10px';
stats.dom.style.marginBottom = '10px';
// stats.dom.style.pointerEvents = 'none';
stats.dom.className = 'statsPanel';
document.getElementById('panelCtl').appendChild(stats.dom);
localStorage.setItem('isShowProfile', '1')
}
let animate = () => {
if (this.$data.isShowProfile) {
stats.update();
requestAnimationFrame(animate);
}
}
let stats = new Stats();
addStats(stats);
animate();
} else {
let panels = document.getElementsByClassName('statsPanel');
while (panels.length > 0) {
panels[0].parentElement.removeChild(panels[0]);
}
localStorage.setItem('isShowProfile', '0');
}
},
handleChangeCheckVersion(isCheckVersion) {
if (isCheckVersion) {
localStorage.setItem('isCheckVersion', '1');
this.checkVersion();
} else {
localStorage.setItem('isCheckVersion', '0');
}
},
handleChangeTheme(isDark) {
isDark ? this.addDarkTheme() : this.removeDarkTheme();
},
// 添加暗色主题
addDarkTheme() {
let link = document.createElement('link');
link.type = 'text/css';
link.id = "theme-css-dark";
link.rel = 'stylesheet';
link.href = 'app/editor/static/preview-templates/ccc-devtools/css/themes/dark.css';
document.getElementsByTagName("head")[0].appendChild(link);
localStorage.setItem('isDarkTheme', 1);
},
// 删除暗色主题
removeDarkTheme() {
document.getElementById('theme-css-dark').remove();
localStorage.setItem('isDarkTheme', 0);
},
fitFullScreen() {
document.getElementsByClassName('toolbar')[0].style.display = 'none';
let gameDiv = document.getElementById('GameDiv');
let gameContainer = document.getElementById('Cocos2dGameContainer');
let gameCanvas = document.getElementById('GameCanvas');
gameDiv.style.width = '100%';
gameDiv.style.height = '100%';
gameCanvas.style.width = '100%';
gameCanvas.style.height = '100%';
// document.body.style.cssText+="-webkit-transform: rotate(-90deg);-moz-transform: rotate(-90deg)";
},
initConsoleUtil() {
if (cc.tree) return;
cc.tree = function (key) {
let index = key || 0;
let treeNode = function (node) {
let nameStyle =
`color: ${node.parent === null || node.activeInHierarchy ? 'green' : 'grey'}; font-size: 14px;font-weight:bold`;
let propStyle =
`color: black; background: lightgrey;margin-left: 5px;border-radius:3px;padding: 0 3px;font-size: 10px;font-weight:bold`;
let indexStyle =
`color: orange; background: black;margin-left: 5px;border-radius:3px;padding:0 3px;fonrt-size: 10px;font-weight:bold;`
let nameValue = `%c${node.name}`;
let propValue =
`%c${node.x.toFixed(0) + ',' + node.y.toFixed(0) + ',' + node.width.toFixed(0) + ',' + node.height.toFixed(0) + ',' + node.scale.toFixed(1)}`
let indexValue = `%c${index++}`;
if (node.childrenCount > 0) {
console.groupCollapsed(nameValue + propValue + indexValue, nameStyle,
propStyle, indexStyle);
for (let i = 0; i < node.childrenCount; i++) {
treeNode(node.children[i]);
}
console.groupEnd();
} else {
console.log(nameValue + propValue + indexValue, nameStyle, propStyle,
indexStyle);
}
}
if (key) {
let node = cc.cat(key);
index = node['tempIndex'];
treeNode(node);
} else {
let scene = cc.director.getScene();
treeNode(scene);
}
return '属性依次为x,y,width,height,scale.使用cc.cat(id)查看详细属性.';
}
cc.cat = function (key) {
let index = 0;
let target;
let sortId = function (node) {
if (target) return;
if (cc.js.isNumber(key)) {
if (key === index++) {
target = node;
return;
}
} else {
if (key.toLowerCase() === node.name.toLowerCase()) {
target = node;
return;
} else {
index++;
}
}
if (node.childrenCount > 0) {
for (let i = 0; i < node.childrenCount; i++) {
sortId(node.children[i]);
}
}
}
let scene = cc.director.getScene();
sortId(scene);
target['tempIndex'] = cc.js.isNumber(key) ? key : index;
return target;
}
cc.list = function (key) {
let targets = [];
let step = function (node) {
if (node.name.toLowerCase().indexOf(key.toLowerCase()) > -1) {
targets.push(node);
}
if (node.childrenCount > 0) {
for (let i = 0; i < node.childrenCount; i++) {
step(node.children[i]);
}
}
}
let scene = cc.director.getScene();
step(scene);
if (targets.length === 1) {
return targets[0];
} else {
return targets;
}
}
cc.where = function (key) {
let target = key.name ? key : cc.cat(key);
if (!target) {
return null;
}
let rect = target.getBoundingBoxToWorld();
let borderNode = new cc.Node();
let bgNode = new cc.Node();
let graphics = bgNode.addComponent(cc.Graphics);
let scene = cc.director.getScene();
scene.addChild(bgNode);
bgNode.addChild(borderNode);
bgNode.position = scene.convertToNodeSpaceAR(rect.center);
let isZeroSize = rect.width === 0 || rect.height === 0;
if (isZeroSize) {
graphics.circle(0, 0, 100);
graphics.fillColor = cc.Color.GREEN;
graphics.fill();
} else {
bgNode.width = rect.width;
bgNode.height = rect.height;
graphics.rect(-bgNode.width / 2, -bgNode.height / 2, bgNode.width, bgNode.height);
graphics.strokeColor = cc.Color.RED;
graphics.lineWidth = 10;
graphics.stroke()
}
setTimeout(() => {
if (cc.isValid(bgNode)) {
bgNode.destroy();
}
}, 2000);
return target;
}
}
},
watch: {
filterText(val) {
this.$refs.sceneTree.filter(val);
// console.log(val);
}
},
created: function () {
document.body.insertBefore(document.getElementById('app'), document.body.firstChild);
let onCCInit = () => {
this.initConsoleUtil();
if (cc.sys.isMobile) {
this.fitFullScreen();
}
if (localStorage.getItem('isDevMode') === '1') {
this.$data.isDevMode = true;
this.openDevMode();
} else {
this.$data.isDevMode = false;
}
if (localStorage.getItem('isDarkTheme') === '1') {
this.$data.isDarkTheme = true;
this.addDarkTheme();
} else {
this.$data.isDarkTheme = false;
}
if (localStorage.getItem('isCheckVersion') === '1') {
this.$data.isCheckVersion = true;
this.checkVersion();
} else {
this.$data.isCheckVersion = false;
}
this.$data.isShowProfile = localStorage.getItem('isShowProfile') === '1';
setTimeout(() => {
this.handleChangeStats();
}, 0);
}
let checkCC = () => {
if (window.cc && window.cc.director) {
onCCInit();
clearInterval(this.$data.intervalId);
} else {
// console.log('cc is not init');
}
}
this.$data.intervalId = setInterval(checkCC, 500);
setTimeout(checkCC, 0);
},
});

336
libs/css/googlefonts.css Normal file
View File

@ -0,0 +1,336 @@
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
src: local('Roboto Thin'), local('Roboto-Thin'), url(../fonts/googlefonts-base.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
src: local('Roboto Thin'), local('Roboto-Thin'), url(../fonts/googlefonts-base.woff22) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
src: local('Roboto Thin'), local('Roboto-Thin'), url(../fonts/googlefonts-base.woff22) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
src: local('Roboto Thin'), local('Roboto-Thin'), url(../fonts/googlefonts-base.woff22) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
src: local('Roboto Thin'), local('Roboto-Thin'), url(../fonts/googlefonts-base.woff22) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
src: local('Roboto Thin'), local('Roboto-Thin'), url(../fonts/googlefonts-base.woff22) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
src: local('Roboto Thin'), local('Roboto-Thin'), url(../fonts/googlefonts-base.woff2format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
src: local('Roboto Light'), local('Roboto-Light'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
src: local('Roboto Light'), local('Roboto-Light'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
src: local('Roboto Light'), local('Roboto-Light'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
src: local('Roboto Light'), local('Roboto-Light'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
src: local('Roboto Light'), local('Roboto-Light'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
src: local('Roboto Light'), local('Roboto-Light'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
src: local('Roboto Light'), local('Roboto-Light'), url(../fonts/googlefonts-base.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../fonts/googlefonts-base.woff2format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../fonts/googlefonts-base.woff2format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../fonts/googlefonts-base.woff2format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../fonts/googlefonts-base.woff2format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../fonts/googlefonts-base.woff2format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../fonts/googlefonts-base.woff2format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../fonts/googlefonts-base.woff2rmat('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/googlefonts-base.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/googlefonts-base.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
src: local('Roboto Black'), local('Roboto-Black'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
src: local('Roboto Black'), local('Roboto-Black'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
src: local('Roboto Black'), local('Roboto-Black'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
src: local('Roboto Black'), local('Roboto-Black'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
src: local('Roboto Black'), local('Roboto-Black'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
src: local('Roboto Black'), local('Roboto-Black'), url(../fonts/googlefonts-base.woff2f2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
src: local('Roboto Black'), local('Roboto-Black'), url(../fonts/googlefonts-base.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

3
libs/css/materialdesignicons.min.css vendored Normal file

File diff suppressed because one or more lines are too long

8
libs/css/vuetify.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

167
libs/js/cc-console-utils.js Normal file
View File

@ -0,0 +1,167 @@
const initConsoleUtil = function () {
if (cc.tree) return;
cc.tree = function (key) {
let index = key || 0;
let treeNode = function (node) {
let nameStyle =
`color: ${node.parent === null || node.activeInHierarchy ? 'green' : 'grey'}; font-size: 14px;font-weight:bold`;
let propStyle =
`color: black; background: lightgrey;margin-left: 5px;border-radius:3px;padding: 0 3px;font-size: 10px;font-weight:bold`;
let indexStyle =
`color: orange; background: black;margin-left: 5px;border-radius:3px;padding:0 3px;fonrt-size: 10px;font-weight:bold;`
let nameValue = `%c${node.name}`;
let propValue =
`%c${node.x.toFixed(0) + ',' + node.y.toFixed(0) + ',' + node.width.toFixed(0) + ',' + node.height.toFixed(0) + ',' + node.scale.toFixed(1)}`
let indexValue = `%c${index++}`;
if (node.childrenCount > 0) {
console.groupCollapsed(nameValue + propValue + indexValue, nameStyle,
propStyle, indexStyle);
for (let i = 0; i < node.childrenCount; i++) {
treeNode(node.children[i]);
}
console.groupEnd();
} else {
console.log(nameValue + propValue + indexValue, nameStyle, propStyle,
indexStyle);
}
}
if (key) {
let node = cc.cat(key);
index = node['tempIndex'];
treeNode(node);
} else {
let scene = cc.director.getScene();
treeNode(scene);
}
return '属性依次为x,y,width,height,scale.使用cc.cat(id)查看详细属性.';
}
cc.cat = function (key) {
let index = 0;
let target;
let sortId = function (node) {
if (target) return;
if (cc.js.isNumber(key)) {
if (key === index++) {
target = node;
return;
}
} else {
if (key.toLowerCase() === node.name.toLowerCase()) {
target = node;
return;
} else {
index++;
}
}
if (node.childrenCount > 0) {
for (let i = 0; i < node.childrenCount; i++) {
sortId(node.children[i]);
}
}
}
let scene = cc.director.getScene();
sortId(scene);
target['tempIndex'] = cc.js.isNumber(key) ? key : index;
return target;
}
cc.list = function (key) {
let targets = [];
let step = function (node) {
if (node.name.toLowerCase().indexOf(key.toLowerCase()) > -1) {
targets.push(node);
}
if (node.childrenCount > 0) {
for (let i = 0; i < node.childrenCount; i++) {
step(node.children[i]);
}
}
}
let scene = cc.director.getScene();
step(scene);
if (targets.length === 1) {
return targets[0];
} else {
return targets;
}
}
cc.where = function (key) {
let target = key.name ? key : cc.cat(key);
if (!target) {
return null;
}
let rect = target.getBoundingBoxToWorld();
let bgNode = new cc.Node();
let graphics = bgNode.addComponent(cc.Graphics);
let scene = cc.director.getScene();
scene.addChild(bgNode);
bgNode.position = rect.center;
bgNode.group = target.group;
bgNode.zIndex = cc.macro.MAX_ZINDEX;
let isZeroSize = rect.width === 0 || rect.height === 0;
if (isZeroSize) {
graphics.circle(0, 0, 100);
graphics.fillColor = cc.Color.GREEN;
graphics.fill();
} else {
bgNode.width = rect.width;
bgNode.height = rect.height;
graphics.rect(-bgNode.width / 2, -bgNode.height / 2, bgNode.width, bgNode.height);
graphics.fillColor = new cc.Color().fromHEX('#E91E6390');
graphics.fill();
}
setTimeout(() => {
if (cc.isValid(bgNode)) {
bgNode.destroy();
}
}, 2000);
return target;
}
cc.cache = function () {
let rawCacheData = cc.loader._cache;
let cacheData = [];
let totalTextureSize = 0;
for (let k in rawCacheData) {
let item = rawCacheData[k];
if (item.type !== 'js' && item.type !== 'json') {
let itemName = '_';
let preview = '';
let content = (item.content && item.content.__classname__) ? item.content.__classname__ : item.type;
let formatSize = -1;
if (item.type === 'png' || item.type === 'jpg') {
let texture = rawCacheData[k.replace('.' + item.type, '.json')];
if (texture && texture._owner && texture._owner._name) {
itemName = texture._owner._name;
preview = texture.content.url;
}
} else {
if (item.content.name && item.content.name.length > 0) {
itemName = item.content.name;
} else if (item._owner) {
itemName = (item._owner && item._owner.name) || '_';
}
if (content === 'cc.Texture2D') {
let texture = item.content;
preview = texture.url;
let textureSize = texture.width * texture.height * ((texture._native === '.jpg' ? 3 : 4) / 1024 / 1024);
totalTextureSize += textureSize;
// sizeStr = textureSize.toFixed(3) + 'M';
formatSize = Math.round(textureSize * 1000) / 1000;
} else if (content === 'cc.SpriteFrame') {
preview = item.content._texture.url;
}
}
cacheData.push({
queueId: item.queueId,
type: item.type,
name: itemName,
preview: preview,
id: item.id,
content: content,
size: formatSize
});
}
}
let cacheTitle = `缓存 [文件总数:${cacheData.length}][纹理缓存:${totalTextureSize.toFixed(2) + 'M'}]`;
return [cacheData, cacheTitle];
}
}

6
libs/js/vue.min.js vendored Normal file

File diff suppressed because one or more lines are too long

41499
libs/js/vuetify.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,200 +0,0 @@
var Stats = function () {
var mode = 0;
var container = document.createElement('div');
container.style.cssText = 'position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000';
container.addEventListener('click', function (event) {
event.preventDefault();
showPanel(++mode % container.children.length);
}, false);
//
function addPanel(panel) {
container.appendChild(panel.dom);
return panel;
}
function showPanel(id) {
for (var i = 0; i < container.children.length; i++) {
container.children[i].style.display = i === id ? 'block' : 'none';
}
mode = id;
}
function getDrawcalls() {
if (window.cc) {
return cc.g_NumberOfDraws || cc.renderer.drawCalls;
} else {
return Infinity;
}
}
function getTexMemory() {
if (window.cc) {
let totalTextureSize = 0;
let cacheData = cc.loader._cache;
for (let k in cacheData) {
let item = cacheData[k];
if (item.content && item.content.__classname__ && item.content.__classname__ === 'cc.Texture2D') {
let texture = item.content;
let textureSize = texture.width * texture.height * ((texture._native === '.jpg' ? 3 : 4) / 1024 / 1024);
totalTextureSize += textureSize;
}
}
return totalTextureSize;
} else {
return Infinity;
}
}
//
var beginTime = (performance || Date).now(), prevTime = beginTime, frames = 0;
var texPanel = addPanel(new Stats.Panel('纹理内存', 'MB', '#0ff', '#002'));
var dcPanel = addPanel(new Stats.Panel('DrawCall', '', '#ff8', '#221'));
var fpsPanel = addPanel(new Stats.Panel('FPS', '', '#0f0', '#020'));
var msPanel = addPanel(new Stats.Panel('渲染时间', 'MS', '#f08', '#201'));
// if (self.performance && self.performance.memory) {
// var memPanel = addPanel(new Stats.Panel('MB', '#f08', '#201'));
// }
showPanel(0);
return {
REVISION: 16,
dom: container,
addPanel: addPanel,
showPanel: showPanel,
begin: function () {
beginTime = (performance || Date).now();
},
end: function () {
frames++;
var time = (performance || Date).now();
msPanel.update(time - beginTime, 200);
if (time >= prevTime + 1000) {
fpsPanel.update((frames * 1000) / (time - prevTime), 100);
prevTime = time;
frames = 0;
// if (memPanel) {
// var memory = performance.memory;
// memPanel.update(memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576);
// }
texPanel.update(getTexMemory(), 1000);
dcPanel.update(getDrawcalls(), 500);
}
return time;
},
update: function () {
beginTime = this.end();
},
// Backwards Compatibility
domElement: container,
setMode: showPanel
};
};
Stats.Panel = function (name, unit, fg, bg) {
var min = Infinity, max = 0, round = Math.round;
var PR = round(window.devicePixelRatio || 1);
var WIDTH = 80 * PR, HEIGHT = 48 * PR,
TEXT_X = 3 * PR, TEXT_Y = 2 * PR,
GRAPH_X = 3 * PR, GRAPH_Y = 15 * PR,
GRAPH_WIDTH = 74 * PR, GRAPH_HEIGHT = 30 * PR;
var canvas = document.createElement('canvas');
canvas.width = WIDTH;
canvas.height = HEIGHT;
canvas.style.cssText = 'width:80px;height:48px';
var context = canvas.getContext('2d');
context.font = 'bold ' + (9 * PR) + 'px Helvetica,Arial,sans-serif';
context.textBaseline = 'top';
context.fillStyle = bg;
context.fillRect(0, 0, WIDTH, HEIGHT);
context.fillStyle = fg;
context.fillText(name, TEXT_X, TEXT_Y);
context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);
context.fillStyle = bg;
context.globalAlpha = 0.9;
context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);
return {
dom: canvas,
update: function (value, maxValue) {
min = Math.min(min, value);
max = Math.max(max, value);
context.fillStyle = bg;
context.globalAlpha = 1;
context.fillRect(0, 0, WIDTH, GRAPH_Y);
context.fillStyle = fg;
// context.fillText(round(value) + ' ' + name + ' (' + round(min) + '-' + round(max) + ')', TEXT_X, TEXT_Y);
context.fillText(name + ' ' + round(value) + unit, TEXT_X, TEXT_Y);
context.drawImage(canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT);
context.fillRect(GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT);
context.fillStyle = bg;
context.globalAlpha = 0.9;
context.fillRect(GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, round((1 - (value / maxValue)) * GRAPH_HEIGHT));
}
};
};
// export { Stats as default };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

6
libs/vue/vue.min.js vendored

File diff suppressed because one or more lines are too long

187
preview.js Normal file
View File

@ -0,0 +1,187 @@
const app = new Vue({
el: '#app',
vuetify: new Vuetify({
theme: { dark: true }
}),
data: {
drawer: false,
cacheDialog: false,
cacheTitle: '',
cacheHeaders: [
{ text: 'Type', value: 'type' },
{ text: 'Name', value: 'name' },
{ text: 'Preivew', value: 'preview' },
{ text: 'ID', value: 'id' },
{ text: 'Content', value: 'content' },
{ text: 'Size', value: 'size' },
],
cacheRawData: [],
cacheData: [],
cacheSearchText: null,
cacheOnlyTexture: true,
treeData: [],
selectedNodes: [],
intervalId: -1,
treeSearchText: null,
nodeSchema: {},
componentsSchema: [],
},
created() {
this.waitCCInit().then(() => {
this.startUpdateTree();
initConsoleUtil();
});
},
watch: {
cacheOnlyTexture() {
this.updateCacheData();
}
},
computed: {
treeFilter() {
return (item, search, textKey) => item[textKey].indexOf(search) > -1;
},
selectedNode() {
if (!this.selectedNodes.length) return undefined
let node = getNodeById(this.selectedNodes[0]);
if (node) {
if (!node.hex_color) {
cc.js.getset(node, 'hex_color', () => {
return '#' + node.color.toHEX('#rrggbb');
}, (hex) => {
node.color = new cc.Color().fromHEX(hex);
}, false, true);
}
let superPreLoad = node._onPreDestroy;
node._onPreDestroy = () => {
superPreLoad.apply(node);
if (this.selectedNodes.length > 0 && this.selectedNodes[0] === node._id) {
this.selectedNodes.pop();
}
}
this.nodeSchema = NEX_CONFIG.nodeSchema.node2d;
let componentsSchema = [];
for (let component of node._components) {
let schema = NEX_CONFIG.componentsSchema[component.__classname__];
if (schema) {
node[schema.key] = node.getComponent(schema.key);
for (let i = 0; i < schema.rows.length; i++) {
if (schema.rows[i].type === 'color') {
if (!node[schema.key][schema.rows[i].key]) {
cc.js.getset(node[schema.key], schema.rows[i].key, () => {
return '#' + node.getComponent(schema.key)[schema.rows[i].rawKey].toHEX('#rrggbb');
}, (hex) => {
node.getComponent(schema.key)[schema.rows[i].rawKey] = new cc.Color().fromHEX(hex);
}, false, true);
}
}
}
} else {
schema = {
title: component.__classname__,
key: component.__classname__
};
node[schema.key] = node.getComponent(schema.key);
}
componentsSchema.push(schema);
}
this.componentsSchema = componentsSchema;
}
return node;
},
},
methods: {
waitCCInit() {
return new Promise((resolve, reject) => {
let id = setInterval(() => {
if (window.cc) {
resolve();
clearInterval(id);
}
}, 500);
});
},
refreshTree: function () {
if (!this.$data.drawer || !window.cc || !cc.director.getScene() || !cc.director.getScene().children) return;
this.$data.treeData = getChildren(cc.director.getScene());
},
startUpdateTree: function () {
this.$data.intervalId = setInterval(() => {
this.refreshTree();
}, 200);
},
stopUpdateTree: function () {
clearInterval(this.$data.intervalId);
},
outputNodeHandler(id) {
let i = 1;
while (window['temp' + i] !== undefined) {
i++;
}
window['temp' + i] = this.selectedNode;
console.log('temp' + i);
console.log(window['temp' + i]);
},
outputComponentHandler(component) {
let i = 1;
while (window['temp' + i] !== undefined) {
i++;
}
window['temp' + i] = this.selectedNode.getComponent(component);
console.log('temp' + i);
console.log(window['temp' + i]);
},
drawNodeRect() {
cc.where(this.selectedNode);
},
updateCacheData() {
if (this.$data.cacheOnlyTexture) {
this.$data.cacheData = this.$data.cacheRawData.filter(item => item.content === 'cc.Texture2D');
} else {
this.$data.cacheData = this.$data.cacheRawData;
}
},
openCacheDialog() {
[this.$data.cacheRawData, this.$data.cacheTitle] = cc.cache();
this.updateCacheData();
this.$data.cacheDialog = true;
},
openGithub() {
window.open('https://github.com/potato47/ccc-devtools');
},
openCocosForum() {
window.open('https://forum.cocos.com/');
},
openCocosDocs() {
window.open('https://docs.cocos.com/');
}
}
});
function getChildren(node) {
return node.children.map(child => {
let children = (child.children && child.children.length > 0) ? getChildren(child) : [];
return { id: child._id, name: child.name, active: child.activeInHierarchy, children };
});
}
function getNodeById(id) {
let target;
const search = function (node) {
if (node._id === id) {
target = node;
return;
}
if (node.childrenCount) {
for (let i = 0; i < node.childrenCount; i++) {
if (!target) {
search(node.children[i]);
}
}
}
}
const scene = cc.director.getScene();
search(scene);
return target;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 713 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

BIN
screenshots/preview1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 KiB

After

Width:  |  Height:  |  Size: 119 KiB

BIN
screenshots/preview4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

BIN
screenshots/preview5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

View File

@ -1,6 +1,6 @@
{ {
"name": "ccc-devtools", "name": "ccc-devtools",
"version": "2.3.3", "version": "3.0.0",
"author": "Next", "author": "Next",
"repo": "https://github.com/potato47/ccc-devtools.git" "repo": "https://github.com/potato47/ccc-devtools.git"
} }