卧槽!骨瘦如柴陈皮皮又出新插件了,还免费开源!

news/2024/7/10 0:13:20 标签: python, js, java, 编程语言, vue
js_content">

前言

嗐,不知道你有没有过这样的烦恼。

当你想要确定一个资源被哪些节点引用的时候,使用资源管理器的查找引用却只能精确到预制体或场景。

对于预制体还好说,里面的节点一般不会很多,找起来还是比较快的。

但是场景里面的节点这么多,节点还可能是关闭着的,那找起来可太麻烦了。

那咋办嘛?

于是我又写了个编辑器扩展。

是的,这篇文章就给大家介绍一下我的新扩展:引用查找器


正文

???? 本文主要包含两部分:

  1. 扩展介绍

  2. 原理解析

让我们开始吧!

引用查找器

简介

这个扩展的用处很简单,就是让你可以一键快速查找资源的所有引用,对于预制体或场景的引用还可以精确到节点上的组件和属性。

注意:本插件无法查找脚本代码中的动态引用(动态加载资源)。

开源

本扩展项目完全开源,仓库地址:https://gitee.com/ifaswind/ccc-references-finder

如果你觉得这个项目还不错,请不要忘记点个 ⭐Star

截图

截图 1
截图 2
查找面板
设置面板

下载

本扩展已上架扩展商店,点击 Cocos Creator 编辑器顶部菜单栏中的 [扩展] -> [扩展商店] 即可打开扩展商店。

在商店页面上方的搜索框中输入“引用查找器”并搜索就可以找到本扩展,点进去直接安装即可(建议安装到全局)。

或者

到码云仓库里自行下载安装~

使用说明

安装扩展后,点击 Cocos Creator 编辑器顶部菜单栏中的 [扩展] -> [引用查找器] -> [设置] 即可打开扩展的设置面板。

有以下 3 个选项:

  • 自动展开查找结果:切换不同的结果展示方式(自动展开或手动展开)

  • 结果精确到节点:结果精确到预制体或场景中的节点上的组件和属性(有的话)

  • 查找快捷键:在资源管理器中选择资源后按下快捷键即可查找资源的引用(默认为 F6)

原理解析

虽然项目已经开源,源码随便看随便改,不过还是在这里给大家稍微解释下扩展的工作原理吧~

查找场景和预制体中的引用

???? 预制体的数据结构和场景大致相同,这里只拿场景举例。

没有专门研究过场景文件数据结构的小伙伴,可能会觉得里面的数据应该是树形结构,就像层级管理器中展示出来的那样,节点与子节点一层一层地嵌套着。

实则不然,场景文件的数据其实是扁平结构的。不理解?那听我娓娓道来~

???? 扁平化

树形结构就好像一个多维数组,不同纬度间不断嵌套,像这样:

[0, 1, [2, 3, 4], 5, [6, [7, 8]], 9]

当我们调用数组的 flat() 函数将这个多维数组扁平化,数组就会变成:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

这就是降维打击!

???? 举个栗子

以新建项目的 helloworld 场景为例,其节点层级是这样的:

场景的层级管理器

helloworld.fire 的文件内容是这样的(为了更直观地展示数据结构我去除了文件中大部分不相关内容):

场景的数据结构

我们可以发现,在场景中所有节点和组件都是一个个独立的对象,且这些对象都处于同一个一维数组中。

  • 每个节点对象中都储存了该节点的父节点 id,子节点 id 和身上的组件 id 等信息。

  • 每个组件对象中都储存了该组件所属的节点 id 和组件的一些数据。

而这些 id(__id__)其实就是对象在数组中的下标

比如 background 节点的父节点 id 为 2,那么就是数组中的第 3 个对象,即 _nameCanvas 的节点对象;又如 Main Camera 节点上有一个组件的 id 为 4,那就是数组中的第 4 个对象:cc.Camera 对象。

生成节点树

想要判断场景是否引用了某个资源,只需要检查场景的数据中是否包含资源的 uuid 即可。

但是,如果想要获取具体引用的节点和组件,而扁平化的数据结构是非常不利于查找的。

所以在正式开始查找之前,先将场景的数据转为树形结构(节点树),且只留下节点和组件对象中一些有用的属性,如 _name__type____uuid__,还要将节点的完整路径保存起来。

???? 具体生成节点树的代码在这里(代码太长,就不贴了):

传送门:https://gitee.com/ifaswind/ccc-references-finder/blob/v1.1.0/main.js#L362

???? 转换后的场景数据结构就像这样:

转换后的节点树

至此,我们就拥有了场景的节点树,查找引用的任务已经变得无比简单,只需在节点树中查询目标 uuid 即可获取场景中的所有引用(包括节点路径、组件和属性信息)。

???? 而判断对象中是否包含 uuid 则是用简单的递归实现的:

containsValue(object, value) {
    let result = false;
    const search = (_object) => {
        if (Object.prototype.toString.call(_object) === '[object Object]') {
            for (const key in _object) {
                if (_object[key] === value) {
                    result = true;
                    return;
                }
                search(_object[key]);
            }
        } else if (Array.isArray(_object)) {
            for (let i = 0; i < _object.length; i++) {
                search(_object[i]);
            }
        }
    }
    search(object);
    return result;
}
加点魔法

