[
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto"
  },
  {
    "path": ".gitignore",
    "content": "/[Ll]ibrary/\n/[Tt]emp/\n/[Oo]bj/\n/[Bb]uild/\n/[Bb]uilds/\n/Assets/AssetStoreTools*\n/Assets/Editor/AssetAuditor/ProxyAssets\n\n.DS_Store\n\n# Autogenerated VS/MD/Consulo solution and project files\nExportedObj/\n.consulo/\n*.csproj\n*.unityproj\n*.sln\n*.suo\n*.tmp\n*.user\n*.userprefs\n*.pidb\n*.booproj\n*.svd\n\n# Unity3D generated meta files\n*.pidb.meta\n\n# Unity3D Generated File On Crash Reports\nsysinfo.txt\n\n# Builds\n*.apk\n*.unitypackage\n\nProjectSettings/\n\nAssets/Plugins\\.meta\n\nAssets/Plugins/Editor\\.meta\n\nAssets/Plugins/Editor/JetBrains\\.meta\n\nAssets/Plugins/Editor/JetBrains/RiderAssetPostprocessor\\.cs\n\nAssets/Plugins/Editor/JetBrains/RiderAssetPostprocessor\\.cs\\.meta\n\nAssets/Plugins/Editor/JetBrains/RiderPlugin\\.cs\n\nAssets/Plugins/Editor/JetBrains/RiderPlugin\\.cs\\.meta\n\nAssets/Plugins/Editor/JetBrains/Unity3DRider\\.cs\n\nAssets/Plugins/Editor/JetBrains/Unity3DRider\\.cs\\.meta\n\n\\.idea/\\.idea\\.AssetAuditor/riderModule\\.iml\n\n\\.idea/\\.idea\\.AssetAuditor/\\.idea/workspace\\.xml\n\n\\.idea/\\.idea\\.AssetAuditor/\\.idea/modules\\.xml\n\n\\.idea/\\.idea\\.AssetAuditor/\\.idea/contentModel\\.xml\n\nAssets/Editor/AssetAuditor/ProxyAssets\\.meta\n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Audio/DefaultAudio.wav.meta",
    "content": "fileFormatVersion: 2\nguid: d13848c7015ad4078abfd3076f74c106\ntimeCreated: 1502381708\nlicenseType: Pro\nAudioImporter:\n  serializedVersion: 6\n  defaultSettings:\n    loadType: 0\n    sampleRateSetting: 0\n    sampleRateOverride: 44100\n    compressionFormat: 1\n    quality: 1\n    conversionMode: 0\n  platformSettingOverrides: {}\n  forceToMono: 0\n  normalize: 1\n  preloadAudioData: 1\n  loadInBackground: 0\n  ambisonic: 0\n  3D: 1\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Audio.meta",
    "content": "fileFormatVersion: 2\nguid: fffabc88153284eda8f44478e35d6337\nfolderAsset: yes\ntimeCreated: 1502381697\nlicenseType: Pro\nDefaultImporter:\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Models/DefaultAvatar.fbx.meta",
    "content": "fileFormatVersion: 2\nguid: 6ca747ad81483413fa1665afa5a9c79a\ntimeCreated: 1502276181\nlicenseType: Pro\nModelImporter:\n  serializedVersion: 21\n  fileIDToRecycleName:\n    100000: Chest\n    100002: //RootNode\n    100004: Geo_grp\n    100006: Head\n    100008: Hips\n    100010: Jaw\n    100012: JawEND\n    100014: Le_Eye_Mesh\n    100016: LeftArm\n    100018: LeftCheek\n    100020: LeftEye\n    100022: LeftEyelidLower\n    100024: LeftEyelidUpper\n    100026: LeftFoot\n    100028: LeftForeArm\n    100030: LeftHand\n    100032: LeftHandIndex1\n    100034: LeftHandIndex2\n    100036: LeftHandIndex3\n    100038: LeftHandMiddle1\n    100040: LeftHandMiddle2\n    100042: LeftHandMiddle3\n    100044: LeftHandPinky1\n    100046: LeftHandPinky2\n    100048: LeftHandPinky3\n    100050: LeftHandRing1\n    100052: LeftHandRing2\n    100054: LeftHandRing3\n    100056: LeftHandThumb1\n    100058: LeftHandThumb2\n    100060: LeftHandThumb3\n    100062: LeftInnerBrow\n    100064: LeftIOuterBrow\n    100066: LeftLeg\n    100068: LeftLipCorner\n    100070: LeftLipLower\n    100072: LeftLipUpper\n    100074: LeftNostril\n    100076: LeftShoulder\n    100078: LeftToes\n    100080: LeftUpLeg\n    100082: Lw_Teeth_Mesh\n    100084: Neck\n    100086: Reference\n    100088: Ri_Eye_Mesh\n    100090: RightArm\n    100092: RightCheek\n    100094: RightEye\n    100096: RightEyelidLower\n    100098: RightEyelidUpper\n    100100: RightFoot\n    100102: RightForeArm\n    100104: RightHand\n    100106: RightHandIndex1\n    100108: RightHandIndex2\n    100110: RightHandIndex3\n    100112: RightHandMiddle1\n    100114: RightHandMiddle2\n    100116: RightHandMiddle3\n    100118: RightHandPinky1\n    100120: RightHandPinky2\n    100122: RightHandPinky3\n    100124: RightHandRing1\n    100126: RightHandRing2\n    100128: RightHandRing3\n    100130: RightHandThumb1\n    100132: RightHandThumb2\n    100134: RightHandThumb3\n    100136: RightInnerBrow\n    100138: RightIOuterBrow\n    100140: RightLeg\n    100142: RightLipCorner\n    100144: RightLipLower\n    100146: RightLipUpper\n    100148: RightNostril\n    100150: RightShoulder\n    100152: RightToes\n    100154: RightUpLeg\n    100156: Spine\n    100158: TongueBack\n    100160: TongueTip\n    100162: Tounge_Mesh\n    100164: Unity_Body_Mesh\n    100166: Up_Teeth_Mesh\n    400000: Chest\n    400002: //RootNode\n    400004: Geo_grp\n    400006: Head\n    400008: Hips\n    400010: Jaw\n    400012: JawEND\n    400014: Le_Eye_Mesh\n    400016: LeftArm\n    400018: LeftCheek\n    400020: LeftEye\n    400022: LeftEyelidLower\n    400024: LeftEyelidUpper\n    400026: LeftFoot\n    400028: LeftForeArm\n    400030: LeftHand\n    400032: LeftHandIndex1\n    400034: LeftHandIndex2\n    400036: LeftHandIndex3\n    400038: LeftHandMiddle1\n    400040: LeftHandMiddle2\n    400042: LeftHandMiddle3\n    400044: LeftHandPinky1\n    400046: LeftHandPinky2\n    400048: LeftHandPinky3\n    400050: LeftHandRing1\n    400052: LeftHandRing2\n    400054: LeftHandRing3\n    400056: LeftHandThumb1\n    400058: LeftHandThumb2\n    400060: LeftHandThumb3\n    400062: LeftInnerBrow\n    400064: LeftIOuterBrow\n    400066: LeftLeg\n    400068: LeftLipCorner\n    400070: LeftLipLower\n    400072: LeftLipUpper\n    400074: LeftNostril\n    400076: LeftShoulder\n    400078: LeftToes\n    400080: LeftUpLeg\n    400082: Lw_Teeth_Mesh\n    400084: Neck\n    400086: Reference\n    400088: Ri_Eye_Mesh\n    400090: RightArm\n    400092: RightCheek\n    400094: RightEye\n    400096: RightEyelidLower\n    400098: RightEyelidUpper\n    400100: RightFoot\n    400102: RightForeArm\n    400104: RightHand\n    400106: RightHandIndex1\n    400108: RightHandIndex2\n    400110: RightHandIndex3\n    400112: RightHandMiddle1\n    400114: RightHandMiddle2\n    400116: RightHandMiddle3\n    400118: RightHandPinky1\n    400120: RightHandPinky2\n    400122: RightHandPinky3\n    400124: RightHandRing1\n    400126: RightHandRing2\n    400128: RightHandRing3\n    400130: RightHandThumb1\n    400132: RightHandThumb2\n    400134: RightHandThumb3\n    400136: RightInnerBrow\n    400138: RightIOuterBrow\n    400140: RightLeg\n    400142: RightLipCorner\n    400144: RightLipLower\n    400146: RightLipUpper\n    400148: RightNostril\n    400150: RightShoulder\n    400152: RightToes\n    400154: RightUpLeg\n    400156: Spine\n    400158: TongueBack\n    400160: TongueTip\n    400162: Tounge_Mesh\n    400164: Unity_Body_Mesh\n    400166: Up_Teeth_Mesh\n    2300000: Le_Eye_Mesh\n    2300002: Ri_Eye_Mesh\n    3300000: Le_Eye_Mesh\n    3300002: Ri_Eye_Mesh\n    4300000: Le_Eye_Mesh\n    4300002: Ri_Eye_Mesh\n    4300004: Unity_Body_Mesh\n    4300006: Up_Teeth_Mesh\n    4300008: Lw_Teeth_Mesh\n    4300010: Tounge_Mesh\n    9500000: //RootNode\n    13700000: Lw_Teeth_Mesh\n    13700002: Tounge_Mesh\n    13700004: Unity_Body_Mesh\n    13700006: Up_Teeth_Mesh\n  materials:\n    importMaterials: 0\n    materialName: 0\n    materialSearch: 1\n  animations:\n    legacyGenerateAnimations: 4\n    bakeSimulation: 0\n    resampleCurves: 1\n    optimizeGameObjects: 0\n    motionNodeName: \n    rigImportErrors: \n    rigImportWarnings: \n    animationImportErrors: \n    animationImportWarnings: \n    animationRetargetingWarnings: \n    animationDoRetargetingWarnings: 0\n    animationCompression: 3\n    animationRotationError: 0.5\n    animationPositionError: 0.5\n    animationScaleError: 0.5\n    animationWrapMode: 0\n    extraExposedTransformPaths: []\n    extraUserProperties: []\n    clipAnimations: []\n    isReadable: 1\n  meshes:\n    lODScreenPercentages: []\n    globalScale: 1\n    meshCompression: 0\n    addColliders: 0\n    importVisibility: 1\n    importBlendShapes: 1\n    importCameras: 1\n    importLights: 1\n    swapUVChannels: 0\n    generateSecondaryUV: 0\n    useFileUnits: 1\n    optimizeMeshForGPU: 1\n    keepQuads: 0\n    weldVertices: 1\n    secondaryUVAngleDistortion: 8\n    secondaryUVAreaDistortion: 15.000001\n    secondaryUVHardAngle: 88\n    secondaryUVPackMargin: 4\n    useFileScale: 1\n  tangentSpace:\n    normalSmoothAngle: 60\n    normalImportMode: 0\n    tangentImportMode: 3\n    normalCalculationMode: 4\n  importAnimation: 1\n  copyAvatar: 0\n  humanDescription:\n    serializedVersion: 2\n    human:\n    - boneName: Hips\n      humanName: Hips\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftUpLeg\n      humanName: LeftUpperLeg\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightUpLeg\n      humanName: RightUpperLeg\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftLeg\n      humanName: LeftLowerLeg\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightLeg\n      humanName: RightLowerLeg\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftFoot\n      humanName: LeftFoot\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightFoot\n      humanName: RightFoot\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: Spine\n      humanName: Spine\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: Chest\n      humanName: Chest\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: Neck\n      humanName: Neck\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: Head\n      humanName: Head\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftShoulder\n      humanName: LeftShoulder\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightShoulder\n      humanName: RightShoulder\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftArm\n      humanName: LeftUpperArm\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightArm\n      humanName: RightUpperArm\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftForeArm\n      humanName: LeftLowerArm\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightForeArm\n      humanName: RightLowerArm\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHand\n      humanName: LeftHand\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHand\n      humanName: RightHand\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftToes\n      humanName: LeftToes\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightToes\n      humanName: RightToes\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftEye\n      humanName: LeftEye\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightEye\n      humanName: RightEye\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: Jaw\n      humanName: Jaw\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandThumb1\n      humanName: Left Thumb Proximal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandThumb2\n      humanName: Left Thumb Intermediate\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandThumb3\n      humanName: Left Thumb Distal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandIndex1\n      humanName: Left Index Proximal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandIndex2\n      humanName: Left Index Intermediate\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandIndex3\n      humanName: Left Index Distal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandMiddle1\n      humanName: Left Middle Proximal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandMiddle2\n      humanName: Left Middle Intermediate\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandMiddle3\n      humanName: Left Middle Distal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandRing1\n      humanName: Left Ring Proximal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandRing2\n      humanName: Left Ring Intermediate\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandRing3\n      humanName: Left Ring Distal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandPinky1\n      humanName: Left Little Proximal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandPinky2\n      humanName: Left Little Intermediate\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: LeftHandPinky3\n      humanName: Left Little Distal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandThumb1\n      humanName: Right Thumb Proximal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandThumb2\n      humanName: Right Thumb Intermediate\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandThumb3\n      humanName: Right Thumb Distal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandIndex1\n      humanName: Right Index Proximal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandIndex2\n      humanName: Right Index Intermediate\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandIndex3\n      humanName: Right Index Distal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandMiddle1\n      humanName: Right Middle Proximal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandMiddle2\n      humanName: Right Middle Intermediate\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandMiddle3\n      humanName: Right Middle Distal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandRing1\n      humanName: Right Ring Proximal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandRing2\n      humanName: Right Ring Intermediate\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandRing3\n      humanName: Right Ring Distal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandPinky1\n      humanName: Right Little Proximal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandPinky2\n      humanName: Right Little Intermediate\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    - boneName: RightHandPinky3\n      humanName: Right Little Distal\n      limit:\n        min: {x: 0, y: 0, z: 0}\n        max: {x: 0, y: 0, z: 0}\n        value: {x: 0, y: 0, z: 0}\n        length: 0\n        modified: 0\n    skeleton:\n    - name: DefaultAvatar(Clone)\n      parentName: \n      position: {x: 0, y: 0, z: 0}\n      rotation: {x: 0, y: 0, z: 0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Geo_grp\n      parentName: DefaultAvatar(Clone)\n      position: {x: -0, y: 0, z: 0}\n      rotation: {x: 0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Lw_Teeth_Mesh\n      parentName: Geo_grp\n      position: {x: -0, y: 0, z: 0}\n      rotation: {x: 0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Tounge_Mesh\n      parentName: Geo_grp\n      position: {x: -0, y: 0, z: 0}\n      rotation: {x: 0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Unity_Body_Mesh\n      parentName: Geo_grp\n      position: {x: -0, y: 0, z: 0}\n      rotation: {x: 0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Up_Teeth_Mesh\n      parentName: Geo_grp\n      position: {x: -0, y: 0, z: 0}\n      rotation: {x: 0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Reference\n      parentName: DefaultAvatar(Clone)\n      position: {x: -0, y: 0, z: 0}\n      rotation: {x: 0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Hips\n      parentName: Reference\n      position: {x: -0, y: 0.963794, z: -0.023506777}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Spine\n      parentName: Hips\n      position: {x: -0, y: 0.092263184, z: 0.015771331}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Chest\n      parentName: Spine\n      position: {x: -0, y: 0.16254029, z: 0.021850722}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Neck\n      parentName: Chest\n      position: {x: -0, y: 0.2357239, z: -0.032413255}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Head\n      parentName: Neck\n      position: {x: -0, y: 0.1063558, z: 0.0113267815}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftEye\n      parentName: Head\n      position: {x: -0.020848233, y: 0.0825027, z: 0.055427432}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Le_Eye_Mesh\n      parentName: LeftEye\n      position: {x: -0.0016841149, y: 0.00040588377, z: 0.0053181886}\n      rotation: {x: 0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightEye\n      parentName: Head\n      position: {x: 0.020849999, y: 0.08250283, z: 0.0554274}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Ri_Eye_Mesh\n      parentName: RightEye\n      position: {x: 0.0016618776, y: 0.00038345336, z: 0.0053166724}\n      rotation: {x: 0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftLipUpper\n      parentName: Head\n      position: {x: -0.014501322, y: -0.005111811, z: 0.09461884}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftNostril\n      parentName: Head\n      position: {x: -0.0179, y: 0.026312828, z: 0.0908674}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftCheek\n      parentName: Head\n      position: {x: -0.054244027, y: 0.03370195, z: 0.0594304}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftEyelidUpper\n      parentName: Head\n      position: {x: -0.034406897, y: 0.10060814, z: 0.08020531}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftEyelidLower\n      parentName: Head\n      position: {x: -0.035618957, y: 0.06507366, z: 0.07623474}\n      rotation: {x: -0.0348995, y: -0, z: -0, w: 0.99939084}\n      scale: {x: 1, y: 1.0000005, z: 1.0000005}\n    - name: LeftInnerBrow\n      parentName: Head\n      position: {x: -0.012062691, y: 0.118765265, z: 0.093466826}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftIOuterBrow\n      parentName: Head\n      position: {x: -0.05503987, y: 0.11482529, z: 0.061777398}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightInnerBrow\n      parentName: Head\n      position: {x: 0.012062687, y: 0.118765265, z: 0.093466826}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightIOuterBrow\n      parentName: Head\n      position: {x: 0.055040002, y: 0.11482283, z: 0.061777398}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightEyelidUpper\n      parentName: Head\n      position: {x: 0.03441, y: 0.10061283, z: 0.08020739}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightEyelidLower\n      parentName: Head\n      position: {x: 0.03562, y: 0.06507283, z: 0.0762374}\n      rotation: {x: -0.0348995, y: -0, z: -0, w: 0.99939084}\n      scale: {x: 1, y: 1.0000005, z: 1.0000005}\n    - name: RightCheek\n      parentName: Head\n      position: {x: 0.054239996, y: 0.033702828, z: 0.0594274}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightNostril\n      parentName: Head\n      position: {x: 0.0179, y: 0.026308905, z: 0.09087062}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightLipUpper\n      parentName: Head\n      position: {x: 0.014501322, y: -0.0051071714, z: 0.094617404}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: Jaw\n      parentName: Head\n      position: {x: -0, y: 0.0111267585, z: 0.010327543}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftLipLower\n      parentName: Jaw\n      position: {x: -0.014250817, y: -0.02168876, z: 0.08224063}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: JawEND\n      parentName: Jaw\n      position: {x: -0, y: -0.04828876, z: 0.07185171}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightLipLower\n      parentName: Jaw\n      position: {x: 0.014250817, y: -0.02168876, z: 0.082238786}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightLipCorner\n      parentName: Jaw\n      position: {x: 0.03284, y: -0.01657876, z: 0.066118784}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftLipCorner\n      parentName: Jaw\n      position: {x: -0.032843262, y: -0.01657876, z: 0.066121764}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: TongueBack\n      parentName: Jaw\n      position: {x: -0, y: -0.022869369, z: 0.010095409}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: TongueTip\n      parentName: TongueBack\n      position: {x: -0, y: -0.00040944412, z: 0.0282273}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightShoulder\n      parentName: Chest\n      position: {x: 0.03832851, y: 0.19217674, z: -0.017063085}\n      rotation: {x: 0.228672, y: 0.9715822, z: -0.014005679, w: -0.059507377}\n      scale: {x: 1.0000013, y: 1, z: 1.000001}\n    - name: RightArm\n      parentName: RightShoulder\n      position: {x: -0.08357552, y: 0.0360957, z: -0.000000051557407}\n      rotation: {x: -0.21105212, y: -0.97439414, z: 0.017311702, w: -0.07558775}\n      scale: {x: 1.0000001, y: 1.0000002, z: 1}\n    - name: RightForeArm\n      parentName: RightArm\n      position: {x: 0.25342825, y: 0.006011353, z: -0.016704524}\n      rotation: {x: -0.0006165215, y: 0.022078624, z: -0.01607026, w: 0.99962693}\n      scale: {x: 0.99999994, y: 0.99999976, z: 1.0000001}\n    - name: RightHand\n      parentName: RightForeArm\n      position: {x: 0.2453737, y: 0.021641772, z: 0.005550465}\n      rotation: {x: 8.1490714e-10, y: -0, z: 0.021413714, w: 0.99977076}\n      scale: {x: 1.0000001, y: 1.0000001, z: 1}\n    - name: RightHandThumb1\n      parentName: RightHand\n      position: {x: 0.014684916, y: -0.011104942, z: 0.025858095}\n      rotation: {x: -0.012817442, y: -0.0032555843, z: 0.031460524, w: 0.99941754}\n      scale: {x: 1.0000004, y: 1, z: 1}\n    - name: RightHandThumb2\n      parentName: RightHandThumb1\n      position: {x: 0.016374, y: -0.00529, z: 0.02349136}\n      rotation: {x: -0.026063675, y: -0.09668989, z: -0.003606537, w: 0.9949667}\n      scale: {x: 1.0000002, y: 1.0000001, z: 1}\n    - name: RightHandThumb3\n      parentName: RightHandThumb2\n      position: {x: 0.02546, y: -0.00764, z: 0.020833}\n      rotation: {x: 0.000000012019879, y: 9.3132235e-10, z: -0.00000000372546, w: 1}\n      scale: {x: 1.0000002, y: 0.9999999, z: 1}\n    - name: RightHandIndex1\n      parentName: RightHand\n      position: {x: 0.0747695, y: -0.0012430536, z: 0.034344498}\n      rotation: {x: -0.0021189174, y: 0.080257446, z: 0.017538162, w: 0.9966176}\n      scale: {x: 1, y: 0.99999994, z: 1.0000001}\n    - name: RightHandIndex2\n      parentName: RightHandIndex1\n      position: {x: 0.0370584, y: 0.00072612107, z: 0.014538894}\n      rotation: {x: -0.0033265573, y: 0.015931673, z: 0.060633723, w: 0.99802744}\n      scale: {x: 1.0000002, y: 1.0000002, z: 1}\n    - name: RightHandIndex3\n      parentName: RightHandIndex2\n      position: {x: 0.025225038, y: -0.0049664653, z: 0.011012146}\n      rotation: {x: -0, y: -0, z: -9.458742e-10, w: 1}\n      scale: {x: 1.0000001, y: 1.0000004, z: 1.0000001}\n    - name: RightHandMiddle1\n      parentName: RightHand\n      position: {x: 0.075647645, y: 0.0047914027, z: 0.011853182}\n      rotation: {x: -0.0007688713, y: 0.03332108, z: 0.020907532, w: 0.99922574}\n      scale: {x: 0.9999999, y: 0.99999994, z: 1}\n    - name: RightHandMiddle2\n      parentName: RightHandMiddle1\n      position: {x: 0.043809064, y: 0.00019418815, z: 0.006454936}\n      rotation: {x: -0.004130707, y: -0.033512067, z: 0.07612222, w: 0.99652666}\n      scale: {x: 1.0000001, y: 1, z: 0.99999994}\n    - name: RightHandMiddle3\n      parentName: RightHandMiddle2\n      position: {x: 0.03307247, y: -0.007547537, z: 0.0016898462}\n      rotation: {x: -0, y: -0, z: -0.0000000032414385, w: 1}\n      scale: {x: 1, y: 1.0000001, z: 1}\n    - name: RightHandRing1\n      parentName: RightHand\n      position: {x: 0.070598476, y: 0.0024570965, z: -0.009821458}\n      rotation: {x: 0.0007108786, y: -0.054342177, z: 0.03494465, w: 0.99791056}\n      scale: {x: 1.0000001, y: 0.99999994, z: 1}\n    - name: RightHandRing2\n      parentName: RightHandRing1\n      position: {x: 0.042887185, y: -0.0013753821, z: -0.004945858}\n      rotation: {x: 0.0004845856, y: -0.021289792, z: 0.06986199, w: 0.99732935}\n      scale: {x: 1.0000002, y: 1.0000001, z: 0.99999964}\n    - name: RightHandRing3\n      parentName: RightHandRing2\n      position: {x: 0.029500604, y: -0.0076929354, z: -0.004622256}\n      rotation: {x: -0, y: -0, z: 0.0000000013351378, w: 1}\n      scale: {x: 1, y: 0.9999999, z: 0.9999998}\n    - name: RightHandPinky1\n      parentName: RightHand\n      position: {x: 0.06680334, y: -0.0019941088, z: -0.030756146}\n      rotation: {x: 0.0031760908, y: -0.19200507, z: 0.0451148, w: 0.9803513}\n      scale: {x: 1.0000001, y: 1, z: 0.99999994}\n    - name: RightHandPinky2\n      parentName: RightHandPinky1\n      position: {x: 0.028530842, y: -0.001397143, z: -0.011623796}\n      rotation: {x: -0.00017062707, y: -0.009661323, z: -0.0053624124, w: 0.999939}\n      scale: {x: 1, y: 1.0000002, z: 1.0000001}\n    - name: RightHandPinky3\n      parentName: RightHandPinky2\n      position: {x: 0.02142686, y: -0.00055350893, z: -0.008516608}\n      rotation: {x: -0, y: 9.3132235e-10, z: -4.2518867e-11, w: 1}\n      scale: {x: 1, y: 1.0000002, z: 1.0000001}\n    - name: LeftShoulder\n      parentName: Chest\n      position: {x: -0.038243506, y: 0.19217809, z: -0.017063085}\n      rotation: {x: -0.01400671, y: -0.05950682, z: 0.22868991, w: 0.97157794}\n      scale: {x: 1, y: 0.99999994, z: 1}\n    - name: LeftArm\n      parentName: LeftShoulder\n      position: {x: -0.08357477, y: 0.036097575, z: 2.8865798e-17}\n      rotation: {x: 0.009464391, y: 0.043691695, z: -0.22304244, w: 0.97378314}\n      scale: {x: 1, y: 1.0000001, z: 0.9999998}\n    - name: LeftForeArm\n      parentName: LeftArm\n      position: {x: -0.2540493, y: 0, z: 0}\n      rotation: {x: -0.0006165216, y: 0.022078618, z: -0.016070211, w: 0.99962693}\n      scale: {x: 1, y: 1, z: 1.0000002}\n    - name: LeftHand\n      parentName: LeftForeArm\n      position: {x: -0.24638927, y: 0, z: 0}\n      rotation: {x: 0.0000000034924592, y: 0.0000000074505797, z: -0.02141356, w: 0.9997707}\n      scale: {x: 0.9999998, y: 1.0000002, z: 0.99999994}\n    - name: LeftHandThumb1\n      parentName: LeftHand\n      position: {x: -0.014231241, y: -0.012377825, z: 0.025531668}\n      rotation: {x: -0.012314987, y: -0.008526002, z: 0.012583703, w: 0.9998086}\n      scale: {x: 1.0000002, y: 0.99999994, z: 0.99999994}\n    - name: LeftHandThumb2\n      parentName: LeftHandThumb1\n      position: {x: -0.016374, y: -0.00529, z: 0.023491409}\n      rotation: {x: -0.026063059, y: 0.09668942, z: 0.0036069017, w: 0.9949668}\n      scale: {x: 1.0000004, y: 1.0000001, z: 0.9999999}\n    - name: LeftHandThumb3\n      parentName: LeftHandThumb2\n      position: {x: -0.02546, y: -0.00764, z: 0.020833}\n      rotation: {x: 0.000000042738975, y: 0.0000000037252903, z: 0.0000000018620199,\n        w: 1}\n      scale: {x: 1.0000001, y: 0.9999999, z: 0.9999999}\n    - name: LeftHandIndex1\n      parentName: LeftHand\n      position: {x: -0.0751258, y: -0.0078414045, z: 0.032652643}\n      rotation: {x: -0.0021189197, y: 0.08025745, z: 0.01753819, w: 0.9966176}\n      scale: {x: 1.0000002, y: 0.9999999, z: 1.0000004}\n    - name: LeftHandIndex2\n      parentName: LeftHandIndex1\n      position: {x: -0.03979728, y: 0.000049808405, z: 0.0011857504}\n      rotation: {x: 0.000501889, y: 0.015471162, z: 0.040411938, w: 0.99906325}\n      scale: {x: 1, y: 0.99999994, z: 0.99999976}\n    - name: LeftHandIndex3\n      parentName: LeftHandIndex2\n      position: {x: -0.027968477, y: -0.000000006281224, z: -0.00000005171866}\n      rotation: {x: -5.8207654e-11, y: -0, z: 0.000000002835804, w: 1}\n      scale: {x: 0.99999994, y: 1.0000001, z: 1.0000001}\n    - name: LeftHandMiddle1\n      parentName: LeftHand\n      position: {x: -0.076023825, y: -0.0018851344, z: 0.010141229}\n      rotation: {x: -0.00076887483, y: 0.033321086, z: 0.020907529, w: 0.9992257}\n      scale: {x: 1.0000001, y: 0.9999999, z: 1.0000001}\n    - name: LeftHandMiddle2\n      parentName: LeftHandMiddle1\n      position: {x: -0.044280436, y: 0.000004798874, z: -0.00042540013}\n      rotation: {x: -0.0013621139, y: -0.01915252, z: 0.037885293, w: 0.99909765}\n      scale: {x: 1.0000002, y: 1, z: 0.99999994}\n    - name: LeftHandMiddle3\n      parentName: LeftHandMiddle2\n      position: {x: -0.033964828, y: -0.000000012197929, z: 0.0000000037564827}\n      rotation: {x: -0, y: -0, z: 4.838512e-10, w: 1}\n      scale: {x: 1, y: 1.0000001, z: 1.0000001}\n    - name: LeftHandRing1\n      parentName: LeftHand\n      position: {x: -0.07030211, y: -0.0037453093, z: -0.011411792}\n      rotation: {x: -0.00032414307, y: 0.011598279, z: 0.024737397, w: 0.99962664}\n      scale: {x: 0.9999999, y: 0.9999998, z: 1.0000001}\n    - name: LeftHandRing2\n      parentName: LeftHandRing1\n      position: {x: -0.043135457, y: -0.000020882308, z: -0.0022351784}\n      rotation: {x: -0.0012033589, y: -0.023113519, z: 0.040983878, w: 0.9988918}\n      scale: {x: 0.99999994, y: 1.0000001, z: 0.99999994}\n    - name: LeftHandRing3\n      parentName: LeftHandRing2\n      position: {x: -0.030835565, y: 7.710497e-11, z: -0.00000001649327}\n      rotation: {x: -0, y: -0, z: 0.0000000013897075, w: 1}\n      scale: {x: 0.99999994, y: 1, z: 1}\n    - name: LeftHandPinky1\n      parentName: LeftHand\n      position: {x: -0.06565995, y: -0.007825106, z: -0.032251246}\n      rotation: {x: -0.00091239274, y: 0.012161445, z: 0.021224977, w: 0.9997003}\n      scale: {x: 1.0000001, y: 0.9999999, z: 1.0000002}\n    - name: LeftHandPinky2\n      parentName: LeftHandPinky1\n      position: {x: -0.030805448, y: -0.000030874573, z: -0.0014480775}\n      rotation: {x: -0.00017062433, y: -0.009661346, z: -0.00536237, w: 0.999939}\n      scale: {x: 0.99999994, y: 1.0000001, z: 1.0000001}\n    - name: LeftHandPinky3\n      parentName: LeftHandPinky2\n      position: {x: -0.023064027, y: -0.0000064025808, z: 0.000000018332095}\n      rotation: {x: -0, y: 9.3132235e-10, z: -1.9895191e-11, w: 1}\n      scale: {x: 0.9999999, y: 1, z: 0.9999999}\n    - name: RightUpLeg\n      parentName: Hips\n      position: {x: 0.075449534, y: -0.04566399, z: 0}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightLeg\n      parentName: RightUpLeg\n      position: {x: 0.020550467, y: -0.40913, z: 0.0071713654}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightFoot\n      parentName: RightLeg\n      position: {x: 0.0051529994, y: -0.4231559, z: -0.012032089}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: RightToes\n      parentName: RightFoot\n      position: {x: 0.007487, y: -0.0731673, z: 0.1454275}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftUpLeg\n      parentName: Hips\n      position: {x: -0.0754495, y: -0.04566402, z: 0}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftLeg\n      parentName: LeftUpLeg\n      position: {x: -0.020550499, y: -0.40912998, z: 0.0071713654}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftFoot\n      parentName: LeftLeg\n      position: {x: -0.0051529994, y: -0.4231559, z: -0.012032089}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    - name: LeftToes\n      parentName: LeftFoot\n      position: {x: -0.007487, y: -0.0731673, z: 0.14542712}\n      rotation: {x: -0, y: -0, z: -0, w: 1}\n      scale: {x: 1, y: 1, z: 1}\n    armTwist: 0.5\n    foreArmTwist: 0.5\n    upperLegTwist: 0.5\n    legTwist: 0.5\n    armStretch: 0.05\n    legStretch: 0.05\n    feetSpacing: 0\n    rootMotionBoneName: \n    rootMotionBoneRotation: {x: 0, y: 0, z: 0, w: 1}\n    hasTranslationDoF: 0\n    hasExtraRoot: 1\n    skeletonHasParents: 1\n  lastHumanDescriptionAvatarSource: {instanceID: 0}\n  animationType: 3\n  humanoidOversampling: 1\n  additionalBone: 0\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Models.meta",
    "content": "fileFormatVersion: 2\nguid: d1003e9744d57413fad5f07821ef2136\nfolderAsset: yes\ntimeCreated: 1502276220\nlicenseType: Pro\nDefaultImporter:\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditTreeElement.cs",
    "content": "using System;\n\nnamespace UnityAssetAuditor\n{\n\t[Serializable]\n\tpublic class AssetAuditTreeElement : TreeElement\n    { \n\t\tpublic bool isAsset;\n\t    public string projectPath;\n\t    public AssetAuditor.AssetType assetType;\n\n\t    internal enum AssetType\n\t    {\n\t        Asset,\n            Directory\n\t    }\n\n\t    public bool conforms;\n\n\t    public AssetAuditTreeElement (string name,string _projectPath, int depth, int id, bool _isAsset, bool _conforms , AssetAuditor.AssetType _assetType) : base (name, depth, id)\n\t\t{\n\t\t\tisAsset = _isAsset;\n\t\t    projectPath = _projectPath;\n\t        conforms = _conforms;\n\t\t\tassetType = _assetType;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditTreeElement.cs.meta",
    "content": "fileFormatVersion: 2\nguid: f1bafad60d37c484dab3ce5b74c04a6a\ntimeCreated: 1472024032\nlicenseType: Pro\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditTreeView.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.Assertions;\n\n\nnamespace UnityAssetAuditor\n{\n    public class AssetAuditTreeView : TreeViewWithTreeModel<AssetAuditTreeElement>\n    {\n        private readonly Action<AssetAuditTreeElement> _ruleFixEvent;\n        const float kRowHeights = 20f;\n        const float kIconWidth = 18f;\n        public bool showControls { get; set; }\n\n        // All columns\n        enum MyColumns\n        {\n            Name,\n            Conforms\n        }\n\n\n        public static void TreeToList(TreeViewItem root, IList<TreeViewItem> result)\n        {\n            if (root == null)\n                throw new NullReferenceException(\"root\");\n            if (result == null)\n                throw new NullReferenceException(\"result\");\n\n            result.Clear();\n\n            if (root.children == null)\n                return;\n\n            Stack<TreeViewItem> stack = new Stack<TreeViewItem>();\n            for (int i = root.children.Count - 1; i >= 0; i--)\n                stack.Push(root.children[i]);\n\n            while (stack.Count > 0)\n            {\n                TreeViewItem current = stack.Pop();\n                result.Add(current);\n\n                if (current.hasChildren && current.children[0] != null)\n                {\n                    for (int i = current.children.Count - 1; i >= 0; i--)\n                    {\n                        stack.Push(current.children[i]);\n                    }\n                }\n            }\n        }\n\n        public AssetAuditTreeView(TreeViewState state, MultiColumnHeader multicolumnHeader, TreeModel<AssetAuditTreeElement> model , Action<AssetAuditTreeElement> ruleFixEvent) : base(state, multicolumnHeader, model)\n        {\n            _ruleFixEvent = ruleFixEvent;\n\n            // Custom setup\n            rowHeight = kRowHeights;\n            columnIndexForTreeFoldouts = 0;\n            showAlternatingRowBackgrounds = true;\n            showBorder = true;\n            customFoldoutYOffset = (kRowHeights - EditorGUIUtility.singleLineHeight) * 0.5f; // center foldout in the row since we also center content. See RowGUI\n            extraSpaceBeforeIconAndLabel = kIconWidth;\n            Reload();\n        }\n\n\n        // Note we We only build the visible rows, only the backend has the full tree information. \n        // The treeview only creates info for the row list.\n        protected override IList<TreeViewItem> BuildRows(TreeViewItem root)\n        {\n            var rows = base.BuildRows(root);\n            return rows;\n        }\n\n\n        protected override void RowGUI(RowGUIArgs args)\n        {\n            var item = (TreeViewItem<AssetAuditTreeElement>)args.item;\n\n            for (int i = 0; i < args.GetNumVisibleColumns(); ++i)\n            {\n                CellGUI(args.GetCellRect(i), item, (MyColumns)args.GetColumn(i), ref args);\n            }\n        }\n\n        void CellGUI(Rect cellRect, TreeViewItem<AssetAuditTreeElement> item, MyColumns column, ref RowGUIArgs args)\n        {\n            // Center cell rect vertically (makes it easier to place controls, icons etc in the cells)\n            CenterRectUsingSingleLineHeight(ref cellRect);\n\n            switch (column)\n            {\n                case MyColumns.Name:\n                    {\n                        // Do toggle\n                        Rect iconRect = cellRect;\n                        iconRect.x += GetContentIndent(item);\n                        iconRect.width = kIconWidth;\n\n                        Texture2D iconTex = null;\n           /*             if (item.data.isAsset)\n                        {\n                            if (!string.IsNullOrEmpty(item.data.projectPath))\n                            {\n                                iconTex = AssetPreview.GetMiniThumbnail(\n                                    AssetDatabase.LoadAssetAtPath<Texture2D>(\n                                        item.data.projectPath.Substring(Application.dataPath.Length - 6)));\n                            }\n                        }*/\n                        switch (item.data.assetType)\n                        {\n                            case AssetAuditor.AssetType.Texture:\n                                iconTex = AssetPreview.GetMiniThumbnail(\n                                    AssetDatabase.LoadAssetAtPath<Texture2D>(\n                                        item.data.projectPath));\n                                break;\n                            case AssetAuditor.AssetType.Model:\n                                iconTex = EditorGUIUtility.FindTexture(\"PrefabModel Icon\");\n                                break;\n                            case AssetAuditor.AssetType.Audio:\n                                iconTex = EditorGUIUtility.FindTexture(\"AudioClip Icon\");\n                                break;\n                            case AssetAuditor.AssetType.Folder:\n                                iconTex = EditorGUIUtility.FindTexture(\"Folder Icon\");\n                                break;\n                            default:\n                                throw new ArgumentOutOfRangeException();\n                        }\n                        if (iconRect.xMax < cellRect.xMax)\n                        {\n                            GUI.DrawTexture(iconRect, iconTex);\n                        }\n                        // Default icon and label\n                        args.rowRect = cellRect;\n                        base.RowGUI(args);\n                    }\n                    break;\n\n                case MyColumns.Conforms:\n                    var conforms = item.data.conforms;\n                    if (item.data.isAsset)\n                    {\n                        if (conforms)\n                        {\n                            GUI.Label(cellRect , \" Settings OK \");\n                        }\n                        else\n                        {\n                            if (GUI.Button(cellRect, \"Fix\"))\n                            {\n                                _ruleFixEvent.Invoke(item.data);\n                            }\n                        }\n                    }\n                    break;\n            }\n        }\n\n\n        // Misc\n        //--------\n\n        protected override bool CanMultiSelect(TreeViewItem item)\n        {\n            return true;\n        }\n\n        public static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState(float treeViewWidth)\n        {\n            var columns = new[]\n            {\n                new MultiColumnHeaderState.Column\n                {\n                    headerContent = new GUIContent(\"Name\"),\n                    headerTextAlignment = TextAlignment.Left,\n                    width = 0, // adjusted below\n\t\t\t\t\tminWidth = 60,\n                    autoResize = true,\n                    allowToggleVisibility = false,\n                    canSort = false\n\n                },\n                new MultiColumnHeaderState.Column\n                {\n                    headerContent = new GUIContent(\"Conforms\"),\n                    headerTextAlignment = TextAlignment.Left,\n                    width = 150, // adjusted below\n\t\t\t\t\tminWidth = 150,\n                    autoResize = true,\n                    allowToggleVisibility = false,\n                    canSort = false\n\n                },\n            };\n\n            Assert.AreEqual(columns.Length, Enum.GetValues(typeof(MyColumns)).Length, \"Number of columns should match number of enum values: You probably forgot to update one of them.\");\n\n            // Set name column width (flexible)\n            int nameColumn = (int)MyColumns.Name;\n            columns[nameColumn].width = treeViewWidth - GUI.skin.verticalScrollbar.fixedWidth;\n            for (int i = 0; i < columns.Length; ++i)\n                if (i != nameColumn)\n                    columns[nameColumn].width -= columns[i].width;\n\n            if (columns[nameColumn].width < 60f)\n                columns[nameColumn].width = 60f;\n\n            var state = new MultiColumnHeaderState(columns);\n            return state;\n        }\n    }\n}\n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditTreeView.cs.meta",
    "content": "fileFormatVersion: 2\nguid: e00d20ba7c1f4d446a34ea24d8b82c4e\ntimeCreated: 1464348051\nlicenseType: Pro\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditor.cs",
    "content": "﻿using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text.RegularExpressions;\nusing UnityEditor;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.Collections;\n\nnamespace UnityAssetAuditor\n{\n\n    public delegate void OnQueueComplete();\n    \n    public class AssetAuditor\n    {\n        public static IEnumerable<float> currentEnumerable;\n        public static IEnumerator<float> currentEnumerator;\n        public static Queue<IEnumerable<float>> enumerableQueue;\n        public static event OnQueueComplete queueComplete;      \n        private static List<string> foundAssets;\n\n        public enum WildCardMatchType\n        {\n            NameContains,\n            Regex\n        }\n\n        public enum AssetType\n        {\n            Texture,\n            Model,\n            Audio,\n            Folder\n        }\n\n\n        [Serializable]\n        public struct AssetRule\n        {\n            public string RuleName;\n            public WildCardMatchType WildCardMatchType;\n            public string WildCard;\n            public string AssetGuid;\n            public AssetType assetType;\n            public bool SelectiveMode;\n            public List<string> SelectiveProperties;\n        }\n        \n        \n        static AssetAuditor()\n        {\n            EditorApplication.update += TickEnumerator;\n            enumerableQueue = new Queue<IEnumerable<float>>();\n        }\n\n        \n        private static void TickEnumerator()\n        {\n            if (currentEnumerable == null)\n            {\n                return;\n            }\n\n            if (!currentEnumerator.MoveNext())\n            {\n                currentEnumerable = null;\n                currentEnumerator = null;\n\n                if (enumerableQueue.Count == 0)\n                {\n                    if (queueComplete != null) queueComplete.Invoke();\n                }\n                else\n                {\n                    currentEnumerable = enumerableQueue.Dequeue();\n                    currentEnumerator = currentEnumerable.GetEnumerator();\n                }\n            }\n        }\n\n        \n        public static float GetProgress()\n        {\n            return currentEnumerator != null ? currentEnumerator.Current : 0f;\n        }\n\n        \n        public static void AddEnumerator(IEnumerable<float> enumerator)\n        {\n            enumerableQueue.Enqueue(enumerator);\n\n            if (currentEnumerable == null)\n            {\n                currentEnumerable = enumerableQueue.Dequeue();\n                currentEnumerator = currentEnumerable.GetEnumerator();\n            }\n        }\n\n        \n        public static void ClearQueue()\n        {\n            enumerableQueue.Clear();\n\n            currentEnumerable = null;\n            currentEnumerator = null;\n        }\n\n\n        public static Type TypeFromAssetType(AssetType assetType)\n        {\n            switch (assetType)\n            {\n                case AssetType.Texture:\n                    return typeof(Texture);\n                case AssetType.Model:\n                    return typeof(GameObject);\n                case AssetType.Audio:\n                    return typeof(AudioClip);\n                case AssetType.Folder:\n                    return null;\n                default:\n                    throw new ArgumentOutOfRangeException(\"assetType\", assetType, null);\n            }\n        }\n\n        \n        public static string[] GetAffectedAssets()\n        {\n            return foundAssets.ToArray();\n        }\n\n        \n        public static void UpdateAffectedAssets(AssetRule assetRule)\n        {\n            foundAssets = new List<string>();\n\n            switch (assetRule.WildCardMatchType)\n            {\n                case WildCardMatchType.NameContains:\n                    ClearQueue();\n                    AddEnumerator(DoNameContainsSearch(foundAssets, assetRule));\n                    break;\n                case WildCardMatchType.Regex:\n                    ClearQueue();\n                    AddEnumerator(DoRegexNameSearch(foundAssets, assetRule));\n                    break;\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n        }\n\n\n        private static IEnumerable<float> DoRegexNameSearch(List<string> foundAssets, AssetRule assetRule)\n        {\n            string type = \"\";\n            switch (assetRule.assetType)\n            {\n                case AssetType.Texture:\n                    type = \"Texture\";\n                    break;\n                case AssetType.Model:\n                    type = \"GameObject\";\n                    break;\n                case AssetType.Audio:\n                    type = \"AudioClip\";\n                    break;\n                case AssetType.Folder:\n                    break;\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n            \n            foreach (var asset in AssetDatabase.FindAssets(\"t:\" + type))\n            {\n                string guidToAssetPath = AssetDatabase.GUIDToAssetPath(asset);\n\n                if (guidToAssetPath.Contains(AssetAuditorPreferences.ProxyAssetsDirectory)) continue;\n\n                if (Regex.IsMatch(guidToAssetPath, assetRule.WildCard))\n                {\n                    foundAssets.Add(guidToAssetPath);\n                }\n            }\n\n            AssetAuditor.foundAssets = foundAssets;\n            yield return 1f;\n        }\n\n\n        public static IEnumerable<float> DoNameContainsSearch(List<string> foundAssets, AssetRule assetRule)\n        {\n            string type = \"\";\n            switch (assetRule.assetType)\n            {\n                case AssetType.Texture:\n                    type = \"Texture\";\n                    break;\n                case AssetType.Model:\n                    type = \"GameObject\";\n                    break;\n                case AssetType.Audio:\n                    type = \"AudioClip\";\n                    break;\n                case AssetType.Folder:\n                    break;\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n            foreach (string findAsset in AssetDatabase.FindAssets(\"t:\" + type + \" \" + assetRule.WildCard))\n            {\n                string guidToAssetPath = AssetDatabase.GUIDToAssetPath(findAsset);\n                if(guidToAssetPath.Contains(AssetAuditorPreferences.ProxyAssetsDirectory))continue;\n                foundAssets.Add(guidToAssetPath);\n            }\n\n            AssetAuditor.foundAssets = foundAssets;\n            yield return 1f;\n        }\n\n\n        public static IEnumerable<float> GatherAssetRules(List<AssetRule> _assetRules , List<string> _assetRuleNames )\n        {\n            int progress = 0;\n            string[] foundAssets = AssetDatabase.FindAssets(\"\", new[] {AssetAuditorPreferences.ProxyAssetsDirectory});\n            // get all assets in the proxyassets folder\n            foreach (string asset in foundAssets)\n            {\n                string guidToAssetPath = AssetDatabase.GUIDToAssetPath(asset);\n                AssetImporter assetImporter = AssetImporter.GetAtPath(guidToAssetPath);\n                AssetRule ar = new AssetRule();\n                ar = JsonUtility.FromJson<AssetRule>(assetImporter.userData);\n                _assetRules.Add(ar);\n\n                progress++;\n                yield return progress / (float)foundAssets.Length;\n            }\n            \n            _assetRuleNames.Clear();\n            foreach (AssetRule assetRule in _assetRules)\n            {\n                _assetRuleNames.Add(assetRule.RuleName);\n            }\n\n            yield return 1f;\n        }\n\n\n        public static IEnumerable<float> GatherData(AssetRule assetRule , List<AssetAuditTreeElement> elements, int selectedSelective)\n        {\n            int id = -1;\n            \n            // get the affected assets \n           string[] affectedAssets = GetAffectedAssets();\n            \n            if(affectedAssets == null) Debug.Log(\" null affected assets\");\n\n            // build the directory tree from the affected assets\n            elements.Add(new AssetAuditTreeElement(\"Root\", \"\", -1, 0, false, false, AssetType.Folder ));\n\n            // early out if there are no affected assets\n            if (affectedAssets.Length == 0)\n            {\n                Debug.Log(\"no affected assets \");\n                if (queueComplete != null) queueComplete.Invoke();\n                yield break;\n            }\n\n            AssetAuditTreeElement assetsFolder = new AssetAuditTreeElement(\"Assets\", \"Assets\", 0, id++, false, false,\n                AssetType.Folder );\n            // add the project root \"Assets\" folder\n            elements.Add(assetsFolder);\n            \n            if (assetsFolder.children == null) assetsFolder.children = new List<TreeElement>();\n            float progress = 0f;\n            foreach (var affectedAsset in affectedAssets)\n            {\n                // split the path \n                string path = affectedAsset.Substring(7);\n                var strings = path.Split(new[]{'/'}, StringSplitOptions.None);\n                string projectPath = \"Assets\";\n                // the first entries have lower depth\n                for(int i = 0 ; i < strings.Length ; i++)\n                {\n                    projectPath += \"/\" + strings[i];\n                    \n                    // the last element is the asset itself\n                    if (i == strings.Length-1)\n                    {\n                       var result = CheckAffectedAsset(affectedAsset, assetRule, selectedSelective);\n                       var element =  new AssetAuditTreeElement(strings[i], projectPath, i + 1, id + 1, true, result,\n                            assetRule.assetType); \n                        \n                        elements.Add(element);\n                        id++;\n                    }\n                    else if (!elements.Exists(element => element.name == strings[i] && element.projectPath == projectPath))\n                    {\n                        var assetAuditTreeElement = new AssetAuditTreeElement(strings[i], projectPath, i+1 , id+1, false, false, AssetType.Folder);\n                        elements.Add(assetAuditTreeElement);\n                        id++;\n                    }\n                }\n                progress += 1f;\n                yield return progress / affectedAssets.Length;\n            }\n        }\n \n\n        private static bool CheckAffectedAsset(string affectedAsset, AssetRule assetRule, int selectedSelective)\n        {\n            SerializedObject assetImporterSO = null;\n            SerializedObject ruleImporterSO = null;\n\n            if (TypeFromAssetType(assetRule.assetType) == typeof(Texture))\n            {\n                TextureImporter assetimporter =\n                    AssetImporter.GetAtPath(affectedAsset) as\n                        TextureImporter;\n\n                // this may happen (e.g. render texture)\n                if (assetimporter == null)\n                    return false;\n\n                TextureImporter ruleimporter =\n                    AssetImporter.GetAtPath(AssetDatabase.GUIDToAssetPath(assetRule.AssetGuid)) as\n                        TextureImporter;\n\n                if (assetimporter.GetInstanceID() == ruleimporter.GetInstanceID())\n                    return false; // this shouldnt happen but is a nice failsafe\n\n                assetImporterSO = new SerializedObject(assetimporter);\n                ruleImporterSO = new SerializedObject(ruleimporter);\n            }\n\n            if (TypeFromAssetType(assetRule.assetType) == typeof(GameObject))\n            {\n                ModelImporter assetimporter =\n                    AssetImporter.GetAtPath(affectedAsset) as\n                        ModelImporter;\n                ModelImporter ruleimporter =\n                    AssetImporter.GetAtPath(AssetDatabase.GUIDToAssetPath(assetRule.AssetGuid)) as\n                        ModelImporter;\n\n                if (assetimporter.GetInstanceID() == ruleimporter.GetInstanceID())\n                    return false; // this shouldnt happen but is a nice failsafe\n\n                assetImporterSO = new SerializedObject(assetimporter);\n                ruleImporterSO = new SerializedObject(ruleimporter);\n            }\n\n            if (TypeFromAssetType(assetRule.assetType) == typeof(AudioClip))\n            {\n                AudioImporter assetimporter =\n                    AssetImporter.GetAtPath(affectedAsset) as\n                        AudioImporter;\n                AudioImporter ruleimporter =\n                    AssetImporter.GetAtPath(AssetDatabase.GUIDToAssetPath(assetRule.AssetGuid)) as\n                        AudioImporter;\n\n                if (assetimporter.GetInstanceID() == ruleimporter.GetInstanceID())\n                    return false; // this shouldnt happen but is a nice failsafe\n\n                assetImporterSO = new SerializedObject(assetimporter);\n                ruleImporterSO = new SerializedObject(ruleimporter);\n            }\n\n            if (assetImporterSO == null || ruleImporterSO == null) return false; // TODO log message here\n\n            if (!assetRule.SelectiveMode || assetRule.SelectiveProperties.Count <= 0)\n            {\n                return CompareSerializedObject(assetImporterSO, ruleImporterSO);\n            }\n            string property = assetRule.SelectiveProperties[selectedSelective];\n\n            string realname = GetPropertyNameFromDisplayName(assetImporterSO, property);\n\n            SerializedProperty foundAssetSP = assetImporterSO.FindProperty(realname);\n\n            SerializedProperty assetRuleSP = ruleImporterSO.FindProperty(realname);\n\n            return CompareSerializedProperty(foundAssetSP, assetRuleSP);\n        }\n\n        \n        public static bool CompareSerializedProperty(SerializedProperty foundAssetSp, SerializedProperty assetRuleSp)\n        {\n\n            if (foundAssetSp.propertyPath == \"m_FileIDToRecycleName\" || foundAssetSp.propertyPath == \"m_UserData\") return true; // the file ids will always be different so we should skip over this. The user data is where the asset rule info is stored so we dont want to check that\n            \n            switch (foundAssetSp.propertyType)\n            {\n                case SerializedPropertyType.Generic: // this eventually goes down through the data until we get a useable value to compare \n\n                    SerializedProperty foundAssetsSPCopy = foundAssetSp.Copy();\n                    SerializedProperty assetRuleSPCopy = assetRuleSp.Copy();\n\n                    // we must get the next sibling SerializedProperties to know when to stop the comparison\n                    SerializedProperty nextSiblingAssetSP = foundAssetSp.Copy ();\n                    SerializedProperty nextSiblingRuleSP = assetRuleSp.Copy ();\n                    nextSiblingAssetSP.NextVisible (false);\n                    nextSiblingRuleSP.NextVisible (false);\n\n                    bool asset, found;\n                    \n                    do\n                    {\n                        if (assetRuleSPCopy.propertyType != foundAssetsSPCopy.propertyType)\n                        {\n                            return false; // mistmatch in types different serialisation\n                        }\n                        if (assetRuleSPCopy.propertyType != SerializedPropertyType.Generic)\n                        {\n                            if (!CompareSerializedProperty(foundAssetsSPCopy, assetRuleSPCopy))\n                            {\n                                return false;\n                            }\n                        }\n                        asset = foundAssetsSPCopy.NextVisible(true);\n                        found = assetRuleSPCopy.NextVisible(true);\n                    } while (found && asset &&\n                        !SerializedProperty.EqualContents (foundAssetsSPCopy, nextSiblingAssetSP) &&\n                        !SerializedProperty.EqualContents (assetRuleSPCopy, nextSiblingRuleSP));\n\n                    return true;\n                case SerializedPropertyType.Integer:\n                    return foundAssetSp.intValue == assetRuleSp.intValue;\n                case SerializedPropertyType.Boolean:\n                    return foundAssetSp.boolValue == assetRuleSp.boolValue;\n                case SerializedPropertyType.Float:\n                    return foundAssetSp.floatValue == assetRuleSp.floatValue;\n                case SerializedPropertyType.String:\n                    return foundAssetSp.stringValue == assetRuleSp.stringValue;\n                case SerializedPropertyType.Color:\n                    return foundAssetSp.colorValue == assetRuleSp.colorValue;\n                case SerializedPropertyType.ObjectReference:\n                    return true;// this is weird on models imports and needs a solution as the exposed transforms reference the model itself\n                case SerializedPropertyType.LayerMask:\n                    break;\n                case SerializedPropertyType.Enum:\n                    return foundAssetSp.enumValueIndex == assetRuleSp.enumValueIndex;\n                case SerializedPropertyType.Vector2:\n                    return foundAssetSp.vector2Value == assetRuleSp.vector2Value;\n                case SerializedPropertyType.Vector3:\n                    return foundAssetSp.vector3Value == assetRuleSp.vector3Value;\n                case SerializedPropertyType.Vector4:\n                    return foundAssetSp.vector4Value == assetRuleSp.vector4Value;\n                case SerializedPropertyType.Rect:\n                    return foundAssetSp.rectValue == assetRuleSp.rectValue;\n                case SerializedPropertyType.ArraySize:\n                    if (foundAssetSp.isArray && assetRuleSp.isArray)\n                    {\n                        Debug.Log(foundAssetSp.arraySize + assetRuleSp.arraySize);\n                        return foundAssetSp.arraySize == assetRuleSp.arraySize;\n                    }\n                    else\n                    {\n                        return foundAssetSp.intValue == assetRuleSp.intValue;\n                    }\n                case SerializedPropertyType.Character:\n                    \n                    break;\n                case SerializedPropertyType.AnimationCurve:\n                    return foundAssetSp.animationCurveValue == assetRuleSp.animationCurveValue;\n                case SerializedPropertyType.Bounds:\n                    return foundAssetSp.boundsValue == assetRuleSp.boundsValue;\n                case SerializedPropertyType.Gradient:\n                    break;\n                case SerializedPropertyType.Quaternion:\n                    return foundAssetSp.quaternionValue == assetRuleSp.quaternionValue;\n                case SerializedPropertyType.ExposedReference:\n                    return foundAssetSp.exposedReferenceValue == assetRuleSp.exposedReferenceValue;\n#if UNITY_2017_1_OR_NEWER\n                case SerializedPropertyType.FixedBufferSize:\n                    break;\n#endif\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n            return false;\n        }\n\n\n        public static bool CompareSerializedObject(SerializedObject rule, SerializedObject asset)\n        {\n            SerializedProperty ruleIter = rule.GetIterator();\n            SerializedProperty assetIter = asset.GetIterator();\n            assetIter.NextVisible(true);\n            ruleIter.NextVisible(true);\n\n            do\n            {\n                if (!CompareSerializedProperty(ruleIter, assetIter))\n                {\n                    Debug.Log(\" failied property \" + ruleIter.propertyPath + \"  \" + assetIter.displayName);\n                    return false;\n                }         \n\n                ruleIter.NextVisible(false);\n            } while (assetIter.NextVisible(false));\n\n            return true;\n        }\n        \n        \n        public static IEnumerable<float> FixAll(AssetAuditTreeView treeView , AssetRule assetRule)\n        {\n            List<AssetAuditTreeElement> list = new List<AssetAuditTreeElement>();\n            TreeElementUtility.TreeToList(treeView.treeModel.root, list);\n\n            float progress = 0f;\n            \n            foreach (AssetAuditTreeElement assetAuditTreeElement in list)\n            {\n                if (assetAuditTreeElement.isAsset && !assetAuditTreeElement.conforms)\n                    FixRule(assetAuditTreeElement, assetRule);\n\n                progress += 1f;\n                yield return progress / list.Count;\n            }\n        }\n\n        \n        public static void FixRule(AssetAuditTreeElement data , AssetRule assetRule)\n        {\n\n            string ruleAssetPath = AssetDatabase.GUIDToAssetPath(assetRule.AssetGuid);\n            string affectedAssetPath = data.projectPath;\n\n            switch (data.assetType)\n            {\n                case AssetType.Texture:\n                \n                    TextureImporter ruleTexImporter = AssetImporter.GetAtPath(ruleAssetPath) as TextureImporter;\n                    TextureImporter affectedAssetTexImporter = AssetImporter.GetAtPath(affectedAssetPath) as TextureImporter;\n\n                    if (assetRule.SelectiveMode)\n                    {\n                        SerializedObject ruleImporterSO = new SerializedObject(ruleTexImporter);\n                        SerializedObject affectedAssetImporterSO = new SerializedObject(affectedAssetTexImporter);\n                        CopySelectiveProperties(affectedAssetImporterSO, ruleImporterSO, assetRule);\n                    }\n                    else\n                    {\n                        EditorUtility.CopySerialized(ruleTexImporter, affectedAssetTexImporter);\n                    }\n                    affectedAssetTexImporter.userData = \"\";\n                    affectedAssetTexImporter.SaveAndReimport();\n                \n                    break;\n\n                case AssetType.Model:\n                    \n                    ModelImporter ruleModelImporter = AssetImporter.GetAtPath(ruleAssetPath) as ModelImporter;\n                    ModelImporter affectedAssetModelImporter = AssetImporter.GetAtPath(affectedAssetPath) as ModelImporter;\n\n                    if (assetRule.SelectiveMode)\n                    {\n                        SerializedObject ruleImporterSO = new SerializedObject(ruleModelImporter);\n                        SerializedObject affectedAssetImporterSO = new SerializedObject(affectedAssetModelImporter);\n                        CopySelectiveProperties(affectedAssetImporterSO, ruleImporterSO, assetRule);\n                    }\n                    else\n                    {\n                        EditorUtility.CopySerialized(ruleModelImporter, affectedAssetModelImporter);\n                    }\n                    affectedAssetModelImporter.userData = \"\";\n                    affectedAssetModelImporter.SaveAndReimport();\n                    break;\n                    \n                case AssetType.Audio:\n                    \n                    AudioImporter ruleAudioImporter = AssetImporter.GetAtPath(ruleAssetPath) as AudioImporter;\n                    AudioImporter affectedAssetAudioImporter = AssetImporter.GetAtPath(affectedAssetPath) as AudioImporter;\n\n                    if (assetRule.SelectiveMode)\n                    {\n                        SerializedObject ruleImporterSO = new SerializedObject(ruleAudioImporter);\n                        SerializedObject affectedAssetImporterSO = new SerializedObject(affectedAssetAudioImporter);\n                        CopySelectiveProperties(affectedAssetImporterSO, ruleImporterSO, assetRule);\n                    }\n                    else\n                    {\n                        EditorUtility.CopySerialized(ruleAudioImporter, affectedAssetAudioImporter);\n                    }\n                    affectedAssetAudioImporter.userData = \"\";\n                    affectedAssetAudioImporter.SaveAndReimport();\n                    break;\n                case AssetType.Folder:\n                    break;\n                    \n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n\n            data.conforms = true;\n        }\n        \n        \n        private static void CopySelectiveProperties(SerializedObject affectedAssetImporterSO, SerializedObject ruleImporterSO, AssetRule assetRule)\n        {\n            foreach (string property in assetRule.SelectiveProperties)\n            {\n                string realname = GetPropertyNameFromDisplayName(affectedAssetImporterSO, property);\n\n                SerializedProperty assetRuleSP = ruleImporterSO.FindProperty(realname);\n\n                affectedAssetImporterSO.CopyFromSerializedProperty(assetRuleSP);\n\n                bool applyModifiedProperties = affectedAssetImporterSO.ApplyModifiedProperties();\n\n                if (!applyModifiedProperties) Debug.Log(\" copy failed \");\n            }\n        }\n\n        \n        public static bool HaveEqualProperties<T>(T rhs, T lhs)\n        {\n            if (rhs != null && lhs != null)\n            {\n                Type type = typeof(T);\n                foreach (PropertyInfo pi in type.GetProperties(\n                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))\n                {\n                    object rhsValue = type.GetProperty(pi.Name).GetValue(rhs, null);\n                    object lhsValue = type.GetProperty(pi.Name).GetValue(lhs, null);\n                    if (!rhsValue.Equals(lhsValue))\n                    {\n                        return false;\n                    }\n                }\n            }\n            return true;\n        }\n        \n        \n        public static string GetPropertyNameFromDisplayName(SerializedObject so, string displayName)\n        {\n            SerializedProperty iter = so.GetIterator();\n\n            iter.NextVisible(true);\n            \n            do\n            {\n                if (iter.displayName == displayName) return iter.name;\n            }\n            while (iter.NextVisible(false)) ;\n\n            return null;\n        }\n        \n        \n        public static string[] GetPropertyNames(SerializedObject so)\n        {\n            SerializedProperty soIter = so.GetIterator();\n\n            List<string> propNames = new List<string>();\n\n            soIter.NextVisible(true);\n            do\n            {\n                propNames.Add(soIter.displayName);\n            } while (soIter.NextVisible(false));\n\n            return propNames.ToArray();\n        }\n\n        \n        public static void CreateProxyAudio(AssetRule newRule , ref string currentAsset)\n        {\n            string audioProxy = AssetAuditorPreferences.ProxyAudioPath;\n            string ext = audioProxy.Substring( audioProxy.LastIndexOf( '.' ) );\n            string newAssetPath = AssetAuditorPreferences.ProxyAssetsDirectory + Path.DirectorySeparatorChar + newRule.RuleName + ext;\n            if( !AssetDatabase.CopyAsset( audioProxy, newAssetPath ) )\n            {\n                Debug.LogWarning( \"Failed to copy proxy asset from \" + audioProxy );\n                return;\n            }\n            \n            AssetDatabase.ImportAsset(newAssetPath);\n            WriteUserData(newAssetPath , newRule, ref currentAsset);\n        }\n\n        public static void CreateProxyModel(AssetRule newRule, ref string currentAsset)\n        {\n            string modelProxy = AssetAuditorPreferences.ProxyModelPath;\n            string ext = modelProxy.Substring( modelProxy.LastIndexOf( '.' ) );\n            string newAssetPath = AssetAuditorPreferences.ProxyAssetsDirectory + Path.DirectorySeparatorChar + newRule.RuleName + ext;\n            if( !AssetDatabase.CopyAsset( modelProxy, newAssetPath ) )\n            {\n                Debug.LogWarning( \"Failed to copy proxy asset from \" + modelProxy );\n                return;\n            }\n\n            AssetDatabase.ImportAsset(newAssetPath);\n            WriteUserData(newAssetPath , newRule, ref currentAsset);\n        }\n        \n        public static void CreateProxyTexture(AssetRule newRule, ref string currentAsset)\n        {\n            string textureProxy = AssetAuditorPreferences.ProxyTexturePath;\n            string ext = textureProxy.Substring( textureProxy.LastIndexOf( '.' ) );\n            string newAssetPath = AssetAuditorPreferences.ProxyAssetsDirectory + Path.DirectorySeparatorChar + newRule.RuleName + ext;\n            if( !AssetDatabase.CopyAsset( textureProxy, newAssetPath ) )\n            {\n                Debug.LogWarning( \"Failed to copy proxy asset from \" + textureProxy );\n                return;\n            }\n\n            AssetDatabase.ImportAsset(newAssetPath);\n            WriteUserData(newAssetPath , newRule , ref currentAsset);\n        }\n\n        \n        public static void WriteUserData(string path, AssetRule assetRule, ref string currentAsset)\n        {\n            AssetImporter assetImporter = AssetImporter.GetAtPath(path);\n            assetRule.AssetGuid = AssetDatabase.AssetPathToGUID(assetImporter.assetPath);\n\n            assetImporter.userData = JsonUtility.ToJson(assetRule);\n\n            EditorUtility.SetDirty(assetImporter);\n            AssetDatabase.WriteImportSettingsIfDirty(path);\n            AssetDatabase.SaveAssets();\n\n            currentAsset = assetRule.AssetGuid;\n        }\n        \n        \n        public static void WriteUserData(string path , AssetRule assetRule)\n        {\n            AssetImporter assetImporter = AssetImporter.GetAtPath(path);\n            assetRule.AssetGuid = AssetDatabase.AssetPathToGUID(assetImporter.assetPath);\n\n            assetImporter.userData = JsonUtility.ToJson(assetRule);\n\n            EditorUtility.SetDirty(assetImporter);\n            AssetDatabase.WriteImportSettingsIfDirty(path);\n            AssetDatabase.SaveAssets();\n        }\n\n        \n        public static bool RuleExists(AssetRule assetRule)\n        {\n            if (!AssetDatabase.IsValidFolder(AssetAuditorPreferences.ProxyAssetsDirectory))\n            {\n                string folder = AssetAuditorPreferences.ProxyAssetsDirectory.Split(Path.DirectorySeparatorChar).Last();\n\n                string dir = AssetAuditorPreferences.ProxyAssetsDirectory.Substring(0,\n                    AssetAuditorPreferences.ProxyAssetsDirectory.Length - folder.Length);\n               \n                AssetDatabase.CreateFolder(dir, folder);\n            }\n                 \n            foreach (string asset in AssetDatabase.FindAssets(\"\", new[] {AssetAuditorPreferences.ProxyAssetsDirectory}))\n            {\n                string guidToAssetPath = AssetDatabase.GUIDToAssetPath(asset);\n                AssetImporter assetImporter = AssetImporter.GetAtPath(guidToAssetPath);\n\n                AssetRule ar = new AssetRule();\n                ar = JsonUtility.FromJson<AssetRule>(assetImporter.userData);\n                if (ar.RuleName == assetRule.RuleName && ar.WildCard == assetRule.WildCard &&\n                    ar.WildCardMatchType == assetRule.WildCardMatchType) return true;\n            }\n            return false;\n        }\n        \n        \n    }\n}"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditor.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 75cdde80fe406b14e816e78029e38d15\ntimeCreated: 1481588091\nlicenseType: Pro\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditorNewRuleWindow.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor;\nusing UnityEditor.VersionControl;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityAssetAuditor\n{\n    public class AssetAuditorNewRuleWindow : EditorWindow\n    {\n        private static List<AssetAuditor.AssetRule> assetRules;\n        private static AssetAuditor.AssetRule newRule;\n\n        private static string currentAsset;\n\n        static int selected = -1;\n        private static string[] affectedAssets;\n        private static AssetAuditorNewRuleWindow window;\n\n        private static Vector2 scrollPosition;\n\n        [MenuItem(\"Asset Auditing/New Audit Rule\")]\n        public static void ShowWindow()\n        {\n            window = GetWindow<AssetAuditorNewRuleWindow>();\n            window.Show();\n            window.titleContent = new GUIContent(\"Asset Auditor Creation\");\n\n            if (!AssetDatabase.IsValidFolder(AssetAuditorPreferences.ProxyAssetsDirectory))\n            {\n                string folder = AssetAuditorPreferences.ProxyAssetsDirectory.Split(Path.DirectorySeparatorChar).Last();\n\n                string dir = AssetAuditorPreferences.ProxyAssetsDirectory.Substring(0,\n                    AssetAuditorPreferences.ProxyAssetsDirectory.Length - folder.Length);\n                \n                \n                AssetDatabase.CreateFolder(dir, folder);\n            }\n            \n            UpdateExistingRules();\n            scrollPosition = Vector2.zero;\n\n            AssetAuditor.queueComplete += AffectedAssetSearchComplete;\n\n        }\n\n        private static void AffectedAssetSearchComplete()\n        {\n            affectedAssets = AssetAuditor.GetAffectedAssets();\n            window.Repaint();\n            AssetAuditor.queueComplete -= AffectedAssetSearchComplete;\n        }\n\n\n        void OnGUI()\n        {\n            DoNewRuleGUI();\n            UpdateSelectedAsset();\n            UpdateExistingRules();\n        }\n\n\n        private static void UpdateSelectedAsset()\n        {\n            if (selected == -1) return;\n            Selection.activeObject =\n                AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(assetRules[selected].AssetGuid),\n                    typeof(Object));\n        }\n\n        \n        private static void UpdateExistingRules()\n        {\n            // clear current list\n            assetRules = new List<AssetAuditor.AssetRule>();\n\n            // get all assets in the proxyassets folder\n            foreach (var asset in AssetDatabase.FindAssets(\"\", new[] {AssetAuditorPreferences.ProxyAssetsDirectory}))\n            {\n                var guidToAssetPath = AssetDatabase.GUIDToAssetPath(asset);\n                var assetImporter = AssetImporter.GetAtPath(guidToAssetPath);\n\n                AssetAuditor.AssetRule ar = new AssetAuditor.AssetRule();\n                ar = JsonUtility.FromJson<AssetAuditor.AssetRule>(assetImporter.userData);\n                assetRules.Add(ar);\n            }\n            int i = 0;\n\n            // make sure that the current asset is selected from assetRules\n            foreach (var assetRule in assetRules)\n            {\n                if (assetRule.AssetGuid == currentAsset)\n                {\n                    selected = i;\n                    return;\n                }\n                i++;\n            }\n            // if we get to here we couldnt find and asset to be the currently selected\n            // set it to -1 and ignore anything to be currently selected\n            selected = -1;\n            currentAsset = \"\";\n        }\n\n        //done\n        private static void DoNewRuleGUI()\n        {\n\n            newRule.RuleName = EditorGUILayout.TextField(\"Rule Name: \", newRule.RuleName);\n\n            EditorGUI.BeginChangeCheck();\n            newRule.WildCardMatchType =\n                (AssetAuditor.WildCardMatchType) EditorGUILayout.EnumPopup(\"Wild Card Matching Type: \",\n                    newRule.WildCardMatchType);\n            if (EditorGUI.EndChangeCheck())\n            {\n                newRule.WildCard = \"\";\n            }\n\n            EditorGUI.BeginChangeCheck();\n            newRule.WildCard = EditorGUILayout.TextField(\"Wild Card: \", newRule.WildCard);\n            if (EditorGUI.EndChangeCheck())\n            {\n                AssetAuditor.queueComplete += AffectedAssetSearchComplete;\n                AssetAuditor.UpdateAffectedAssets(newRule);\n            }\n\n\n            newRule.SelectiveMode = EditorGUILayout.Toggle(\"Selective Mode\", newRule.SelectiveMode);\n\n            if (newRule.SelectiveMode)\n            {\n                if(newRule.SelectiveProperties == null) newRule.SelectiveProperties = new List<string>();\n\n                SerializedObject so = GetSerializedObject(newRule.assetType);\n                var propertyNames = AssetAuditor.GetPropertyNames(so); // TODO need to cache this\n                \n                // loop through all the selective properties\n                for (int i = 0 ; i < newRule.SelectiveProperties.Count ; i++)\n                {\n                    EditorGUILayout.BeginHorizontal();\n                    \n                    EditorGUI.BeginChangeCheck();\n                    newRule.SelectiveProperties[i] = propertyNames[EditorGUILayout.Popup(SelectedFromList(propertyNames , newRule.SelectiveProperties[i]), propertyNames)];\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        AssetAuditor.queueComplete += AffectedAssetSearchComplete;\n                        AssetAuditor.UpdateAffectedAssets(newRule);\n                    }\n\n                    EditorGUILayout.EndHorizontal();\n                }\n\n                EditorGUILayout.BeginHorizontal();\n\n                if (GUILayout.Button(\"+\", GUILayout.MaxWidth(20)))\n                {\n                    AddNewSelectiveRule();\n                }\n                if (GUILayout.Button(\"-\", GUILayout.MaxWidth(20)))\n                {\n                    RemoveLastSelectiveRule();\n                }\n\n                EditorGUILayout.LabelField(\"Add and remove selective property overiding\");\n                EditorGUILayout.EndHorizontal();\n            }\n            \n            // drop down for type\n            EditorGUI.BeginChangeCheck();\n            newRule.assetType = (AssetAuditor.AssetType) EditorGUILayout.IntPopup(\"Rule Type: \", (int)newRule.assetType, new[]{\"Texture\", \"Model\",\"Audio\"},new[]{0,1,2} );\n            if (EditorGUI.EndChangeCheck())\n            {\n                newRule.SelectiveProperties = new List<string>();\n                AssetAuditor.queueComplete += AffectedAssetSearchComplete;\n                AssetAuditor.UpdateAffectedAssets(newRule);\n            }\n            \n            if (!AssetAuditor.RuleExists(newRule))\n            {\n                if (GUILayout.Button(\"Create New \" + newRule.assetType + \" Rule\"))\n                {\n                    switch (newRule.assetType)\n                    {\n                        case AssetAuditor.AssetType.Texture:\n                            AssetAuditor.CreateProxyTexture(newRule , ref currentAsset);\n                            break;\n                        case AssetAuditor.AssetType.Audio:\n                            AssetAuditor.CreateProxyAudio(newRule , ref currentAsset);\n                            break;\n                        case AssetAuditor.AssetType.Model:\n                            AssetAuditor.CreateProxyModel(newRule, ref currentAsset);\n                            break;\n                        default:\n                            throw new ArgumentOutOfRangeException();\n                    }\n\n                    UpdateExistingRules();\n                    AssetAuditor.queueComplete += AffectedAssetSearchComplete;\n                    AssetAuditor.UpdateAffectedAssets(assetRules[selected]);\n                }\n            }\n            else\n            {\n                GUILayout.Label(\"Rule already exists in the project cannot create duplicates\");\n            }\n\n            GUILayout.Space(20);\n            GUILayout.Label(\"Affect Assets Preview\");\n            GUILayout.Space(5);\n\n\n            Rect rt = GUILayoutUtility.GetRect(5, window ? window.position.width-10 : 100f, 18, 18);\n            EditorGUI.ProgressBar(rt,AssetAuditor.GetProgress(), \"Affected Asset Search Progress \" + (AssetAuditor.GetProgress() * 100f).ToString(\"0.00%\"));\n\n            scrollPosition = GUILayout.BeginScrollView(scrollPosition);\n            if (affectedAssets != null)\n            {\n                foreach (string affectedAsset in affectedAssets)\n                {\n                    EditorGUILayout.ObjectField(\n                        AssetDatabase.LoadAssetAtPath(affectedAsset,\n                            AssetAuditor.TypeFromAssetType(newRule.assetType)),\n                        AssetAuditor.TypeFromAssetType(newRule.assetType), false);\n                }\n            }\n            GUILayout.EndScrollView();\n\n            if (GUILayout.Button(\"Open Audit View\"))\n            {\n                AssetAuditorWindow.GetWindow();\n            }\n        }\n\n        private static SerializedObject GetSerializedObject(AssetAuditor.AssetType assetType)\n        {\n            SerializedObject so = null;\n            switch (assetType)\n            {\n                case AssetAuditor.AssetType.Texture:\n                    so = new SerializedObject(TextureImporter.GetAtPath(AssetAuditorPreferences.ProxyTexturePath));\n                    break;\n                case AssetAuditor.AssetType.Model:\n                    so = new SerializedObject(ModelImporter.GetAtPath(AssetAuditorPreferences.ProxyModelPath));\n                    break;\n                case AssetAuditor.AssetType.Audio:\n                    so = new SerializedObject(AudioImporter.GetAtPath(AssetAuditorPreferences.ProxyAudioPath));\n                    break;\n                case AssetAuditor.AssetType.Folder:\n                    break;\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n            return so;\n        }\n\n        private static int SelectedFromList(string[] propertyNames , string current)\n        {\n            if (current == \"\") return 0; // hack to avoid the empty string problem\n            \n            int i = 0;\n            while (propertyNames[i] != current)\n            {\n                i++;\n            }\n            return i;\n        }\n\n        private static void RemoveLastSelectiveRule()\n        {\n            newRule.SelectiveProperties.RemoveAt(newRule.SelectiveProperties.Count-1);\n        }\n\n        private static void AddNewSelectiveRule()\n        {\n            newRule.SelectiveProperties.Add(AssetAuditor.GetPropertyNames(GetSerializedObject(newRule.assetType))[0]);\n        }\n\n    }\n}\n\n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditorNewRuleWindow.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 9cfdaaf847ee42a46bd18fa749076260\ntimeCreated: 1479436789\nlicenseType: Pro\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditorPreferences.cs",
    "content": "﻿using System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityAssetAuditor\n{\n    public class AssetAuditorPreferences\n    {\n        private static string proxyAssetDir;\n        private const string proxyAssetDirKey = \"ProxyAssetDirectory\";\n        private const string proxyAssetDirDefault = \"Assets/Editor/AssetAuditor/ProxyAssets\";\n\n        private static string proxyTexturePath;\n        private const string proxyTexturePathKey = \"ProxyTexturePath\";\n        private const string proxyTexturePathDefault = \"Assets/Editor/AssetAuditor/Texture/DefaultTexture.jpg\";\n\n        private static string proxyModelPath;\n        private const string proxyModelPathKey = \"ProxyModelPath\";\n        private const string proxyModelPathDefault = \"Assets/Editor/AssetAuditor/Models/DefaultAvatar.fbx\";\n\n        private static string proxyAudioPath;\n        private const string proxyAudioPathKey = \"ProxyAudioPath\";\n        private const string proxyAudioPathDefault = \"Assets/Editor/AssetAuditor/Audio/DefaultAudio.wav\";\n\n        static AssetAuditorPreferences()\n        {\n            proxyAssetDir = EditorPrefs.GetString( proxyAssetDirKey, proxyAssetDirDefault );\n            proxyTexturePath = EditorPrefs.GetString( proxyTexturePathKey, proxyTexturePathDefault );\n            proxyModelPath = EditorPrefs.GetString( proxyModelPathKey, proxyModelPathDefault );\n            proxyAudioPath = EditorPrefs.GetString( proxyAudioPathKey, proxyAudioPathDefault );\n        }\n\n        public static string ProxyAssetsDirectory\n        {\n            get\n            {\n                createProxyAssetsDirectory();\n                return proxyAssetDir;\n            }\n        }\n\n        public static string ProxyTexturePath\n        {\n            get { return proxyTexturePath; }\n        }\n\n        public static string ProxyModelPath\n        {\n            get { return proxyModelPath; }\n        }\n\n        public static string ProxyAudioPath\n        {\n            get { return proxyAudioPath; }\n        }\n\n        private static void createProxyAssetsDirectory()\n        {\n            if( AssetDatabase.IsValidFolder( proxyAssetDir ) )\n                return;\n\n            AssetAuditorUtilities.CreatePath.Create( proxyAssetDir );\n        }\n\n        [PreferenceItem( \"Asset Auditor\" )]\n        public static void PreferencesGUI()\n        {\n            EditorGUILayout.LabelField( \"Proxy Assets Directory\", EditorStyles.boldLabel );\n\n            EditorGUILayout.BeginHorizontal();\n\n            proxyAssetDir = \"Assets/\" + EditorGUILayout.TextField( proxyAssetDir.Remove( 0, 7 ) );\n\n            if( GUILayout.Button( \"Browse\", EditorStyles.miniButton ) )\n            {\n                string path = EditorUtility.OpenFolderPanel( \"Select Proxy Assets Directory\", proxyAssetDir, \"\" );\n\n                if( !path.Contains( Application.dataPath ) )\n                {\n                    Debug.LogError( \"Selected path \" + path + \" is not a directory within the open project\" );\n                }\n                else if( path.Length > 0 )\n                {\n                    proxyAssetDir = path.Substring( Application.dataPath.Length - 6 );\n                    ;\n                    EditorPrefs.SetString( proxyAssetDirKey, proxyAssetDir );\n                }\n            }\n\n            EditorGUILayout.EndHorizontal();\n\n            if( AssetDatabase.IsValidFolder( proxyAssetDir ) == false )\n            {\n                EditorGUILayout.HelpBox( \"Folder does not exist at given path\", MessageType.Warning );\n                if( GUILayout.Button( \"Create Now\", EditorStyles.miniButton ) )\n                {\n                    createProxyAssetsDirectory();\n                }\n            }\n\n            EditorGUILayout.Space();\n            EditorGUILayout.Space();\n\n            EditorGUILayout.LabelField( \"Proxy Asset Paths\", EditorStyles.boldLabel );\n\n            EditorGUILayout.Space();\n            EditorGUILayout.LabelField( \"Texture\" );\n\n            EditorGUILayout.BeginHorizontal();\n            proxyTexturePath = \"Assets/\" + EditorGUILayout.TextField( proxyTexturePath.Remove( 0, 7 ) );\n\n            if( GUILayout.Button( \"Browse\", EditorStyles.miniButton ) )\n            {\n                string path = EditorUtility.OpenFilePanel( \"Select Proxy Texture\", proxyTexturePath, \"jpg,png,bmp,tga\" );\n\n                if( path.Length > 0 )\n                {\n                    if( !path.Contains( Application.dataPath ) )\n                    {\n                        Debug.LogError( \"Selected path <\" + path + \"> is not a directory within the open project\" );\n                    }\n                    else\n                    {\n                        proxyTexturePath = path.Substring( Application.dataPath.Length - 6 );\n                        EditorPrefs.SetString( proxyTexturePathKey, proxyTexturePath );\n                    }\n                }\n            }\n\n            EditorGUILayout.EndHorizontal();\n\n            System.Type t = AssetDatabase.GetMainAssetTypeAtPath( proxyTexturePath );\n            if( t == null || t != typeof(Texture2D) )\n                EditorGUILayout.HelpBox( \"Proxy Texture does not exist at given path\", MessageType.Warning );\n\n            EditorGUILayout.Space();\n            EditorGUILayout.LabelField( \"Model\" );\n\n            EditorGUILayout.BeginHorizontal();\n            proxyModelPath = \"Assets/\" + EditorGUILayout.TextField( proxyModelPath.Remove( 0, 7 ) );\n            if( GUILayout.Button( \"Browse\", EditorStyles.miniButton ) )\n            {\n                string path = EditorUtility.OpenFilePanel( \"Select Proxy Model\", proxyModelPath, \"fbx,obj,3ds\" );\n\n                if( path.Length > 0 )\n                {\n                    if( !path.Contains( Application.dataPath ) )\n                    {\n                        Debug.LogError( \"Selected path <\" + path + \"> is not a directory within the open project\" );\n                    }\n                    else\n                    {\n                        proxyModelPath = path.Substring( Application.dataPath.Length - 6 );\n                        EditorPrefs.SetString( proxyModelPathKey, proxyModelPath );\n                    }\n                }\n            }\n\n            EditorGUILayout.EndHorizontal();\n\n            t = AssetDatabase.GetMainAssetTypeAtPath( proxyModelPath );\n            if( t == null || t != typeof(GameObject) )\n                EditorGUILayout.HelpBox( \"Proxy Texture does not exist at given path\", MessageType.Warning );\n\n            EditorGUILayout.Space();\n            EditorGUILayout.LabelField( \"Audio\" );\n\n            EditorGUILayout.BeginHorizontal();\n            proxyAudioPath = \"Assets/\" + EditorGUILayout.TextField( proxyAudioPath.Remove( 0, 7 ) );\n            if( GUILayout.Button( \"Browse\", EditorStyles.miniButton ) )\n            {\n                string path = EditorUtility.OpenFilePanel( \"Select Proxy Audio\", proxyAudioPath, \"wav,mp3,ogg\" );\n\n                if( path.Length > 0 )\n                {\n                    if( !path.Contains( Application.dataPath ) )\n                    {\n                        Debug.LogError( \"Selected path <\" + path + \"> is not a directory within the open project\" );\n                    }\n                    else\n                    {\n                        proxyAudioPath = path.Substring( Application.dataPath.Length - 6 );\n                        EditorPrefs.SetString( proxyAudioPathKey, proxyAudioPath );\n                    }\n                }\n            }\n\n            EditorGUILayout.EndHorizontal();\n\n            t = AssetDatabase.GetMainAssetTypeAtPath( proxyAudioPath );\n            if( t == null || t != typeof(AudioClip) )\n                EditorGUILayout.HelpBox( \"Proxy AudioClip does not exist at given path\", MessageType.Warning );\n        }\n    }\n}"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditorPreferences.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 940f261582124401db9376c57e2a48c8\ntimeCreated: 1505468470\nlicenseType: Pro\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditorUtilities.cs",
    "content": "﻿using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEngine;\nusing UnityEngine.Assertions;\n\nnamespace UnityAssetAuditor\n{\n\tpublic class AssetAuditorUtilities\n\t{\n\t\tpublic class CreatePath : IEnumerable\n\t\t{\n\t\t\tprivate string[] m_Folders;\n\n\t\t\tpublic CreatePath( string path )\n\t\t\t{\n\t\t\t\tAssert.IsTrue( path.StartsWith( \"Assets/\" ) );\n\t\t\t\tm_Folders = path.Split( '/' );\n\t\t\t}\n\n\t\t\tpublic CreatePath( string[] folderList )\n\t\t\t{\n\t\t\t\tAssert.IsTrue( folderList.Length > 1 && folderList[0] == \"Assets\" );\n\n\t\t\t\tm_Folders = new string[folderList.Length];\n\t\t\t\tfor( int i = 0; i < folderList.Length; i++ )\n\t\t\t\t\tm_Folders[i] = folderList[i];\n\t\t\t}\n\n\t\t\tIEnumerator IEnumerable.GetEnumerator()\n\t\t\t{\n\t\t\t\treturn GetEnumerator();\n\t\t\t}\n\n\t\t\tpublic CreatePathEnumerator GetEnumerator()\n\t\t\t{\n\t\t\t\treturn new CreatePathEnumerator( m_Folders );\n\t\t\t}\n\n\t\t\tpublic static string Create( string path )\n\t\t\t{\n\t\t\t\tCreatePathEnumerator e = new CreatePathEnumerator( path );\n\t\t\t\twhile( e.MoveNext() )\n\t\t\t\t{\n\t\t\t\t\t// Loop through each folder\n\t\t\t\t}\n\n\t\t\t\treturn e.Current;\n\t\t\t}\n\t\t}\n\n\t\tpublic class CreatePathEnumerator : IEnumerator\n\t\t{\n\t\t\tprivate string[] m_FolderNames;\n\t\t\tprivate int m_Position = 0;\n\n\t\t\tprivate string m_CurrentGuid;\n\t\t\tprivate string m_CurrentPath;\n\n\t\t\tpublic CreatePathEnumerator( string[] folderList )\n\t\t\t{\n\t\t\t\tm_FolderNames = folderList;\n\t\t\t\tm_CurrentPath = m_FolderNames[0];\n\t\t\t}\n\n\t\t\tpublic CreatePathEnumerator( string path )\n\t\t\t{\n\t\t\t\tDebug.Log( path );\n\t\t\t\tm_FolderNames = path.Split( '/' );\n\t\t\t\tm_CurrentPath = m_FolderNames[0];\n\t\t\t}\n\n\t\t\tpublic bool MoveNext()\n\t\t\t{\n\t\t\t\tm_Position++;\n\n\t\t\t\tif( m_Position < m_FolderNames.Length )\n\t\t\t\t{\n\t\t\t\t\tstring nextPath = m_CurrentPath + \"/\" + m_FolderNames[m_Position];\n\t\t\t\t\tif( AssetDatabase.IsValidFolder( nextPath ) )\n\t\t\t\t\t\tm_CurrentGuid = string.Empty;\n\t\t\t\t\telse\n\t\t\t\t\t\tm_CurrentGuid = AssetDatabase.CreateFolder( m_CurrentPath, m_FolderNames[m_Position] );\n\n\t\t\t\t\tm_CurrentPath = nextPath;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tpublic void Reset()\n\t\t\t{\n\t\t\t\tm_Position = 0;\n\t\t\t}\n\n\t\t\tobject IEnumerator.Current\n\t\t\t{\n\t\t\t\tget { return Current; }\n\t\t\t}\n\n\t\t\tpublic string Current\n\t\t\t{\n\t\t\t\tget { return m_CurrentGuid; }\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditorUtilities.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 5e05911aedaeb4c9e9bd82b182deab1b\ntimeCreated: 1529319486\nlicenseType: Pro\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditorWindow.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\n\n\nnamespace UnityAssetAuditor\n{\n\n    public delegate void OnGatherAssetRulesComplete();\n\n    public delegate void OnGatherDataComplete();\n    \n    class AssetAuditorWindow : EditorWindow\n    {\n        [SerializeField]\n        static TreeViewState m_TreeViewState; // Serialized in the window layout file so it survives assembly reloading\n\n        [SerializeField] MultiColumnHeaderState m_MultiColumnHeaderState;\n\n        static AssetAuditTreeView m_TreeView;\n        private static List<AssetAuditor.AssetRule> assetRules;\n        private List<string> assetRuleNames;\n        private static int selected = 0;\n        private static int selectedSelective = 0;\n        private static bool editSelective;\n        private static int editSelectiveProp = 0;\n        private string[] affectedAssets;\n        private Action<AssetAuditTreeElement> act;\n\n        private OnGatherAssetRulesComplete onGatherAssetRulesComplete;\n        private OnGatherDataComplete onGatherDataComplete;\n        private List<AssetAuditTreeElement> elements;\n        private bool gatherAssetsComplete;\n        private bool gatherDataComplete;\n        private List<AssetAuditTreeElement> tempElements;\n\n        private enum State\n        {\n            Uninitialized,\n            GatheringRules,\n            GatheringData,\n            Initialized,\n            NoAssetRules\n        }\n\n        [NonSerialized]\n        private State state = State.Uninitialized;\n\n\n        [MenuItem(\"Asset Auditing/Auditor View\")]\n        public static AssetAuditorWindow GetWindow()\n        {\n            var window = GetWindow<AssetAuditorWindow>();\n            window.titleContent = new GUIContent(\"Audit\");\n\n            return window;\n        }\n\n\n        Rect multiColumnTreeViewRect\n        {\n            get { return new Rect(20, 110, position.width - 40, position.height - 130); }\n        }\n\n        Rect toolbarRect\n        {\n            get { return new Rect(20f, 90f, position.width - 40f, 20f); }\n        }\n\n        Rect bottomToolbarRect\n        {\n            get { return new Rect(20f, position.height - 18f, position.width - 40f, 16f); }\n        }\n        \n        Rect progressBarRect\n        {\n            get { return new Rect(20f, position.height - 36f, position.width - 40f, 16f); }\n        }\n\n        Rect ruleSelectRect\n        {\n            get { return new Rect(20f, 10f, position.width - 40, 15); }\n        }\n\n        Rect wildCardDisplayRect\n        {\n            get { return new Rect(20, 30, position.width - 40f, 15f); }\n        }\n\n        Rect SelectivePropRect\n        {\n            get { return new Rect(20, 50, position.width - 40f, 15f); }\n        }\n\n        Rect AddSelectivePropRect\n        {\n            get {return new Rect(20,70,18,18);}\n        }\n\n        Rect RemoveSelectivePropRect\n        {\n            get { return new Rect(40,70,18,18);}\n        }\n\n        Rect EditSelectedPropButtonRect\n        {\n            get {return new Rect(60,70, 40,18 );}\n        }\n        \n        Rect EditSelectedPropDropDownRect\n        {\n            get {return new Rect(110,70, 400,18 );}\n        }\n\n        public AssetAuditTreeView treeView\n        {\n            get { return m_TreeView; }\n        }\n\n        private void  FixRule(AssetAuditTreeElement assetAuditTreeElement)\n        {\n            AssetAuditor.FixRule(assetAuditTreeElement , assetRules[selected]);\n\n            elements = new List<AssetAuditTreeElement>();\n            AssetAuditor.queueComplete += OnGatherDataComplete;\n            AssetAuditor.AddEnumerator(AssetAuditor.GatherData(assetRules[selected], elements , selectedSelective));\n        }\n\n\n        void GatherAssetRules()\n        {\n            gatherAssetsComplete = false;\n            AssetAuditor.queueComplete += OnGatherAssetRulesComplete;\n                \n            assetRules = new List<AssetAuditor.AssetRule>();\n            assetRuleNames = new List<string>();\n                \n                \n            AssetAuditor.ClearQueue();\n            AssetAuditor.AddEnumerator(AssetAuditor.GatherAssetRules(assetRules,assetRuleNames));   \n        }\n        \n        private void OnGatherAssetRulesComplete()\n        {\n            AssetAuditor.queueComplete -= OnGatherAssetRulesComplete;\n\n            if (assetRules.Count > 0)\n            {\n                gatherAssetsComplete = true;\n            }\n            else\n            {\n                gatherAssetsComplete = false;\n                state = State.NoAssetRules;\n            }\n        }\n\n\n        void GatherData()\n        {\n            gatherDataComplete = false;\n            AssetAuditor.queueComplete += OnGatherDataComplete;\n            elements = new List<AssetAuditTreeElement>();\n            \n            AssetAuditor.ClearQueue();\n            AssetAuditor.UpdateAffectedAssets(assetRules[selected]);\n            AssetAuditor.AddEnumerator(AssetAuditor.GatherData(assetRules[selected],elements,selectedSelective));  \n        }\n        \n        private void OnGatherDataComplete()\n        {\n            AssetAuditor.queueComplete -= OnGatherDataComplete;\n\n            // Check if it already exists (deserialized from window layout file or scriptable object)\n            if (m_TreeViewState == null)\n                m_TreeViewState = new TreeViewState();\n\n            if (m_TreeView != null && elements.Count > 0)\n            {\n                m_TreeView.treeModel.SetData(elements);\n                m_TreeView.Reload();\n            }\n\n            gatherDataComplete = true;\n        }\n\n\n        void OnSelectionChange()\n        {\n       //     if (!m_Initialized)\n       //         return;\n       //     m_TreeView.treeModel.SetData(GetData());\n       //     m_TreeView.Reload();\n        }\n\n        private void OnFocus()\n        {\n            // this doesn't seem to be needed\n            /*if (m_Initialized)\n            {\n                GatherAssetRules();\n                m_TreeView.treeModel.SetData(GetData());\n                m_TreeView.Reload();\n            }*/\n        }\n\n        void OnGUI()\n        {\n            switch (state)\n            {\n                case State.Uninitialized:\n                    act = FixRule;\n                    GatherAssetRules();\n                    state = State.GatheringRules;\n                    break;\n\n                case State.GatheringRules:\n                    if (gatherAssetsComplete)\n                    {\n                        GatherData();\n                        state = State.GatheringData;\n                    }\n                    break;\n\n                case State.GatheringData:\n                    if (gatherDataComplete)\n                    {\n                        // Check if it already exists (deserialized from window layout file or scriptable object)\n                        if (m_TreeViewState == null)\n                            m_TreeViewState = new TreeViewState();\n\n                        var headerState =\n                            AssetAuditTreeView.CreateDefaultMultiColumnHeaderState(multiColumnTreeViewRect.width);\n                        if (MultiColumnHeaderState.CanOverwriteSerializedFields(m_MultiColumnHeaderState, headerState))\n                            MultiColumnHeaderState.OverwriteSerializedFields(m_MultiColumnHeaderState, headerState);\n                        m_MultiColumnHeaderState = headerState;\n\n                        var multiColumnHeader = new MultiColumnHeader(headerState); \n                        var treeModel = new TreeModel<AssetAuditTreeElement>(elements); \n                        m_TreeView = new AssetAuditTreeView(m_TreeViewState, multiColumnHeader, treeModel, act); \n                        GUILayout.Label(\" no asset rules have been found in the project\");\n\n                        state = State.Initialized;\n                    }\n                    break;\n\n                case State.Initialized:\n                    DoRuleSelectionGUI();\n                    SearchBar(toolbarRect);\n                    DoTreeView(multiColumnTreeViewRect);\n                    BottomToolBar(bottomToolbarRect);\n                    break;\n                    \n                case State.NoAssetRules:\n                    DoNoAssetRuleGUI();\n                    break;\n                        \n            }\n                    \n            DoProgressBar(progressBarRect);\n        }\n\n        private void DoNoAssetRuleGUI()\n        {\n            GUILayout.Label(\" No Asset Rules Are Present In The Project \");\n\n            if (GUILayout.Button(\"Search Again For Assets \")) /// TODO add directory to string for proxy asset path\n            {\n                GatherAssetRules();\n                state = State.GatheringRules;\n            }\n        }\n\n        private void DoProgressBar(Rect rect)\n        {\n            var progress = AssetAuditor.GetProgress();\n            EditorGUI.ProgressBar(progressBarRect , progress, \" Search Progress \" + progress.ToString(\"0.00%\"));\n        }\n\n        private void DoRuleSelectionGUI()\n        {   \n            EditorGUI.BeginChangeCheck();\n            selected = EditorGUI.Popup(ruleSelectRect, \"Rule Name\", selected, assetRuleNames.ToArray());\n            if (EditorGUI.EndChangeCheck())\n            {\n                selectedSelective = 0;\n                GatherData();\n            }\n\n            // make wildcard editable and update selection from it\n            if (assetRules != null && selected != -1)// && !string.IsNullOrEmpty(assetRules[selected].WildCard))\n            {\n                AssetAuditor.AssetRule ar = assetRules[selected];\n                EditorGUI.BeginChangeCheck();\n                ar.WildCard = EditorGUI.TextField(wildCardDisplayRect, \"WildCard \", ar.WildCard);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    assetRules[selected] = ar;\n                    GatherData();\n                    AssetAuditor.WriteUserData(AssetDatabase.GUIDToAssetPath(ar.AssetGuid), ar);\n                }\n                \n                if (ar.SelectiveProperties != null && ar.SelectiveProperties.Count > 0)\n                {\n                    selectedSelective = EditorGUI.Popup(SelectivePropRect, \"Selective Properties\", selectedSelective, ar.SelectiveProperties.ToArray());\n                }\n                else\n                {\n                    EditorGUI.LabelField(SelectivePropRect , \" No Selective Properties in the Asset Rule\");\n                }\n\n                if (GUI.Button(AddSelectivePropRect, \"+\"))\n                {\n                    // add a new selective property              \n                    if (ar.SelectiveProperties != null && !ar.SelectiveProperties.Contains(\"Unnasigned property\")) ar.SelectiveProperties.Add(\"Unnasigned property\");\n                    assetRules[selected] = ar;\n                    GatherData();\n                    AssetAuditor.WriteUserData(AssetDatabase.GUIDToAssetPath(ar.AssetGuid), ar);\n                }\n                if (ar.SelectiveProperties != null && ar.SelectiveProperties.Count > 0)\n                {\n                    if (GUI.Button(RemoveSelectivePropRect, \"-\"))\n                    {\n                        // remove last selective property\n                        ar.SelectiveProperties.RemoveAt(ar.SelectiveProperties.Count - 1);\n                        \n                        if (ar.SelectiveProperties.Count == 0)\n                            ar.SelectiveMode = false;\n                        \n                        assetRules[selected] = ar;\n                        GatherData();\n                        AssetAuditor.WriteUserData(AssetDatabase.GUIDToAssetPath(ar.AssetGuid), ar);\n                    }\n                    editSelective = GUI.Toggle(EditSelectedPropButtonRect, editSelective, \"Edit\", \"Button\");\n                    if (editSelective)\n                    {\n                        SerializedObject so = new SerializedObject(\n                            AssetImporter.GetAtPath(AssetDatabase.GUIDToAssetPath(ar.AssetGuid)));\n                        EditorGUI.BeginChangeCheck();\n                        editSelectiveProp = EditorGUI.Popup(EditSelectedPropDropDownRect, editSelectiveProp,\n                            AssetAuditor.GetPropertyNames(so));\n\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            ar.SelectiveProperties[selectedSelective] =\n                                AssetAuditor.GetPropertyNames(so)[editSelectiveProp];\n                            \n                            assetRules[selected] = ar;\n                            GatherData();\n                            AssetAuditor.WriteUserData(AssetDatabase.GUIDToAssetPath(ar.AssetGuid), ar);\n                        }\n                    }\n                }\n            }\n        }\n\n\n\n        void SearchBar(Rect rect)\n        {\n            if(treeView != null)\n            treeView.searchString = SearchField.OnGUI(rect, treeView.searchString);\n        }\n\n        void DoTreeView(Rect rect)\n        {\n            if(m_TreeView != null)\n            m_TreeView.OnGUI(rect);\n        }\n\n        void BottomToolBar(Rect rect)\n        {\n            var style = \"miniButton\";\n            if (GUI.Button(new Rect(rect.x, rect.y, rect.width / 3, rect.height), \"Expand All\", style))\n            {\n                treeView.ExpandAll();\n            }\n            if (GUI.Button(new Rect(rect.x + rect.width / 3, rect.y, rect.width / 3, rect.height), \"Collapse All\",\n                style))\n            {\n                treeView.CollapseAll();\n            }\n            if (GUI.Button(new Rect(rect.x + ((rect.width / 3) * 2), rect.y, rect.width / 3, rect.height), \"Fix All\",\n                style))\n            {\n                AssetAuditor.AddEnumerator(AssetAuditor.FixAll(m_TreeView , assetRules[selected]));\n            }\n        }\n\n    }\n\n    internal static class SearchField\n    {\n        static class Styles\n        {\n            public static GUIStyle searchField = \"SearchTextField\";\n            public static GUIStyle searchFieldCancelButton = \"SearchCancelButton\";\n            public static GUIStyle searchFieldCancelButtonEmpty = \"SearchCancelButtonEmpty\";\n        }\n\n        public static string OnGUI(Rect position, string text)\n        {\n            // Search field \n            Rect textRect = position;\n            textRect.width -= 15;\n            text = EditorGUI.TextField(textRect, GUIContent.none, text, Styles.searchField);\n\n            // Cancel button\n            Rect buttonRect = position;\n            buttonRect.x += position.width - 15;\n            buttonRect.width = 15;\n            if (GUI.Button(buttonRect, GUIContent.none,\n                    text != \"\" ? Styles.searchFieldCancelButton : Styles.searchFieldCancelButtonEmpty) && text != \"\")\n            {\n                text = \"\";\n                GUIUtility.keyboardControl = 0;\n            }\n            return text;\n        }\n    }\n}"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/AssetAuditorWindow.cs.meta",
    "content": "fileFormatVersion: 2\nguid: c3cf55b48c197bb40a09696dead1d7c2\ntimeCreated: 1467106475\nlicenseType: Pro\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/TreeElement.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\n\nnamespace UnityAssetAuditor\n{\n\n\t[Serializable]\n\tpublic class TreeElement\n\t{\n\t\t[SerializeField] int m_ID;\n\t\t[SerializeField] string m_Name;\n\t\t[SerializeField] int m_Depth;\n\n\t\t[NonSerialized] TreeElement m_Parent;\n\t\t[NonSerialized] List<TreeElement> m_Children;\n\n\t\tpublic int depth\n\t\t{\n\t\t\tget { return m_Depth; }\n\t\t\tset { m_Depth = value; }\n\t\t}\n\n\t\tpublic TreeElement parent\n\t\t{\n\t\t\tget { return m_Parent; }\n\t\t\tset { m_Parent = value; }\n\t\t}\n\n\t\tpublic List<TreeElement> children\n\t\t{\n\t\t\tget { return m_Children; }\n\t\t\tset { m_Children = value; }\n\t\t}\n\n\t\tpublic bool hasChildren\n\t\t{\n\t\t\tget { return children != null && children.Count > 0; }\n\t\t}\n\n\t\tpublic string name\n\t\t{\n\t\t\tget { return m_Name; } set { m_Name = value; }\n\t\t}\n\n\t\tpublic int id\n\t\t{\n\t\t\tget { return m_ID; } set { m_ID = value; }\n\t\t}\n\n\t\tpublic TreeElement ()\n\t\t{\n\t\t}\n\n\t\tpublic TreeElement (string name, int depth, int id)\n\t\t{\n\t\t\tm_Name = name;\n\t\t\tm_ID = id;\n\t\t\tm_Depth = depth;\n\t\t}\n\t}\n\n}\n\n\n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/TreeElement.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 69be32fe4d27dde489209c5885c1e5dc\ntimeCreated: 1472024155\nlicenseType: Pro\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/TreeElementUtility.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing NUnit.Framework;\nusing UnityEditor;\n\n\nnamespace UnityAssetAuditor\n{\n\n\t// TreeElementUtility and TreeElement are useful helper classes for backend tree data structures.\n\t// See tests at the bottom for examples of how to use.\n\n\tpublic static class TreeElementUtility\n\t{\n\t\tpublic static void TreeToList<T>(T root, IList<T> result) where T : TreeElement\n\t\t{\n\t\t\tif (result == null)\n\t\t\t\tthrow new NullReferenceException(\"The input 'IList<T> result' list is null\");\n\t\t\tresult.Clear();\n\n\t\t\tStack<T> stack = new Stack<T>();\n\t\t\tstack.Push(root);\n\n\t\t\twhile (stack.Count > 0)\n\t\t\t{\n\t\t\t\tT current = stack.Pop();\n\t\t\t\tresult.Add(current);\n\n\t\t\t\tif (current.children != null && current.children.Count > 0)\n\t\t\t\t{\n\t\t\t\t\tfor (int i = current.children.Count - 1; i >= 0; i--)\n\t\t\t\t\t{\n\t\t\t\t\t\tstack.Push((T)current.children[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Returns the root of the tree parsed from the list (always the first element).\n\t\t// Important: the first item and is required to have a depth value of -1. \n\t\t// The rest of the items should have depth >= 0. \n\t\tpublic static T ListToTree<T>(IList<T> list) where T : TreeElement\n\t\t{\n\t\t\t// Validate input\n\t\t\tValidateDepthValues (list);\n\n\t\t\t// Clear old states\n\t\t\tforeach (var element in list)\n\t\t\t{\n\t\t\t\telement.parent = null;\n\t\t\t\telement.children = null;\n\t\t\t}\n\n\t\t\t// Set child and parent references using depth info\n\t\t\tfor (int parentIndex = 0; parentIndex < list.Count; parentIndex++)\n\t\t\t{\n\t\t\t\tvar parent = list[parentIndex];\n\t\t\t\tbool alreadyHasValidChildren = parent.children != null;\n\t\t\t\tif (alreadyHasValidChildren)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tint parentDepth = parent.depth;\n\t\t\t\tint childCount = 0;\n\n\t\t\t\t// Count children based depth value, we are looking at children until it's the same depth as this object\n\t\t\t\tfor (int i = parentIndex + 1; i < list.Count; i++)\n\t\t\t\t{\n\t\t\t\t\tif (list[i].depth == parentDepth + 1)\n\t\t\t\t\t\tchildCount++;\n\t\t\t\t\tif (list[i].depth <= parentDepth)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Fill child array\n\t\t\t\tList<TreeElement> childList = null;\n\t\t\t\tif (childCount != 0)\n\t\t\t\t{\n\t\t\t\t\tchildList = new List<TreeElement>(childCount); // Allocate once\n\t\t\t\t\tchildCount = 0;\n\t\t\t\t\tfor (int i = parentIndex + 1; i < list.Count; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (list[i].depth == parentDepth + 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlist[i].parent = parent;\n\t\t\t\t\t\t\tchildList.Add(list[i]);\n\t\t\t\t\t\t\tchildCount++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (list[i].depth <= parentDepth)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tparent.children = childList;\n\t\t\t}\n\n\t\t\treturn list[0];\n\t\t}\n\n\t\t// Check state of input list\n\t\tpublic static void ValidateDepthValues<T>(IList<T> list) where T : TreeElement\n\t\t{\n\t\t\tif (list.Count == 0)\n\t\t\t\tthrow new ArgumentException(\"list should have items, count is 0, check before calling ValidateDepthValues\", \"list\");\n\n\t\t\tif (list[0].depth != -1)\n\t\t\t\tthrow new ArgumentException(\"list item at index 0 should have a depth of -1 (since this should be the hidden root of the tree). Depth is: \" + list[0].depth, \"list\");\n\n\t\t\tfor (int i = 0; i < list.Count - 1; i++)\n\t\t\t{\n\t\t\t\tint depth = list[i].depth;\n\t\t\t\tint nextDepth = list[i + 1].depth;\n\t\t\t\tif (nextDepth > depth && nextDepth - depth > 1)\n\t\t\t\t\tthrow new ArgumentException(string.Format(\"Invalid depth info in input list. Depth cannot increase more than 1 per row. Index {0} has depth {1} while index {2} has depth {3}\", i, depth, i + 1, nextDepth));\n\t\t\t}\n\n\t\t\tfor (int i = 1; i < list.Count; ++i)\n\t\t\t\tif (list[i].depth < 0)\n\t\t\t\t\tthrow new ArgumentException(\"Invalid depth value for item at index \" + i + \". Only the first item (the root) should have depth below 0.\");\n\n\t\t\tif (list.Count > 1 && list[1].depth != 0)\n\t\t\t\tthrow new ArgumentException(\"Input list item at index 1 is assumed to have a depth of 0\", \"list\");\n\t\t}\n\n\n\t\t// For updating depth values below any given element e.g after reparenting elements\n\t\tpublic static void UpdateDepthValues<T>(T root) where T : TreeElement\n\t\t{\n\t\t\tif (root == null)\n\t\t\t\tthrow new ArgumentNullException(\"root\", \"The root is null\");\n\n\t\t\tif (!root.hasChildren)\n\t\t\t\treturn;\n\n\t\t\tStack<TreeElement> stack = new Stack<TreeElement>();\n\t\t\tstack.Push(root);\n\t\t\twhile (stack.Count > 0)\n\t\t\t{\n\t\t\t\tTreeElement current = stack.Pop();\n\t\t\t\tif (current.children != null)\n\t\t\t\t{\n\t\t\t\t\tforeach (var child in current.children)\n\t\t\t\t\t{\n\t\t\t\t\t\tchild.depth = current.depth + 1;\n\t\t\t\t\t\tstack.Push(child);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Returns true if there is an ancestor of child in the elements list\n\t\tstatic bool IsChildOf<T>(T child, IList<T> elements) where T : TreeElement\n\t\t{\n\t\t\twhile (child != null)\n\t\t\t{\n\t\t\t\tchild = (T)child.parent;\n\t\t\t\tif (elements.Contains(child))\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tpublic static IList<T> FindCommonAncestorsWithinList<T>(IList<T> elements) where T : TreeElement\n\t\t{\n\t\t\tif (elements.Count == 1)\n\t\t\t\treturn new List<T>(elements);\n\n\t\t\tList<T> result = new List<T>(elements);\n\t\t\tresult.RemoveAll(g => IsChildOf(g, elements));\n\t\t\treturn result;\n\t\t}\n\t}\n\n\n\n\tclass TreeElementUtilityTests\n\t{\n\t\tclass TestElement : TreeElement\n\t\t{\n\t\t\tpublic TestElement (string name, int depth)\n\t\t\t{\n\t\t\t\tthis.name = name;\n\t\t\t\tthis.depth = depth;\n\t\t\t}\n\t\t}\n\n\t\t#region Tests\n\t\t[Test]\n\t\tpublic static void TestTreeToListWorks()\n\t\t{\n\t\t\t// Arrange\n\t\t\tTestElement root = new TestElement(\"root\", -1);\n\t\t\troot.children = new List<TreeElement>();\n\t\t\troot.children.Add(new TestElement(\"A\", 0));\n\t\t\troot.children.Add(new TestElement(\"B\", 0));\n\t\t\troot.children.Add(new TestElement(\"C\", 0));\n\n\t\t\troot.children[1].children = new List<TreeElement>();\n\t\t\troot.children[1].children.Add(new TestElement(\"Bchild\", 1));\n\n\t\t\troot.children[1].children[0].children = new List<TreeElement>();\n\t\t\troot.children[1].children[0].children.Add(new TestElement(\"Bchildchild\", 2));\n\n\t\t\t// Test\n\t\t\tList<TestElement> result = new List<TestElement>();\n\t\t\tTreeElementUtility.TreeToList(root, result);\n\n\t\t\t// Assert\n\t\t\tstring[] namesInCorrectOrder = { \"root\", \"A\", \"B\", \"Bchild\", \"Bchildchild\", \"C\" };\n\t\t\tAssert.AreEqual(namesInCorrectOrder.Length, result.Count, \"Result count is not match\");\n\t\t\tfor (int i = 0; i < namesInCorrectOrder.Length; ++i)\n\t\t\t{\n\t\t\t\tAssert.AreEqual(namesInCorrectOrder[i], result[i].name);\n\t\t\t}\n\t\t\tTreeElementUtility.ValidateDepthValues(result);\n\t\t}\n\n\n\t\t[Test]\n\t\tpublic static void TestListToTreeWorks()\n\t\t{\n\t\t\t// Arrange\n\t\t\tvar list = new List<TestElement>();\n\t\t\tlist.Add(new TestElement(\"root\", -1));\n\t\t\tlist.Add(new TestElement(\"A\", 0));\n\t\t\tlist.Add(new TestElement(\"B\", 0));\n\t\t\tlist.Add(new TestElement(\"Bchild\", 1));\n\t\t\tlist.Add(new TestElement(\"Bchildchild\", 2));\n\t\t\tlist.Add(new TestElement(\"C\", 0));\n\n\t\t\t// Test\n\t\t\tTestElement root = TreeElementUtility.ListToTree(list);\n\n\t\t\t// Assert\n\t\t\tAssert.AreEqual(\"root\", root.name);\n\t\t\tAssert.AreEqual(3, root.children.Count);\n\t\t\tAssert.AreEqual(\"C\", root.children[2].name);\n\t\t\tAssert.AreEqual(\"Bchildchild\", root.children[1].children[0].children[0].name);\n\t\t}\n\n\t\t[Test]\n\t\tpublic static void TestListToTreeThrowsExceptionIfRootIsInvalidDepth()\n\t\t{\n\t\t\t// Arrange\n\t\t\tvar list = new List<TestElement>();\n\t\t\tlist.Add(new TestElement(\"root\", 0));\n\t\t\tlist.Add(new TestElement(\"A\", 1));\n\t\t\tlist.Add(new TestElement(\"B\", 1));\n\t\t\tlist.Add(new TestElement(\"Bchild\", 2));\n\n\t\t\t// Test\n\t\t\tbool catchedException = false;\n\t\t\ttry\n\t\t\t{\n\t\t\t\tTreeElementUtility.ListToTree(list);\n\t\t\t}\n\t\t\tcatch (Exception)\n\t\t\t{\n\t\t\t\tcatchedException = true;\n\t\t\t}\n\n\t\t\t// Assert\n\t\t\tAssert.IsTrue(catchedException, \"We require the root.depth to be -1, here it is: \" + list[0].depth);\n\t\t\n\t\t}\n\n\t\t[Test]\n\t\tpublic static void FindCommonAncestorsWithinListWorks()\n\t\t{\n\t\t\t// Arrange\n\t\t\tvar list = new List<TestElement>();\n\t\t\tlist.Add(new TestElement(\"root\", -1));\n\t\t\tlist.Add(new TestElement(\"A\", 0));\n\t\t\tvar b0 = new TestElement(\"B\", 0);\n\t\t\tvar b1 = new TestElement(\"Bchild\", 1);\n\t\t\tvar b2 = new TestElement(\"Bchildchild\", 2);\n\t\t\tlist.Add(b0);\n\t\t\tlist.Add(b1);\n\t\t\tlist.Add(b2);\n\n\t\t\tvar c0 = new TestElement (\"C\", 0);\n\t\t\tlist.Add(c0);\n\t\t\n\t\t\tvar f0 = new TestElement(\"F\", 0);\n\t\t\tvar f1 = new TestElement(\"Fchild\", 1);\n\t\t\tvar f2 = new TestElement(\"Fchildchild\", 2);\n\t\t\tlist.Add(f0);\n\t\t\tlist.Add(f1);\n\t\t\tlist.Add(f2);\n\t\t\n\t\t\t// Init tree structure: set children and parent properties\n\t\t\tTreeElementUtility.ListToTree(list);\n\n\t\n\t\t\t// Single element\n\t\t\tTestElement[] input = {b1};\n\t\t\tTestElement[] expectedResult = {b1};\n\t\t\tvar result = TreeElementUtility.FindCommonAncestorsWithinList(input).ToArray();\n\t\t\tAssert.IsTrue(ArrayUtility.ArrayEquals(expectedResult, result), \"Single input should return single output\");\n\n\t\t\t// Single sub tree\n\t\t\tinput = new[] {b1, b2};\n\t\t\texpectedResult = new[] {b1};\n\t\t\tresult = TreeElementUtility.FindCommonAncestorsWithinList (input).ToArray ();\n\t\t\tAssert.IsTrue(ArrayUtility.ArrayEquals(expectedResult, result), \"Common ancestor should only be b1 \");\n\n\t\t\t// Multiple sub trees\n\t\t\tinput = new[] { b0, b2, f0, f2, c0 };\n\t\t\texpectedResult = new[] { b0, f0, c0 };\n\t\t\tresult = TreeElementUtility.FindCommonAncestorsWithinList(input).ToArray();\n\t\t\tAssert.IsTrue(ArrayUtility.ArrayEquals(expectedResult, result), \"Common ancestor should only be b0, f0, c0\");\n\t\t}\n\n\t\t#endregion\t\n\t}\n\n\n}\n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/TreeElementUtility.cs.meta",
    "content": "fileFormatVersion: 2\nguid: fd65e8f324e17a344a97ddcf5a8d89d2\ntimeCreated: 1471616285\nlicenseType: Pro\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/TreeModel.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing NUnit.Framework;\n\n\nnamespace UnityAssetAuditor\n{\n\t// The TreeModel is a utility class working on a list of serializable TreeElements where the order and the depth of each TreeElement define\n\t// the tree structure. Note that the TreeModel itself is not serializable (in Unity we are currently limited to serializing lists/arrays) but the \n\t// input list is.\n\t// The tree representation (parent and children references) are then build internally using TreeElementUtility.ListToTree (using depth \n\t// values of the elements). \n\t// The first element of the input list is required to have depth == -1 (the hiddenroot) and the rest to have\n\t// depth >= 0 (otherwise an exception will be thrown)\n\n\tpublic class TreeModel<T> where T : TreeElement\n\t{\n\t\tIList<T> m_Data;\n\t\tT m_Root;\n\t\tint m_MaxID;\n\t\n\t\tpublic T root { get { return m_Root; } set { m_Root = value; } }\n\t\tpublic event Action modelChanged;\n\t\tpublic int numberOfDataElements\n\t\t{\n\t\t\tget { return m_Data.Count; }\n\t\t}\n\n\t\tpublic TreeModel (IList<T> data)\n\t\t{\n\t\t\tSetData (data);\n\t\t}\n\n\t\tpublic T Find (int id)\n\t\t{\n\t\t\treturn m_Data.FirstOrDefault (element => element.id == id);\n\t\t}\n\t\n\t\tpublic void SetData (IList<T> data)\n\t\t{\n\t\t\tInit (data);\n\t\t}\n\n\t\tvoid Init (IList<T> data)\n\t\t{\n\t\t\tif (data == null)\n\t\t\t\tthrow new ArgumentNullException(\"data\", \"Input data is null. Ensure input is a non-null list.\");\n\n\t\t\tm_Data = data;\n\t\t\tif (m_Data.Count > 0)\n\t\t\t\tm_Root = TreeElementUtility.ListToTree(data);\n\n\t\t\tm_MaxID = m_Data.Max(e => e.id);\n\t\t}\n\n\t\tpublic int GenerateUniqueID ()\n\t\t{\n\t\t\treturn ++m_MaxID;\n\t\t}\n\n\t\tpublic IList<int> GetAncestors (int id)\n\t\t{\n\t\t\tvar parents = new List<int>();\n\t\t\tTreeElement T = Find(id);\n\t\t\tif (T != null)\n\t\t\t{\n\t\t\t\twhile (T.parent != null)\n\t\t\t\t{\n\t\t\t\t\tparents.Add(T.parent.id);\n\t\t\t\t\tT = T.parent;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn parents;\n\t\t}\n\n\t\tpublic IList<int> GetDescendantsThatHaveChildren (int id)\n\t\t{\n\t\t\tT searchFromThis = Find(id);\n\t\t\tif (searchFromThis != null)\n\t\t\t{\n\t\t\t\treturn GetParentsBelowStackBased(searchFromThis);\n\t\t\t}\n\t\t\treturn new List<int>();\n\t\t}\n\n\t\tIList<int> GetParentsBelowStackBased(TreeElement searchFromThis)\n\t\t{\n\t\t\tStack<TreeElement> stack = new Stack<TreeElement>();\n\t\t\tstack.Push(searchFromThis);\n\n\t\t\tvar parentsBelow = new List<int>();\n\t\t\twhile (stack.Count > 0)\n\t\t\t{\n\t\t\t\tTreeElement current = stack.Pop();\n\t\t\t\tif (current.hasChildren)\n\t\t\t\t{\n\t\t\t\t\tparentsBelow.Add(current.id);\n\t\t\t\t\tforeach (var T in current.children)\n\t\t\t\t\t{\n\t\t\t\t\t\tstack.Push(T);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn parentsBelow;\n\t\t}\n\n\t\tpublic void RemoveElements (IList<int> elementIDs)\n\t\t{\n\t\t\tIList<T> elements = m_Data.Where (element => elementIDs.Contains (element.id)).ToArray ();\n\t\t\tRemoveElements (elements);\n\t\t}\n\n\t\tpublic void RemoveElements (IList<T> elements)\n\t\t{\n\t\t\tforeach (var element in elements)\n\t\t\t\tif (element == m_Root)\n\t\t\t\t\tthrow new ArgumentException(\"It is not allowed to remove the root element\");\n\t\t\n\t\t\tvar commonAncestors = TreeElementUtility.FindCommonAncestorsWithinList (elements);\n\n\t\t\tforeach (var element in commonAncestors)\n\t\t\t{\n\t\t\t\telement.parent.children.Remove (element);\n\t\t\t\telement.parent = null;\n\t\t\t}\n\n\t\t\tTreeElementUtility.TreeToList(m_Root, m_Data);\n\n\t\t\tChanged();\n\t\t}\n\n\t\tpublic void AddElements (IList<T> elements, TreeElement parent, int insertPosition)\n\t\t{\n\t\t\tif (elements == null)\n\t\t\t\tthrow new ArgumentNullException(\"elements\", \"elements is null\");\n\t\t\tif (elements.Count == 0)\n\t\t\t\tthrow new ArgumentNullException(\"elements\", \"elements Count is 0: nothing to add\");\n\t\t\tif (parent == null)\n\t\t\t\tthrow new ArgumentNullException(\"parent\", \"parent is null\");\n\n\t\t\tif (parent.children == null)\n\t\t\t\tparent.children = new List<TreeElement>();\n\n\t\t\tparent.children.InsertRange(insertPosition, elements.Cast<TreeElement> ());\n\t\t\tforeach (var element in elements)\n\t\t\t{\n\t\t\t\telement.parent = parent;\n\t\t\t\telement.depth = parent.depth + 1;\n\t\t\t\tTreeElementUtility.UpdateDepthValues(element);\n\t\t\t}\n\n\t\t\tTreeElementUtility.TreeToList(m_Root, m_Data);\n\n\t\t\tChanged();\n\t\t}\n\n\t\tpublic void AddRoot (T root)\n\t\t{\n\t\t\tif (root == null)\n\t\t\t\tthrow new ArgumentNullException(\"root\", \"root is null\");\n\n\t\t\tif (m_Data == null)\n\t\t\t\tthrow new InvalidOperationException(\"Internal Error: data list is null\");\n\n\t\t\tif (m_Data.Count != 0)\n\t\t\t\tthrow new InvalidOperationException(\"AddRoot is only allowed on empty data list\");\n\n\t\t\troot.id = GenerateUniqueID ();\n\t\t\troot.depth = -1;\n\t\t\tm_Data.Add (root);\n\t\t}\n\n\t\tpublic void AddElement (T element, TreeElement parent, int insertPosition)\n\t\t{\n\t\t\tif (element == null)\n\t\t\t\tthrow new ArgumentNullException(\"element\", \"element is null\");\n\t\t\tif (parent == null)\n\t\t\t\tthrow new ArgumentNullException(\"parent\", \"parent is null\");\n\t\t\n\t\t\tif (parent.children == null)\n\t\t\t\tparent.children = new List<TreeElement> ();\n\n\t\t\tparent.children.Insert (insertPosition, element);\n\t\t\telement.parent = parent;\n\n\t\t\tTreeElementUtility.UpdateDepthValues(parent);\n\t\t\tTreeElementUtility.TreeToList(m_Root, m_Data);\n\n\t\t\tChanged ();\n\t\t}\n\n\t\tpublic void MoveElements(TreeElement parentElement, int insertionIndex, List<TreeElement> elements)\n\t\t{\n\t\t\tif (insertionIndex < 0)\n\t\t\t\tthrow new ArgumentException(\"Invalid input: insertionIndex is -1, client needs to decide what index elements should be reparented at\");\n\n\t\t\t// Invalid reparenting input\n\t\t\tif (parentElement == null)\n\t\t\t\treturn;\n\n\t\t\t// We are moving items so we adjust the insertion index to accomodate that any items above the insertion index is removed before inserting\n\t\t\tif (insertionIndex > 0)\n\t\t\t\tinsertionIndex -= parentElement.children.GetRange(0, insertionIndex).Count(elements.Contains);\n\n\t\t\t// Remove draggedItems from their parents\n\t\t\tforeach (var draggedItem in elements)\n\t\t\t{\n\t\t\t\tdraggedItem.parent.children.Remove(draggedItem);\t// remove from old parent\n\t\t\t\tdraggedItem.parent = parentElement;\t\t\t\t\t// set new parent\n\t\t\t} \n\n\t\t\tif (parentElement.children == null)\n\t\t\t\tparentElement.children = new List<TreeElement>();\n\n\t\t\t// Insert dragged items under new parent\n\t\t\tparentElement.children.InsertRange(insertionIndex, elements);\n\n\t\t\tTreeElementUtility.UpdateDepthValues (root);\n\t\t\tTreeElementUtility.TreeToList (m_Root, m_Data);\n\n\t\t\tChanged ();\n\t\t}\n\n\t\tvoid Changed ()\n\t\t{\n\t\t\tif (modelChanged != null)\n\t\t\t\tmodelChanged ();\n\t\t}\n\t}\n\n\n\t#region Tests\n\tclass TreeModelTests\n\t{\n\t\t[Test]\n\t\tpublic static void TestTreeModelCanAddElements()\n\t\t{\n\t\t\tvar root = new TreeElement {name = \"Root\", depth = -1};\n\t\t\tvar listOfElements = new List<TreeElement>();\n\t\t\tlistOfElements.Add(root);\n\n\t\t\tvar model = new TreeModel<TreeElement>(listOfElements);\n\t\t\tmodel.AddElement(new TreeElement { name = \"Element\"  }, root, 0);\n\t\t\tmodel.AddElement(new TreeElement { name = \"Element \" + root.children.Count }, root, 0);\n\t\t\tmodel.AddElement(new TreeElement { name = \"Element \" + root.children.Count }, root, 0);\n\t\t\tmodel.AddElement(new TreeElement { name = \"Sub Element\" }, root.children[1], 0);\n\n\t\t\t// Assert order is correct\n\t\t\tstring[] namesInCorrectOrder = { \"Root\", \"Element 2\", \"Element 1\", \"Sub Element\", \"Element\" };\n\t\t\tAssert.AreEqual(namesInCorrectOrder.Length, listOfElements.Count, \"Result count does not match\");\n\t\t\tfor (int i = 0; i < namesInCorrectOrder.Length; ++i)\n\t\t\t\tAssert.AreEqual(namesInCorrectOrder[i], listOfElements[i].name);\n\n\t\t\t// Assert depths are valid\n\t\t\tTreeElementUtility.ValidateDepthValues(listOfElements);\n\t\t}\n\t\n\t\t[Test]\n\t\tpublic static void TestTreeModelCanRemoveElements()\n\t\t{\n\t\t\tvar root = new TreeElement { name = \"Root\", depth = -1 };\n\t\t\tvar listOfElements = new List<TreeElement>();\n\t\t\tlistOfElements.Add(root);\n\n\t\t\tvar model = new TreeModel<TreeElement>(listOfElements);\n\t\t\tmodel.AddElement(new TreeElement { name = \"Element\"  }, root, 0);\n\t\t\tmodel.AddElement(new TreeElement { name = \"Element \" + root.children.Count }, root, 0);\n\t\t\tmodel.AddElement(new TreeElement { name = \"Element \" + root.children.Count }, root, 0);\n\t\t\tmodel.AddElement(new TreeElement { name = \"Sub Element\" }, root.children[1], 0);\n\n\t\t\tmodel.RemoveElements(new[] { root.children[1].children[0], root.children[1] });\n\n\t\t\t// Assert order is correct\n\t\t\tstring[] namesInCorrectOrder = { \"Root\", \"Element 2\", \"Element\" };\n\t\t\tAssert.AreEqual(namesInCorrectOrder.Length, listOfElements.Count, \"Result count does not match\");\n\t\t\tfor (int i = 0; i < namesInCorrectOrder.Length; ++i)\n\t\t\t\tAssert.AreEqual(namesInCorrectOrder[i], listOfElements[i].name);\n\n\t\t\t// Assert depths are valid\n\t\t\tTreeElementUtility.ValidateDepthValues(listOfElements);\n\t\t}\n\t}\n\n\t#endregion\n\n}\n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/TreeModel.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 6f9fab1cf2636a6439c644bf08108abb\ntimeCreated: 1472122507\nlicenseType: Pro\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/TreeViewWithTreeModel.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\n\n\nnamespace UnityAssetAuditor\n{\n\n\tinternal class TreeViewItem<T> : TreeViewItem where T : TreeElement\n\t{\n\t\tpublic T data { get; set; }\n\n\t\tpublic TreeViewItem (int id, int depth, string displayName, T data) : base (id, depth, displayName)\n\t\t{\n\t\t\tthis.data = data;\n\t\t}\n\t}\n\n\tpublic class TreeViewWithTreeModel<T> : TreeView where T : TreeElement\n\t{\n\t\tTreeModel<T> m_TreeModel;\n\t\treadonly List<TreeViewItem> m_Rows = new List<TreeViewItem>(100);\n\t\tpublic event Action treeChanged;\n\n\t\tpublic TreeModel<T> treeModel { get { return m_TreeModel; } }\n\t\tpublic event Action<IList<TreeViewItem>>  beforeDroppingDraggedItems;\n\n\n\t\tpublic TreeViewWithTreeModel (TreeViewState state, TreeModel<T> model) : base (state)\n\t\t{\n\t\t\tInit (model);\n\t\t}\n\n\t\tpublic TreeViewWithTreeModel (TreeViewState state, MultiColumnHeader multiColumnHeader, TreeModel<T> model)\n\t\t\t: base(state, multiColumnHeader)\n\t\t{\n\t\t\tInit (model);\n\t\t}\n\n\t\tvoid Init (TreeModel<T> model)\n\t\t{\n\t\t\tm_TreeModel = model;\n\t\t\tm_TreeModel.modelChanged += ModelChanged;\n\t\t}\n\n\t\tvoid ModelChanged ()\n\t\t{\n\t\t\tif (treeChanged != null)\n\t\t\t\ttreeChanged ();\n\n\t\t\tReload ();\n\t\t}\n\n\t\tprotected override TreeViewItem BuildRoot()\n\t\t{\n\t\t\tint depthForHiddenRoot = -1;\n\t\t\treturn new TreeViewItem(m_TreeModel.root.id, depthForHiddenRoot, m_TreeModel.root.name);\n\t\t}\n\n\t\tprotected override IList<TreeViewItem> BuildRows (TreeViewItem root)\n\t\t{\n\t\t\tif (m_TreeModel.root == null)\n\t\t\t{\n\t\t\t\tDebug.LogError (\"tree model root is null. did you call SetData()?\");\n\t\t\t}\n\n\t\t\tm_Rows.Clear ();\n\t\t\tif (!string.IsNullOrEmpty(searchString))\n\t\t\t{\n\t\t\t\tSearch (m_TreeModel.root, searchString, m_Rows);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (m_TreeModel.root.hasChildren)\n\t\t\t\t\tAddChildrenRecursive(m_TreeModel.root, 0, m_Rows);\n\t\t\t}\n\n\t\t\t// We still need to setup the child parent information for the rows since this \n\t\t\t// information is used by the TreeView internal logic (navigation, dragging etc)\n\t\t\tSetupParentsAndChildrenFromDepths (root, m_Rows);\n\n\t\t\treturn m_Rows;\n\t\t}\n\n\t\tvoid AddChildrenRecursive (T parent, int depth, IList<TreeViewItem> newRows)\n\t\t{\n\t\t\tforeach (T child in parent.children)\n\t\t\t{\n\t\t\t\tvar item = new TreeViewItem<T>(child.id, depth, child.name, child);\n\t\t\t\tnewRows.Add(item);\n\n\t\t\t\tif (child.hasChildren)\n\t\t\t\t{\n\t\t\t\t\tif (IsExpanded(child.id))\n\t\t\t\t\t{\n\t\t\t\t\t\tAddChildrenRecursive (child, depth + 1, newRows);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\titem.children = CreateChildListForCollapsedParent();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvoid Search(T searchFromThis, string search, List<TreeViewItem> result)\n\t\t{\n\t\t\tif (string.IsNullOrEmpty(search))\n\t\t\t\tthrow new ArgumentException(\"Invalid search: cannot be null or empty\", \"search\");\n\n\t\t\tconst int kItemDepth = 0; // tree is flattened when searching\n\n\t\t\tStack<T> stack = new Stack<T>();\n\t\t\tforeach (var element in searchFromThis.children)\n\t\t\t\tstack.Push((T)element);\n\t\t\twhile (stack.Count > 0)\n\t\t\t{\n\t\t\t\tT current = stack.Pop();\n\t\t\t\t// Matches search?\n\t\t\t\tif (current.name.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0)\n\t\t\t\t{\n\t\t\t\t\tresult.Add(new TreeViewItem<T>(current.id, kItemDepth, current.name, current));\n\t\t\t\t}\n\n\t\t\t\tif (current.children != null && current.children.Count > 0)\n\t\t\t\t{\n\t\t\t\t\tforeach (var element in current.children)\n\t\t\t\t\t{\n\t\t\t\t\t\tstack.Push((T)element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tSortSearchResult(result);\n\t\t}\n\n\t\tprotected virtual void SortSearchResult (List<TreeViewItem> rows)\n\t\t{\n\t\t\trows.Sort (); // sort by displayName by default, can be overriden for multicolumn solutions\n\t\t}\n\t\n\t\tprotected override IList<int> GetAncestors (int id)\n\t\t{\n\t\t\treturn m_TreeModel.GetAncestors(id);\n\t\t}\n\n\t\tprotected override IList<int> GetDescendantsThatHaveChildren (int id)\n\t\t{\n\t\t\treturn m_TreeModel.GetDescendantsThatHaveChildren(id);\n\t\t}\n\n\n\t\t// Dragging\n\t\t//-----------\n\t\n\t\tconst string k_GenericDragID = \"GenericDragColumnDragging\";\n\n\t\tprotected override bool CanStartDrag (CanStartDragArgs args)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\n\t\tprotected override void SetupDragAndDrop(SetupDragAndDropArgs args)\n\t\t{\n\t\t\tif (hasSearch)\n\t\t\t\treturn;\n\n\t\t\tDragAndDrop.PrepareStartDrag();\n\t\t\tvar draggedRows = GetRows().Where(item => args.draggedItemIDs.Contains(item.id)).ToList();\n\t\t\tDragAndDrop.SetGenericData(k_GenericDragID, draggedRows);\n\t\t\tDragAndDrop.objectReferences = new UnityEngine.Object[] { }; // this IS required for dragging to work\n\t\t\tstring title = draggedRows.Count == 1 ? draggedRows[0].displayName : \"< Multiple >\";\n\t\t\tDragAndDrop.StartDrag (title);\n\t\t}\n\n\t\tprotected override DragAndDropVisualMode HandleDragAndDrop (DragAndDropArgs args)\n\t\t{\n\t\t\t// Check if we can handle the current drag data (could be dragged in from other areas/windows in the editor)\n\t\t\tvar draggedRows = DragAndDrop.GetGenericData(k_GenericDragID) as List<TreeViewItem>;\n\t\t\tif (draggedRows == null)\n\t\t\t\treturn DragAndDropVisualMode.None;\n\n\t\t\t// Parent item is null when dragging outside any tree view items.\n\t\t\tswitch (args.dragAndDropPosition)\n\t\t\t{\n\t\t\t\tcase DragAndDropPosition.UponItem:\n\t\t\t\tcase DragAndDropPosition.BetweenItems:\n\t\t\t\t\t{\n\t\t\t\t\t\tbool validDrag = ValidDrag(args.parentItem, draggedRows);\n\t\t\t\t\t\tif (args.performDrop && validDrag)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tT parentData = ((TreeViewItem<T>)args.parentItem).data;\n\t\t\t\t\t\t\tOnDropDraggedElementsAtIndex(draggedRows, parentData, args.insertAtIndex == -1 ? 0 : args.insertAtIndex);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn validDrag ? DragAndDropVisualMode.Move : DragAndDropVisualMode.None;\n\t\t\t\t\t}\n\n\t\t\t\tcase DragAndDropPosition.OutsideItems:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (args.performDrop)\n\t\t\t\t\t\t\tOnDropDraggedElementsAtIndex(draggedRows, m_TreeModel.root, m_TreeModel.root.children.Count);\n\n\t\t\t\t\t\treturn DragAndDropVisualMode.Move;\n\t\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tDebug.LogError(\"Unhandled enum \" + args.dragAndDropPosition);\n\t\t\t\t\treturn DragAndDropVisualMode.None;\n\t\t\t}\n\t\t}\n\n\t\tpublic virtual void OnDropDraggedElementsAtIndex (List<TreeViewItem> draggedRows, T parent, int insertIndex)\n\t\t{\n\t\t\tif (beforeDroppingDraggedItems != null)\n\t\t\t\tbeforeDroppingDraggedItems (draggedRows);\n\n\t\t\tvar draggedElements = new List<TreeElement> ();\n\t\t\tforeach (var x in draggedRows)\n\t\t\t\tdraggedElements.Add (((TreeViewItem<T>) x).data);\n\t\t\n\t\t\tvar selectedIDs = draggedElements.Select (x => x.id).ToArray();\n\t\t\tm_TreeModel.MoveElements (parent, insertIndex, draggedElements);\n\t\t\tSetSelection(selectedIDs, TreeViewSelectionOptions.RevealAndFrame);\n\t\t}\n\n\n\t\tbool ValidDrag(TreeViewItem parent, List<TreeViewItem> draggedItems)\n\t\t{\n\t\t\tTreeViewItem currentParent = parent;\n\t\t\twhile (currentParent != null)\n\t\t\t{\n\t\t\t\tif (draggedItems.Contains(currentParent))\n\t\t\t\t\treturn false;\n\t\t\t\tcurrentParent = currentParent.parent;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\n\t}\n\n}\n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts/TreeViewWithTreeModel.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 68fe63fd42552e7418aac450b41b8afb\ntimeCreated: 1472481611\nlicenseType: Pro\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Scripts.meta",
    "content": "fileFormatVersion: 2\nguid: d8004df83cf28884ab8e34a091ddd853\nfolderAsset: yes\ntimeCreated: 1481588073\nlicenseType: Pro\nDefaultImporter:\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Texture/DefaultTexture.jpg.meta",
    "content": "fileFormatVersion: 2\nguid: e762cc062d5c5411a9264437e5c9c09e\ntimeCreated: 1502701589\nlicenseType: Pro\nTextureImporter:\n  fileIDToRecycleName: {}\n  serializedVersion: 4\n  mipmaps:\n    mipMapMode: 0\n    enableMipMap: 1\n    sRGBTexture: 1\n    linearTexture: 0\n    fadeOut: 0\n    borderMipMap: 0\n    mipMapsPreserveCoverage: 0\n    alphaTestReferenceValue: 0.5\n    mipMapFadeDistanceStart: 1\n    mipMapFadeDistanceEnd: 3\n  bumpmap:\n    convertToNormalMap: 0\n    externalNormalMap: 0\n    heightScale: 0.25\n    normalMapFilter: 0\n  isReadable: 0\n  grayScaleToAlpha: 0\n  generateCubemap: 6\n  cubemapConvolution: 0\n  seamlessCubemap: 0\n  textureFormat: 1\n  maxTextureSize: 2048\n  textureSettings:\n    serializedVersion: 2\n    filterMode: -1\n    aniso: -1\n    mipBias: -1\n    wrapU: -1\n    wrapV: -1\n    wrapW: -1\n  nPOTScale: 1\n  lightmap: 0\n  compressionQuality: 50\n  spriteMode: 0\n  spriteExtrude: 1\n  spriteMeshType: 1\n  alignment: 0\n  spritePivot: {x: 0.5, y: 0.5}\n  spriteBorder: {x: 0, y: 0, z: 0, w: 0}\n  spritePixelsToUnits: 100\n  alphaUsage: 1\n  alphaIsTransparency: 0\n  spriteTessellationDetail: -1\n  textureType: 0\n  textureShape: 1\n  maxTextureSizeSet: 0\n  compressionQualitySet: 0\n  textureFormatSet: 0\n  platformSettings:\n  - buildTarget: DefaultTexturePlatform\n    maxTextureSize: 2048\n    textureFormat: -1\n    textureCompression: 1\n    compressionQuality: 50\n    crunchedCompression: 0\n    allowsAlphaSplitting: 0\n    overridden: 0\n  spriteSheet:\n    serializedVersion: 2\n    sprites: []\n    outline: []\n    physicsShape: []\n  spritePackingTag: \n  userData: '{\"RuleName\":\"nromalmaps\",\"WildCardMatchType\":0,\"WildCard\":\"nrm\",\"AssetGuid\":\"0bc6347fd6d584af3ab1a06182982dad\",\"assetType\":0}'\n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor/Texture.meta",
    "content": "fileFormatVersion: 2\nguid: 2e33a099c182b4826a46f527b242a2cd\nfolderAsset: yes\ntimeCreated: 1502705399\nlicenseType: Pro\nDefaultImporter:\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor/AssetAuditor.meta",
    "content": "fileFormatVersion: 2\nguid: 36d6f139a16b47a469947e0afd23b31d\nfolderAsset: yes\ntimeCreated: 1479437964\nlicenseType: Pro\nDefaultImporter:\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Editor.meta",
    "content": "fileFormatVersion: 2\nguid: fa69737d10241b54391c55189b99b9c6\nfolderAsset: yes\ntimeCreated: 1440440842\nlicenseType: Pro\nDefaultImporter:\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "LICENSE",
    "content": "MIT X11\n\nCopyright (C) 2017 Unity Technologies ApS\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL UNITY TECHNOLOGIES APS OR ANY OF ITS AFFILIATES (“UNITY”) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the “Unity” name/mark shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Unity.\n"
  },
  {
    "path": "README.md",
    "content": "# Asset Auditor\n\nThe asset auditor tool is designed to allow you to create sets of rules for the import settings for your assets in a Unity project and fix any assets that do not comply to those rules. \n\n#### The new audit rule window. \nThis window allows you to create a new rule for you assets. \n\n**Rule Name** - The first step is to give the rule a name. This can be whatever you desire it to be and will be name given to the proxy/dummy asset stored in the project. The reason for using a proxy/dummy assets is to provide a full inspector for the asset so that you modify the settings properties in a familiar manner to modify any other asset in\nyour project. \n\n**Wild Card Matching Type** - The wild card matching type has two options. \n\n**Name Contains** - Name contains works by matching the providing string to any of the asset names in the project that are of the same asset type as the asset rule. So If you set the name contains string to \"nrm\" on texture based rule.  Any texture asset that has nrm in the name will be found by the rule when inspecting in audit view.\n\n**Regex** - This work the same as name contains but uses full regex pattern matching. N.B. This is C# regex so there is no need for start and end /\n\n**Wild Card** - This is the string that is used in the Wild Card Matching Type for finding assets that the rule should effect. \n\n**Selective Mode** - This lets you create a rule that will only overwrite certain settings from a drop down The drop down enabling selective mode creates allows you to add as many selective element as you like and selectwhich rules you would like to override from it. \n\n**Rule Type** - This determines what assets the rule should affect. Currently there are three supported asset types. Texture, for all your imported textures, Model, for all your imported models and Audio for the imported audio files. \n\n\nDuring the creation of the rule new audit rule window will display a list of the assets that will be found by that rule so you can preview your results.\n\n#### Audit View\nThe audit view allows you to see the assets that the rule wild card will cover and apply the desired import settings to if desired. It also allows for modification of the wildcard property in case of naming convention changes. \n\n**Rule** - this is a drop down list of the available rules in the project. \n\n**Wild Card** - This can be used to modify the wild card that has been supplied to original rule. \n\n**Selective** - A drop down showing the properties that will be overriden. \n\n**Search bar** - This allows for searching of the the assets that are in the tree view. \n\n**Tree view** - This shows the subset of the project view that contains the assets that the rule has found through its search based on the wild card and wild card matching type.\n\n**Tool Bar** - This contains three options\n\n**Expand all** - This expands every element in the tree view\n\n**Collapse all** - This collapses the entire tree view\n\n**Fix all**- This fixes every asset that has been found to not match rules import settings. \n\n\n\n## In Development\nImprovements to selective mode.\nUI improvements. \nFolder level overrides. \n\n"
  }
]