<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      cocos craetor2.4.5 逆向之屬性面板顯示原理

      最近在封裝一個組件,有一個字符串枚舉類型, 發現不支持, 想探探原因,看看能否hook解決這個問題!  因為數字枚舉類型編輯器是支持的。

      cocos creator支持的所有屬性類型分別是:

      [
        "string",
        "number",
        "boolean",
        "array",
        "object",
        "enum",
        "color",
        "vec2",
        "vec3",
        "String",
        "Float",
        "Boolean",
        "Object",
        "Integer",
        "Enum",
        "asset",
        "cc.Asset",
        "cc.Node",
        "cc.Vec2",
        "cc.Vec3",
        "cc.Size",
        "cc.Color",
        "cc.Rect",
        "cc.Vec4"
      ]

      所有類型的顯示模版如下:

      string
      template(t) {
          let i;
          return (i = t.multiline
            ? '\n        <ui-text-area class="flex-1" resize-v></ui-text-area>\n      '
            : '\n        <ui-input class="flex-1"></ui-input>\n      ');
        }
      ===================
      number
      template(t) {
            let i;
            return (i = t.slide
              ? '\n        <ui-slider class="flex-1"></ui-slider>\n      '
              : '\n        <ui-num-input class="flex-1"></ui-num-input>\n      ');
          }
      ===================
      boolean
      
          <ui-checkbox class="flex-1"></ui-checkbox>
        
      ===================
      array
      
          <ui-num-input class="flex-1"></ui-num-input>
          <div slot="child"></div>
        
      ===================
      object
      
          <div class="child" slot="child"></div>
        
      ===================
      enum
      
          <ui-select class="flex-1"></ui-select>
        
      ===================
      color
      
          <ui-color class="flex-1"></ui-color>
        
      ===================
      vec2
      
          <ui-prop name="X" id="x-comp" slidable class="fixed-label red flex-1">
            <ui-num-input class="flex-1"></ui-num-input>
          </ui-prop>
          <ui-prop name="Y" id="y-comp" slidable class="fixed-label green flex-1">
            <ui-num-input class="flex-1"></ui-num-input>
          </ui-prop>
        
      ===================
      vec3
      
          <ui-prop name="X" id="x-comp" slidable class="fixed-label red flex-1">
            <ui-num-input class="flex-1"></ui-num-input>
          </ui-prop>
          <ui-prop name="Y" id="y-comp" slidable class="fixed-label green flex-1">
            <ui-num-input class="flex-1"></ui-num-input>
          </ui-prop>
          <ui-prop name="Z" id="z-comp" slidable class="fixed-label blue flex-1">
            <ui-num-input class="flex-1"></ui-num-input>
          </ui-prop>
        
      ===================
      String
      template(t) {
          let i;
          return (i = t.multiline
            ? '\n        <ui-text-area class="flex-1" resize-v></ui-text-area>\n      '
            : '\n        <ui-input class="flex-1"></ui-input>\n      ');
        }
      ===================
      Float
      template(t) {
            let i;
            return (i = t.slide
              ? '\n        <ui-slider class="flex-1"></ui-slider>\n      '
              : '\n        <ui-num-input class="flex-1"></ui-num-input>\n      ');
          }
      ===================
      Boolean
      
          <ui-checkbox class="flex-1"></ui-checkbox>
        
      ===================
      Object
      
          <div class="child" slot="child"></div>
        
      ===================
      Integer
      template(t) {
            let i;
            return (i = t.slide
              ? '\n        <ui-slider class="flex-1"></ui-slider>\n        '
              : '\n        <ui-num-input class="flex-1" type="int"></ui-num-input>\n        ');
          }
      ===================
      Enum
      
            <ui-select class="flex-1"></ui-select>
          
      ===================
      asset
      (t) =>
            `\n        <ui-asset class="flex-1" type="${t.assetType}"></ui-asset>\n      `
      ===================
      cc.Asset
      (t) =>
            `\n        <ui-asset class="flex-1" type="${t.assetType}"></ui-asset>\n      `
      ===================
      cc.Node
      (t) =>
            `\n        <ui-node class="flex-1"\n          type="${t.typeid}"\n          typename="${t.typename}"\n        ></ui-node>\n      `
      ===================
      cc.Vec2
      
              <ui-prop name="X" id="x-comp" subset slidable class="fixed-label flex-1">
                <ui-num-input class="flex-1"></ui-num-input>
              </ui-prop>
            
              <ui-prop name="Y" id="y-comp" subset slidable class="fixed-label flex-1">
                <ui-num-input class="flex-1"></ui-num-input>
              </ui-prop>
            
      ===================
      cc.Vec3
      
              <ui-prop name="X" id="x-comp" subset slidable class="fixed-label flex-1">
                <ui-num-input class="flex-1"></ui-num-input>
              </ui-prop>
            
              <ui-prop name="Y" id="y-comp" subset slidable class="fixed-label flex-1">
                <ui-num-input class="flex-1"></ui-num-input>
              </ui-prop>
            
              <ui-prop name="Z" id="z-comp" subset slidable class="fixed-label flex-1">
                <ui-num-input class="flex-1"></ui-num-input>
              </ui-prop>
            
      ===================
      cc.Size
      
            <ui-prop name="W" id="w-comp" subset slidable class="fixed-label flex-1">
              <ui-num-input class="flex-1"></ui-num-input>
            </ui-prop>
            <ui-prop name="H" id="h-comp" subset slidable class="fixed-label flex-1">
              <ui-num-input class="flex-1"></ui-num-input>
            </ui-prop>
          
      ===================
      cc.Color
      
            <ui-color class="flex-1"></ui-color>
          
      ===================
      cc.Rect
      
            <div class="vertical flex-1">
              <div class="layout horizontal">
                <ui-prop subset slidable name="X" class="fixed-label flex-1" style="min-width: 0; margin-right: 10px;">
                  <ui-num-input id="x-input" class="flex-1"></ui-num-input>
                </ui-prop>
                <ui-prop subset slidable name="Y" class="fixed-label flex-1" style="min-width: 0;">
                  <ui-num-input id="y-input" class="flex-1"></ui-num-input>
                </ui-prop>
              </div>
              <div class="layout horizontal">
                <ui-prop subset slidable name="W" class="fixed-label flex-1" style="min-width: 0; margin-right: 10px;">
                  <ui-num-input id="w-input" class="flex-1"></ui-num-input>
                </ui-prop>
                <ui-prop subset slidable name="H" class="fixed-label flex-1" style="min-width: 0;">
                  <ui-num-input id="h-input" class="flex-1"></ui-num-input>
                </ui-prop>
              </div>
            </div>
          
      ===================
      cc.Vec4
      
            <div class="vertical flex-1">
              <div class="layout horizontal">
                <ui-prop name="X" class="fixed-label flex-1" style="min-width: 0; margin-right: 10px;">
                  <ui-num-input id="x-input" class="flex-1"></ui-num-input>
                </ui-prop>
                <ui-prop name="Y" class="fixed-label flex-1" style="min-width: 0;">
                  <ui-num-input id="y-input" class="flex-1"></ui-num-input>
                </ui-prop>
              </div>
              <div class="layout horizontal">
                <ui-prop name="Z" class="fixed-label flex-1" style="min-width: 0; margin-right: 10px;">
                  <ui-num-input id="z-input" class="flex-1"></ui-num-input>
                </ui-prop>
                <ui-prop name="W" class="fixed-label flex-1" style="min-width: 0;">
                  <ui-num-input id="w-input" class="flex-1"></ui-num-input>
                </ui-prop>
              </div>
            </div>
          

      有一個關鍵算法, 它是獲取所有屬性源頭:

      function getClassAttrs(ctor) {
        return ctor.hasOwnProperty('__attrs__') && ctor.__attrs__ || createAttrs(ctor);
      }
      
      function attr(ctor, propName, newAttrs) {
        var attrs = getClassAttrs(ctor);
      
        if (!CC_DEV || typeof newAttrs === 'undefined') {
          // get
          var prefix = propName + DELIMETER;
          var ret = {};
      
          for (var key in attrs) {
            if (key.startsWith(prefix)) {
              ret[key.slice(prefix.length)] = attrs[key];
            }
          }
      
          return ret;
        } else if (CC_DEV && typeof newAttrs === 'object') {
          // set
          cc.warn("`cc.Class.attr(obj, prop, { key: value });` is deprecated, use `cc.Class.Attr.setClassAttr(obj, prop, 'key', value);` instead please.");
      
          for (var _key in newAttrs) {
            attrs[propName + DELIMETER + _key] = newAttrs[_key];
          }
        }
      } // returns a readonly meta object

      creator編輯器自己有一個運行時, 所有的對象存放cc.engine.attachedObjsForEditor:

       

      如果是數字枚舉, 結果如下:

      如果是字符串枚舉, 結果如下:

      這個就是問題所在了,類型是Enum,默認值string類型,enumList 為空。 

      enumList 元素對象類型是{name:xxx, value: v}

      enumList 的數據來源算法是:

      cc.Enum.getList = function (enumDef) {
        if (enumDef.__enums__) return enumDef.__enums__;
        var enums = enumDef.__enums__ = [];
      
        for (var name in enumDef) {
          var value = enumDef[name];
      
          if (Number.isInteger(value)) {
            enums.push({
              name: name,
              value: value
            });
          }
        }
      
        enums.sort(function (a, b) {
          return a.value - b.value;
        });
        return enums;
      };

      從這個代碼就可以知道enumList為啥空了, 因為只處理了interger. 

      寫一個插件看看, 強行讓它也可以處理string類型看看

       現在插件運行正確,確實能賦值給enumList了, 但是還是顯示類型錯誤

      那么就需要從顯示邏輯著手了,為啥顯示Type Error:

       這是錯誤組件cc-type-error-prop:

       看看什么時候會用cc-type-error-prop組件:

      通過斷點找到了異常的地方, 大概的意思值類型String和Enum不是一個類型

       這個數據本身沒問題, 因為字符串枚舉, 底層本身就是string。 

      enum CmpIconGroup {
        ABC = 'abc',
        DEF = 'def',
      }

      從初步分析結果來看,數字枚舉應該也會顯示Type Error才對, 因為number類似不等于Enum,  再次分析正確的情況:

       非常好,這就是為啥不顯示的Type Error的原因了, value是2,但是o卻是Enum.  并沒有識別出是Number

      為啥value=2能識別出是Enum, 而value='def'確是string?

      繼續往前跟蹤,  發現之前忽略一點,只關注了prop屬性值, 沒有關心value值:

       繼續往前,看看為啥數字2為啥可以識別出Enum:

      這個數字2,源頭就是Enum, 再看看字符串枚舉, 這個源頭是啥:

       數據源頭也是Enum, 但是經過Editor.getNodeDump(node) 之后變成了String:

      繼續挖掘, 找到了根源:

      如果原始數據是Enum, 值是Number類型時,強制用Enum, 而忽略了string類型。  這也是為啥Type Error的真正原因。

      知道原因就好處理了, 直接hook Editor.getNodeDump方法, 解決編輯器不支持字符串枚舉的方法是寫一個插件,代碼如下:

      if(CC_EDITOR){
              cc.Enum.getList = function (enumDef) {
                  if (enumDef.__enums__) return enumDef.__enums__;
                  var enums = enumDef.__enums__ = [];
                
                  let isStr = false;
                  for (var name in enumDef) {
                    var value = enumDef[name];
                
                    isStr = typeof value === 'string';
                    enums.push({name: name,value: value});
                  }
                
                  !isStr && enums.sort(function (a, b) {
                    return a.value - b.value;
                  });
                  return enums;
              };
      
              const oldDump = Editor.getNodeDump;
              Editor.getNodeDump = function(node){
                  const ret = oldDump(node);
                  let {types, value} = ret;
                  if(value.__comps__){
                      value.__comps__.forEach((comp)=>{
                          const cmpType = types[comp.type];
                          const properties = cmpType.properties;
                          for(let propKey in properties){
                              const prop = properties[propKey];
                              if(prop.type === 'Enum'){// 真實數據是Enum類型
                                  comp.value[propKey].type = 'Enum';
                              }
                          }
                      });
                  }
                  return ret;
              }
      
              Editor.UI.getProperty('Enum').inputValue = function(){
                  const ty = this.get_real_type();
                  if(ty == 'string'){
                      return this.$input.value;
                  }
                  return Number(this.$input.value);
              }
      
              Editor.UI.getProperty('Enum').get_real_type = function(){
                  if(this.__ty){
                      return this.__ty;
                  }
                  let ty = 'string';
                  try{
                      ty = typeof this._attrs.enumList[0].value;
                  }catch(e){
                      // pass
                  }
                  this.__ty = ty;
                  return ty;
              }
      
              const oldEidtorWarn = Editor.warn;
              Editor.warn = function(s){// hook 枚舉類型保存錯誤的警告!因為已經支持string類型了
                  if(typeof s == 'string' && s.startsWith('Expecting number type of value for')){
                      return;
                  }
                  return oldEidtorWarn.apply(Editor, arguments);
              }
          }

       

      附上最終的效果圖:

      碰到字符串枚舉類型時編輯器再也不顯示Type Error了, 哈哈,完美收工!!!

      經過實際測試已經支持 string float, int 的枚舉類型了。

      比如:

      export const CmpIconSize = {
      SCALE_0_3: 0.3,
      SCALE_0_5: 0.5,
      SCALE_0_8: 0.8,
      SCALE_1 : 1,
      SCALE_1_2: 1.2,
      SCALE_1_5: 1.5,
      SCALE_2 : 2,
      };
       
      后續屬性設置可以直接 
      @property({
      type: cc.Enum(CmpIconType),
      tooltip: '圖標類型',
      })
      iconSize = CmpIconType.SCALE_1_2;
       
       

       

      posted @ 2025-06-07 15:53  浪浪辛  閱讀(111)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 99精品热在线在线观看视| 毕节市| 国产三级精品三级在线观看| 国产精品自拍视频第一页| 日区中文字幕一区二区| 久久精品丝袜高跟鞋| 九九热在线精品视频首页| 黄又色又污又爽又高潮| 国产免费高清69式视频在线观看| 国产成人av大片大片| 日韩av影院在线观看| 国产精品亚洲二区在线播放| 亚洲少妇人妻无码视频| 91精品91久久久久久| 亚洲精品久久国产高清小说 | 亚洲国产精品线观看不卡| 成人福利一区二区视频在线| 中文字幕 制服 亚洲 另类| 最近中文字幕国产精选| 一区二区三区激情都市| 激情综合网激情激情五月天| 成人福利一区二区视频在线| 99精品久久毛片a片| 亚洲精品国产综合久久一线| 麻豆一区二区三区精品视频| 91精品亚洲一区二区三区| 99噜噜噜在线播放| 亚洲国产美国产综合一区| 成人动漫综合网| 国产成人AV男人的天堂| 综合色一色综合久久网| 精品国产午夜福利在线观看| 国产农村激情免费专区| 久久SE精品一区精品二区| 亚洲av永久无码精品漫画| 国产成人av一区二区三区不卡| 痉挛高潮喷水av无码免费| 丰满人妻无码∧v区视频| 国产一区二区不卡在线| 国产性三级高清在线观看 | 国产片一区二区三区视频|