为了加快查询速度,每个场景和预制体的节点树都只会生成一次,所以只有第一次查找会稍微慢一点点(其实也很快)。

另外扩展内部监听了项目中场景和预制体的修改,以便及时更新对应的节点树。

// 监听资源更新事件
'asset-db:asset-changed'(event, info) {
    // 只处理场景和预制体
    if (info.type === 'scene' || info.type === 'prefab') {
        // 获取资源的路径
        const path = Editor.assetdb.uuidToFspath(info.uuid);
        // 更新节点树
        this.updateNodeTree(path);
    }
}

查找其它资源中的引用

对于动画片段、材质和字体等资源,只需简单判断资源数据中是否包含目标 uuid 即可。

???? 就像这样:

// 动画片段资源(扩展名为 .anim)
if (extname === '.anim') {
    const data = JSON.parse(Fs.readFileSync(filePath));
    // 截取有效数据
    const curveData = data['curveData'];
    // 数据中是否包含目标 uuid
    const contains = ObjectUtil.containsValue(curveData, uuid);
    if (contains) {
        // 获取文件路径
        const fileUrl = Editor.assetdb.fspathToUrl(filePath);
        // 保存结果
        results.push({ type: typeMap[extname], fileUrl: fileUrl });
    }
}

菜鸟小栈

????我是陈皮皮,一个还在不断学习(如何脱单)的游戏开发者
一个热爱分享的 Cocos Star Writer。

????这是我的个人公众号,专注但不仅限于游戏开发和前端技术分享。

????每一篇原创都非常用心,你的关注就是我原创的动力!


http://www.niftyadmin.cn/n/805991.html

相关文章

【阻塞队列源码系列】 ArrayBlockingQueue 源码解析

ArrayBlockingQueue 一个由数组实现的有界阻塞队列&#xff0c;其大小在构造时由构造函数来决定&#xff0c;确认之后就不能再改变了支持对等待的生产者线程和使用者线程进行排序的可选公平策略&#xff0c;但是在默认情况下不保证线程公平的访问&#xff0c;在构造时可以选择…

JAVA 生成文件的MD5码

下面的代码是自己写的&#xff1a;Java代码 /** * Copyright 2012 * * All right reserved * * Created on 2012-8-31下午5:43:58 */ package com.test.md5; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; impo…

华为AppGallery Connect ,我遇到Cocos大佬啦!

昨天11月26日 AppGallery Connect &#xff08;简称AGC&#xff09;研习社「游戏专场」沙龙在成都召开&#xff01;起初收到消息还没有什么感觉&#xff0c;后来了解到将会有 Cocos 的超级大佬 Panda、麒麟子将登台演讲&#xff0c;机会难得呀&#xff01;如此近距离领略大佬风…

表格隔行换色及删除后仍隔行换色效果(好别扭的标题。。。)

表格隔行换色&#xff0c;有多种写法&#xff0c;可以通过jquery来写&#xff0c;也可以用css3实现。 1.jquery方法 odd,奇数&#xff1b;even&#xff0c;偶数 方法很简单 $("tr:odd").css({background:"#c66",color:"#fff"}); $(tr:even).css(…

RFC2617- HTTP Authentication自译本-(3) (转)

RFC2617- HTTP Authentication自译本-(3) (转)[more] XML:namespace prefix o ns "urn:schemas-microsoft-com:Office:office" /> auth-param 该指示用于未来扩展。任何无法识别的指示都必须被忽略。 3.2.2 授权请求标题&#xff08;The Authorization Request…

【阻塞队列源码系列】 LinkedBlockingDeque 源码解析

LinkedBlockingDeque 实现接口 BlockingDeque&#xff0c;而 BlockingDeque 又继承接口 BlockingQueue &#xff0c;提供了一系列的以First和Last结尾的方法&#xff0c;如addFirst、addLast、peekFirst、peekLast&#xff0c;为双向操作Queue提供了可能。底层实现就是链表&am…

Cocos KOL派对,大佬分享,看完涨见识了...

11月28日&#xff0c;一大波 Cocos 社区活跃开发者受 Cocos 官方邀请齐聚厦门&#xff0c;参加 Cocos 十周年『Cocos 首届大中华区 KOL 派对』。文章末尾&#xff0c;可解密封面对应的大佬名字感谢「Nowpaper」老师精心制作的VLOG&#xff01;晓衡也有幸参与整个Cocos KOL 派对…

使用SourceTree 关联远程仓库

创建好公密钥&#xff0c;把公钥添加到远程仓库。就可以拉去提交了。 分3中情况&#xff0c;sourceTree也有对应三个按钮。 1、项目在远程库直接克隆下来&#xff0c; 2、本地以前关联过git仓库的项目&#xff08;比如&#xff0c;项目路径还在&#xff0c;sourcetree重装了&am…