2026-04-30 그린빈 추가

This commit is contained in:
2026-04-30 12:55:27 +09:00
parent b03f1b3e56
commit 2cc46ebea6
147 changed files with 31909 additions and 5 deletions

Binary file not shown.

View File

@@ -51,5 +51,6 @@ public enum ProductGroup
None,
ChocoBar,
PotatoChip,
GreenBeans,
}
}

View File

@@ -57,7 +57,7 @@ public void Show(ItemData data)
if (hasDiscount)
{
if (_discountPriceText != null) _discountPriceText.text = FormatPrice(data.FinalPrice);
if (_discountRateText != null) _discountRateText.text = $"-{Mathf.RoundToInt(data.DiscountRate * 100f)}%";
if (_discountRateText != null) _discountRateText.text = $"{Mathf.RoundToInt(data.DiscountRate * 100f)}";
}
_root.SetActive(true);

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3768d0f9519980b4b8c0f62966a56ab0
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 736a87880695f4d47b1c732083f04582
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4152f82672157b240a0eb0b802584254
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e9e109fb49381c540b4a5108479c269e
folderAsset: yes
timeCreated: 1626271522
licenseType: Store
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 078b33d3bbdbd3f478bca270510b58aa
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/DOTS/EasyDOTSDocumentation.pdf
uploadId: 885904

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 28e4c31123bcd614b910d5cfe5c82e2e
folderAsset: yes
timeCreated: 1626290231
licenseType: Store
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
#if (UNITY_EDITOR)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace ECE
{
// This is just the empty class that get's overwritten to add DOTS support.
// This make it much simpler for future updates to also work with DOTS as
// the only thing it does is convert the colliders through the UI Button.
// by having the same class with required method, we don't need to adjust
// other scripts each update.
public class EasyColliderDOTS
{
public void OnInspectorGUI(EasyColliderEditor Editor) { }
}
}
#endif

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: a8ac46b819edd88459956fa0b4832ff7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/DOTS/Scripts/EasyColliderDOTS.cs
uploadId: 885904

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: b04cc4b7e03f58f46a6bd2a7b3fe4498
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/EasyColliderEditorDocumentation.pdf
uploadId: 885904

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 723d55ae3f9555c42bcd3edb401a4613
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: e998347e00b1629449691174d6ce75de
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 82ac149ea221fb545a0fb56f2203b797
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUIBox32.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: 480816d7d5b863f42984e0a47484f216
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: e7eeee5780c59014ea4b310dbd384852
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUIBox32Merge.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: 1b9402ac744555345b9f6111ff8c4b8a
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: ec9b94295078e8e4989339a3c3f2c388
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUICapsule32.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: 0ad3709299b6f5e44a2db34afc52ccd4
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: f27b277bd5d034d4097d222005f63399
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUICapsule32Merge.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: 53b9b7a941c40804b8179b13ecf40b09
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: eaf3439ed7ce6624ca3aba5a5563f408
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUIConvexMesh32.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: b0c31ecbc9bd28e4e8ac1e5e43ba307e
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 15c81a624ef7f0a46ac5c566730ebca8
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUIConvexMesh32Merge.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: ccbaf976cae4b064f9a918823e8f6552
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 4674b33d58a9a5d45b39418124f53ac9
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUICylinder32.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: 2d782a0c73983ee4b95417abf7be42ef
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 6d9f9948f75eff44b8243fe5f1bc1a83
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUICylinder32Merge.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: 06f5537b1554be7429d39076a339a6e9
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 43dba5d881a539c46b514427a4041b89
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUIRotatedBox32.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: 9759e644c16116c46ad7d928f57b00be
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 1fbf28e7ef18a624b882903ec37cf195
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUIRotatedBox32Merge.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: b909a7c899938ca4d8c9705a045fe410
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: b586c269269556a418cca90db1e955c1
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUIRotatedCapsule32.png
uploadId: 885904

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: 764a526c991bd194cbfc2f4319b1d8dc
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: fa24b5ba62ace4d47990cefe71a46da7
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUIRotatedCapsule32Merge.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: e01e5ee2b0ff2214196190f59f373bac
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 50086ebfa2f74a447b9f73bcb4ebf480
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUISphere32.png
uploadId: 885904

Binary file not shown.

View File

@@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: 950da02c7c566da49bd0785d2f903f0f
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 76f0a0b7288f5c940b9cd55cb702ba24
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Icons/ECEUISphereMerge32.png
uploadId: 885904

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e652979cf9e1eac4e90f77a15a69ff0c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 45eb3a409ea753b44ab3bb6b8585be07
timeCreated: 1591641873
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderAutoSkinned.cs
uploadId: 885904

View File

@@ -0,0 +1,97 @@
using System.Collections.Generic;
using UnityEngine;
namespace ECE
{
[System.Serializable]
/// <summary>
/// Class to hold data for a skinned meshes' bones
/// Used because the bones transform array can be empty in cases where optimize gameobjects is used on import
/// The bindbose index of a bone, is the same as a bone's boneindex, so boneweight's can still be used.
/// </summary>
public class EasyColliderAutoSkinnedBone
{
public SkinnedMeshRenderer renderer;
/// <summary>
/// Create a collider for this bone?
/// </summary>
public bool Enabled = true;
/// <summary>
/// What kind of collider to create.
/// </summary>
public SKINNED_MESH_COLLIDER_TYPE ColliderType = SKINNED_MESH_COLLIDER_TYPE.Box;
/// <summary>
/// Minimum skinning bone weight to include a vertex in the bone's collider calculations.
/// </summary>
public float BoneWeight = 0.5f;
/// <summary>
/// Bone's display name (transform.name)
/// </summary>
public string BoneName = "Default";
/// <summary>
/// Is this bone paired with another bone?
/// </summary>
public bool IsPaired = false;
/// <summary>
/// If this bone is paired, is this the bone that is displayed in the UI?
/// </summary>
public bool IsPairDisplayBone = false;
/// <summary>
/// Is this bone valid? (Has at least 1 vertex that meets it's boneWeight)
/// </summary>
public bool IsValid = false;
public EasyColliderAutoSkinnedBone(Matrix4x4 bp, int index, Transform t)
{
BoneIndex = index;
BindPose = bp;
Transform = t;
}
/// <summary>
/// Local to world matrix of the bone's transform.
/// </summary>
public Matrix4x4 Matrix;
/// <summary>
/// Bind pose of the bone
/// </summary>
public Matrix4x4 BindPose;
/// <summary>
/// Bind pose index is the bone index as well.
/// </summary>
public int BoneIndex;
/// <summary>
/// Transform of the bone
/// </summary>
public Transform Transform;
/// <summary>
/// List of vertices in world space for this bo
/// </summary>
/// <typeparam name="Vector3"></typeparam>
/// <returns></returns>
public List<Vector3> WorldSpaceVertices = new List<Vector3>();
[SerializeField]
/// <summary>
/// List of other bone's index's in the BoneList that this bone is paired with.
/// </summary>
/// <typeparam name="int"></typeparam>
/// <returns></returns>
public List<int> PairedBones = new List<int>();
/// <summary>
/// Collider for this bone.
/// </summary>
public Collider Collider;
/// <summary>
/// Indent level of this bone when displaying in UI.
/// </summary>
public int IndentLevel = -1;
}
}

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 22d8868ad24ea0c43828e22314004216
timeCreated: 1625687084
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderAutoSkinnedBone.cs
uploadId: 885904

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 241873a664ee81d418528c165ef0dd12
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderCreator.cs
uploadId: 885904

View File

@@ -0,0 +1,125 @@
using UnityEngine;
namespace ECE
{
/// <summary>
/// Data holder for collider calculations.
/// </summary>
public class EasyColliderData
{
/// <summary>
/// Type of collider data
/// </summary>
public CREATE_COLLIDER_TYPE ColliderType;
/// <summary>
/// Did the collider calculation complete
/// </summary>
public bool IsValid = false;
/// <summary>
/// TRS matrix of the attach to object, or TRS matrix of what the rotated collider will have
/// </summary>
public Matrix4x4 Matrix;
public void Clone(EasyColliderData data)
{
this.ColliderType = data.ColliderType;
this.IsValid = data.IsValid;
this.Matrix = data.Matrix;
}
}
/// <summary>
/// Data for creating a sphere collider
/// </summary>
public class SphereColliderData : EasyColliderData
{
/// <summary>
/// Radius of the collider
/// </summary>
public float Radius;
/// <summary>
/// Center of the collider
/// </summary>
public Vector3 Center;
public void Clone(SphereColliderData data)
{
base.Clone(data);
this.Radius = data.Radius;
this.Center = data.Center;
}
}
/// <summary>
/// Data for creating a capsule collider
/// </summary>
public class CapsuleColliderData : SphereColliderData
{
/// <summary>
/// Direction of the capsule collider
/// </summary>
public int Direction;
/// <summary>
/// Height of the capsule collider
/// </summary>
public float Height;
public void Clone(CapsuleColliderData data)
{
base.Clone(data);
this.Direction = data.Direction;
this.Height = data.Height;
}
}
/// <summary>
/// Data for creating a box collider
/// </summary>
public class BoxColliderData : EasyColliderData
{
/// <summary>
/// Center of the box collider
/// </summary>
public Vector3 Center;
/// <summary>
/// Size of the box collider
/// </summary>
public Vector3 Size;
public void Clone(BoxColliderData data)
{
base.Clone(data);
this.Center = data.Center;
this.Size = data.Size;
this.Matrix = data.Matrix;
}
public override string ToString()
{
return "Rotated box collider. Center:" + Center.ToString() + " Size:" + Size.ToString();
}
}
/// <summary>
/// Data for creating a mesh collider
/// </summary>
public class MeshColliderData : EasyColliderData
{
/// <summary>
/// Mesh of the convex mesh collider
/// </summary>
public Mesh ConvexMesh;
public void Clone(MeshColliderData data)
{
base.Clone(data);
this.ConvexMesh = data.ConvexMesh;
}
}
}

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: f703485b98da54c489209f1fd7ad2db9
timeCreated: 1593006697
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderData.cs
uploadId: 885904

View File

@@ -0,0 +1,160 @@
#if (UNITY_EDITOR)
using UnityEngine;
using UnityEditor;
namespace ECE
{
public static class EasyColliderDraw
{
/// <summary>
/// Draws a box
/// </summary>
/// <param name="transform">Transform of the box</param>
/// <param name="center">Center of the box in local space</param>
/// <param name="halfSize">Half the size of the box</param>
/// <param name="color">Color of lines used to draw the box</param>
private static void DrawBox(Transform transform, Vector3 center, Vector3 halfSize, Color color)
{
Vector3 p1 = transform.TransformPoint(center + halfSize);
Vector3 p2 = transform.TransformPoint(center - halfSize);
Vector3 p3 = transform.TransformPoint(center + new Vector3(halfSize.x, halfSize.y, -halfSize.z));
Vector3 p4 = transform.TransformPoint(center + new Vector3(halfSize.x, -halfSize.y, halfSize.z));
Vector3 p5 = transform.TransformPoint(center + new Vector3(halfSize.x, -halfSize.y, -halfSize.z));
Vector3 p6 = transform.TransformPoint(center + new Vector3(-halfSize.x, halfSize.y, halfSize.z));
Vector3 p7 = transform.TransformPoint(center + new Vector3(-halfSize.x, -halfSize.y, halfSize.z));
Vector3 p8 = transform.TransformPoint(center + new Vector3(-halfSize.x, halfSize.y, -halfSize.z));
Handles.color = color;
Handles.DrawLine(p1, p3);
Handles.DrawLine(p1, p4);
Handles.DrawLine(p1, p6);
Handles.DrawLine(p8, p3);
Handles.DrawLine(p8, p6);
Handles.DrawLine(p8, p2);
Handles.DrawLine(p7, p6);
Handles.DrawLine(p7, p2);
Handles.DrawLine(p7, p4);
Handles.DrawLine(p5, p4);
Handles.DrawLine(p5, p2);
Handles.DrawLine(p5, p3);
}
/// <summary>
/// Draws a box collider
/// </summary>
/// <param name="boxCollider">Box collider to draw</param>
/// <param name="color">Color of lines used to draw</param>
private static void DrawBoxCollider(BoxCollider boxCollider, Color color)
{
DrawBox(boxCollider.transform, boxCollider.center, boxCollider.size / 2, color);
}
private static EasyColliderPreviewer previewer;
public static EasyColliderPreviewer Previewer
{
get
{
if (previewer == null)
{
previewer = ScriptableObject.CreateInstance<EasyColliderPreviewer>();
}
return previewer;
}
}
/// <summary>
/// Draws a capsule collider
/// </summary>
/// <param name="capsuleCollider">Capsule collider to draw</param>
/// <param name="color">Color of lines to draw</param>
private static void DrawCapsuleCollider(CapsuleCollider capsuleCollider, Color color)
{
CapsuleColliderData data = new CapsuleColliderData();
data.ColliderType = CREATE_COLLIDER_TYPE.CAPSULE;
data.Height = capsuleCollider.height;
data.Radius = capsuleCollider.radius;
data.Center = capsuleCollider.center;
data.Direction = capsuleCollider.direction;
data.Matrix = capsuleCollider.transform.localToWorldMatrix;
Previewer.DrawCapsuleCollider(data, color);
return;
}
/// <summary>
/// Draws a primitive collider (box, sphere, capsule) using lines.
/// </summary>
/// <param name="collider">Collider to draw</param>
/// <param name="color">Color of lines to draw with</param>
public static void DrawCollider(Collider collider, Color color)
{
if (collider == null) return;
if (collider is BoxCollider)
{
DrawBoxCollider(collider as BoxCollider, color);
}
else if (collider is SphereCollider)
{
DrawSphereCollider(collider as SphereCollider, color);
}
else if (collider is CapsuleCollider)
{
DrawCapsuleCollider(collider as CapsuleCollider, color);
}
else if (collider is MeshCollider)
{
DrawMeshCollider(collider as MeshCollider, color);
}
}
/// <summary>
/// Shader used to draw mesh colliders.
/// </summary>
static Shader MeshColliderShader;
/// <summary>
/// Draws a mesh collider by drawing lines connecting it's meshs vertices.
/// </summary>
/// <param name="collider">Mesh Collider</param>
/// <param name="color">Color to draw lines with</param>
private static void DrawMeshCollider(MeshCollider collider, Color color)
{
// try to find mesh collider.
if (MeshColliderShader == null)
{
MeshColliderShader = Shader.Find("Custom/EasyColliderMeshColliderPreview");
}
// if we have the shader, draw it using the wireframe and the color
if (MeshColliderShader != null && collider != null && collider.sharedMesh != null)
{
Material wireMat = new Material(MeshColliderShader);
wireMat.SetColor("_Color", color);
wireMat.SetPass(0);
GL.wireframe = true;
Graphics.DrawMeshNow(collider.sharedMesh, collider.transform.localToWorldMatrix);
GL.wireframe = false;
}
else
{
// no shader? fall back to old draw box method.
DrawBox(collider.transform, collider.transform.InverseTransformPoint(collider.bounds.center), collider.transform.InverseTransformVector(collider.bounds.extents), color);
}
}
// Draws a sphere collider, taken from previous version
/// <summary>
/// Draws a sphere collider.
/// </summary>
/// <param name="sphereCollider">Sphere collider to draw</param>
/// <param name="color">Color of lines used to draw</param>
private static void DrawSphereCollider(SphereCollider sphereCollider, Color color)
{
SphereColliderData data = new SphereColliderData();
data.ColliderType = CREATE_COLLIDER_TYPE.SPHERE;
data.Center = sphereCollider.center;
data.Radius = sphereCollider.radius;
data.Matrix = sphereCollider.transform.localToWorldMatrix;
Previewer.DrawSphereCollider(data, color);
}
}
}
#endif

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 3c95b61c7ebb7b14e9688b95552cef80
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderDraw.cs
uploadId: 885904

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8765d9c9fa7824d4da8e37f5cc1913fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderEditor.cs
uploadId: 885904

View File

@@ -0,0 +1,158 @@
namespace ECE
{
public enum NORMAL_OFFSET
{
Out,
In,
Both,
}
/// <summary>
/// Capsule method to use when creating a capsule
/// </summary>
public enum CAPSULE_COLLIDER_METHOD
{
BestFit,
MinMax,
MinMaxPlusRadius,
MinMaxPlusDiameter,
}
/// <summary>
/// Type of collider to create
/// </summary>
public enum CREATE_COLLIDER_TYPE
{
BOX,
ROTATED_BOX,
SPHERE,
CAPSULE,
ROTATED_CAPSULE,
CONVEX_MESH,
CYLINDER,
}
/// <summary>
/// Orientation of collider
/// </summary>
public enum COLLIDER_ORIENTATION
{
NORMAL,
ROTATED,
}
public enum CYLINDER_ORIENTATION
{
Automatic,
LocalX,
LocalY,
LocalZ
}
/// <summary>
/// Enum for spheres ot cubes when drawing gizmos
/// </summary>
public enum GIZMO_TYPE
{
CUBE,
SPHERE,
}
/// <summary>
/// enum for Shaders or Gizmos to draw vertices with.
/// </summary>
public enum RENDER_POINT_TYPE
{
SHADER,
GIZMOS,
}
/// <summary>
/// Collider type to use when automatically generating colliders along a bone chain for a skinned mesh renderer.
/// </summary>
public enum SKINNED_MESH_COLLIDER_TYPE
{
Box,
Capsule,
Sphere,
Convex_Mesh,
}
public enum SKINNED_MESH_DEPENETRATE_ORDER
{
InOrder,
Reverse,
InsideOut,
OutsideIn,
}
/// <summary>
/// Sphere method to use when creating a sphere
/// </summary>
public enum SPHERE_COLLIDER_METHOD
{
BestFit,
Distance,
MinMax,
}
public enum VHACD_CONVERSION
{
None,
Boxes,
Spheres,
Capsules,
}
public enum MESH_COLLIDER_METHOD
{
QuickHull,
MessyHull
}
public enum VERTEX_SNAP_METHOD
{
Add,
Remove,
Both,
}
/// <summary>
/// Method used to attach mesh colliders to the attach to object.
/// </summary>
public enum VHACD_RESULT_METHOD
{
AttachTo,
ChildObject,
IndividualChildObjects
}
/// <summary>
/// Current window tab selected in the editor window.
/// </summary>
public enum ECE_WINDOW_TAB
{
None = -1,
Creation = 0,
Editing = 1,
VHACD = 2,
AutoSkinned = 3,
}
public enum COLLIDER_HOLDER
{
Default,
Once,
Always
}
public enum CONVEX_HULL_SAVE_METHOD
{
Prefab,
Mesh,
PrefabMesh,
MeshPrefab,
Folder,
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: d3013554ca157424db48970772ea240c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderEnums.cs
uploadId: 885904

View File

@@ -0,0 +1,185 @@
#if (UNITY_EDITOR)
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace ECE
{
/// <summary>
/// Used to draw gizmos for selected / hovered vertices
/// Gizmos draw significantly faster than handles.
/// </summary>
[System.Serializable]
public class EasyColliderGizmos : MonoBehaviour, ISerializationCallbackReceiver
{
#region preference settings
private EasyColliderPreferences ECEPreferences
{
get { return EasyColliderPreferences.Preferences; }
}
public float CommonScale { get { return ECEPreferences.CommonScalingMultiplier; } }
public float DefaultScale { get { return ECEPreferences.DefaultScale; } }
public bool DisplayAllVertices { get { return ECEPreferences.DisplayAllVertices; } }
public Color DisplayVertexColor { get { return ECEPreferences.DisplayVerticesColour; } }
public GIZMO_TYPE GizmoType { get { return ECEPreferences.GizmoType; } }
public Color HoveredVertexColor { get { return ECEPreferences.HoverVertColour; } }
public Color OverlapVertexColor { get { return ECEPreferences.OverlapSelectedVertColour; } }
public Color SelectedVertexColor { get { return ECEPreferences.SelectedVertColour; } }
public bool UseFixedGizmoScale { get { return ECEPreferences.UseFixedGizmoScale; } }
#endregion
/// <summary>
/// calculated density scale if use density scale is enabled.
/// </summary>
public float DensityScale = 0.0f;
/// <summary>
/// List of all valid vertex positions in world space
/// </summary>
public HashSet<Vector3> DisplayVertexPositions = new HashSet<Vector3>();
/// <summary>
/// Should gizmos be drawn
/// </summary>
public bool DrawGizmos = true;
/// <summary>
/// Set of hovered vertices in world space
/// </summary>
public HashSet<Vector3> HoveredVertexPositions = new HashSet<Vector3>();
/// <summary>
/// Set of selected vertices in world space
/// </summary>
public HashSet<Vector3> SelectedVertexPositions = new HashSet<Vector3>();
float GetScale()
{
// *10 makes it more equivalent to how the shader is drawn.
float scale = DefaultScale * CommonScale * 10;
if (scale <= 0.0f)
{
scale = ECEPreferences.DefaultScale * 10;
}
return scale;
}
void OnDrawGizmos()
{
if (DrawGizmos)
{
// Keep track of gizmos color to reset at end
Color original = Gizmos.color;
// Selected vertices.
// scale for spheres.
float scale = GetScale();
// size for cubes
Vector3 size = Vector3.one * scale;
// default scaling of 1.0f
float handleSize = 1.0f;
// Display all vertices.
if (DisplayAllVertices)
{
Gizmos.color = DisplayVertexColor;
foreach (Vector3 vert in DisplayVertexPositions)
{
if (UseFixedGizmoScale)
{
handleSize = HandleUtility.GetHandleSize(vert);
}
DrawAGizmo(vert, size * handleSize, scale * handleSize, GizmoType);
}
}
// Selected vertices
Gizmos.color = SelectedVertexColor;
foreach (Vector3 vert in SelectedVertexPositions)
{
if (UseFixedGizmoScale)
{
handleSize = HandleUtility.GetHandleSize(vert);
}
DrawAGizmo(vert, size * handleSize, scale * handleSize, GizmoType);
}
// Hover vertices.
Gizmos.color = HoveredVertexColor;
foreach (Vector3 vert in HoveredVertexPositions)
{
if (SelectedVertexPositions.Contains(vert))
{
if (UseFixedGizmoScale)
{
handleSize = HandleUtility.GetHandleSize(vert);
}
Gizmos.color = OverlapVertexColor;
DrawAGizmo(vert, size * handleSize, scale * handleSize, GizmoType);
}
else
{
if (UseFixedGizmoScale)
{
handleSize = HandleUtility.GetHandleSize(vert);
}
Gizmos.color = HoveredVertexColor;
DrawAGizmo(vert, size * handleSize, scale * handleSize, GizmoType);
}
}
Gizmos.color = original;
}
}
/// <summary>
/// Draws a gizmo of type at position at size or scale.
/// </summary>
/// <param name="position">World position to draw at</param>
/// <param name="size">Size of cube to draw</param>
/// <param name="scale">Radius of sphere to draw</param>
/// <param name="gizmoType">Sphere or Cubes?</param>
private void DrawAGizmo(Vector3 position, Vector3 size, float scale, GIZMO_TYPE gizmoType)
{
switch (gizmoType)
{
case GIZMO_TYPE.SPHERE:
Gizmos.DrawSphere(position, scale / 2);
break;
case GIZMO_TYPE.CUBE:
Gizmos.DrawCube(position, size);
break;
}
}
/// <summary>
/// Sets the set of selected vertices from a list of selected world vertices
/// </summary>
/// <param name="worldVertices">List of world vertex positions that are selected</param>
public void SetSelectedVertices(List<Vector3> worldVertices)
{
SelectedVertexPositions.Clear();
SelectedVertexPositions.UnionWith(worldVertices);
}
public List<Vector3> SerializedDisplayVertexPositions = new List<Vector3>();
public List<Vector3> SerializedHoveredVertexPositions = new List<Vector3>();
public List<Vector3> SerializedSelectedVertexPositions = new List<Vector3>();
public void OnBeforeSerialize()
{
SerializedDisplayVertexPositions.AddRange(DisplayVertexPositions);
SerializedHoveredVertexPositions.AddRange(HoveredVertexPositions);
SerializedSelectedVertexPositions.AddRange(SelectedVertexPositions);
}
public void OnAfterDeserialize()
{
DisplayVertexPositions.UnionWith(SerializedDisplayVertexPositions);
HoveredVertexPositions.UnionWith(SerializedHoveredVertexPositions);
SelectedVertexPositions.UnionWith(SerializedSelectedVertexPositions);
}
}
}
#endif

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 7302dd3862f934949a13c03008aba827
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderGizmos.cs
uploadId: 885904

View File

@@ -0,0 +1,55 @@
using UnityEngine;
namespace ECE
{
public class EasyColliderPostProccessor : IEasyColliderPostProcessor
{
// The default implementation does nothing.
// Can be used to add your own code if you want to do something specifically to each type of collider.
// If you're creating colliders at runtime with EasyColliderCreator, you can also set the post processor through code,
// if you don't it will by default use this implementation
// NOTE: this happens for every single collider created in this asset / created by EasyColliderCreator
// Vertex selected created colliders, merged colliders, auto skinned colliders, vhacd colliders all go through these methods.
/// <summary>
/// post processes a box collider, properties orientation indiciates if it's a rotated collider.
/// </summary>
/// <param name="box"></param>
/// <param name="properties"></param>
public void PostProcessCollider(BoxCollider boxCollider, EasyColliderProperties properties)
{
// in here you'll get passed a completely generated box collider, and can do whatever you want with it.
}
/// <summary>
/// post processes a capsule collider, properties orientation indiciates if it's a rotated collider.
/// </summary>
/// <param name="box"></param>
/// <param name="properties"></param>
public void PostProcessCollider(CapsuleCollider capsuleCollider, EasyColliderProperties properties)
{
// in here you'll get passed a completely generated capsule collider, and can do whatever you want with it.
}
/// <summary>
/// post processes a sphere collider
/// </summary>
/// <param name="box"></param>
/// <param name="properties"></param>
public void PostProcessCollider(SphereCollider sphereCollider, EasyColliderProperties properties)
{
// in here you'll get passed a completely generated sphere collider, and can do whatever you want with it.
}
/// <summary>
/// post processes a mesh collider. cylinder colliders are mesh colliders as well.
/// </summary>
/// <param name="box"></param>
/// <param name="properties"></param>
public void PostProcessCollider(MeshCollider meshCollider, EasyColliderProperties properties)
{
// in here you'll get passed a completely generated mesh collider, and can do whatever you want with it.
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: c4635610932a87342a4bf2e41e9ab050
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderPostProccessor.cs
uploadId: 885904

View File

@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 99d3a08e9dc280246aa61e99c233b0c0
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderPreferences.asset
uploadId: 885904

View File

@@ -0,0 +1,615 @@
#if (UNITY_EDITOR)
using UnityEngine;
using UnityEditor;
using System.IO;
namespace ECE
{
[System.Serializable]
public class EasyColliderPreferences : ScriptableObject
{
/// <summary>
/// Currently set vhacd parameters.
/// </summary>
[SerializeField] private VHACDParameters _VHACDParameters;
public VHACDParameters VHACDParameters
{
get
{
if (_VHACDParameters == null)
{
_VHACDParameters = new VHACDParameters();
}
return _VHACDParameters;
}
set { _VHACDParameters = value; }
}
/// <summary>
/// Float to convert to vhacd parameters resolution using 2^Value for UI Slider when advanced parameters is expanded
/// </summary>
[SerializeField] public float VHACDResFloat = 12.97f;
/// <summary>
/// Resets vhacd parameters to default.
/// </summary>
public void VHACDSetDefaultParameters()
{
VHACDParameters = new VHACDParameters();
}
/// <summary>
/// When enabled, selecting objects in the background of the scene view can be done with a single click even when an object is currently selected for collider creation.
/// </summary>
[SerializeField] public bool AllowBackgroundSelection;
/// <summary>
/// when enabled, allows convex hulls used in mesh colliders to be saved in Packages folder.
/// THESE FILES ARE NOT SHARED WITH JUST THE PROJECT. MUST BE HANDLED BY YOUR TEAM. MUST ALSO SHARE SOURCE PACKAGES FOLDERS
/// </summary>
[SerializeField] public bool AllowSavingConvexHullsInPackages;
/// <summary>
/// When entering prefab mode, should we automatically select the root object?
/// </summary>
[SerializeField] public bool AutoSelectOnPrefabOpen;
/// <summary>
/// Auto include child skinned meshes
/// </summary>
[SerializeField] public bool AutoIncludeChildSkinnedMeshes;
/// <summary>
/// Should we try to reduce the number of vertices in auto-skinned calculations for convex mesh colliders if the result ends up trying to create a collider that has >=256 triangles.
/// </summary>
[SerializeField] public bool AutoSkinnedForce256Triangles;
/// <summary>
/// The minimum weight for a vertex to be included in a bone's calculations.
/// </summary>
[SerializeField] public float AutoSkinnedMinBoneWeight;
/// <summary>
/// The angle of mis-alignedment above which we should create a better aligned child transform to hold colliders for skinned meshes.
/// </summary>
[SerializeField] public float AutoSkinnedMinRealignAngle;
/// <summary>
/// Should we allow transforms to be created that would better align the collider with the mesh than a mis-aligned bone?
/// </summary>
[SerializeField] public bool AutoSkinnedAllowRealign;
/// <summary>
/// Type of collider to use when auto generating skinned mesh colliders along a bone chain.
/// </summary>
[SerializeField] public SKINNED_MESH_COLLIDER_TYPE AutoSkinnedColliderType = SKINNED_MESH_COLLIDER_TYPE.Box;
/// <summary>
/// Should we be attempting to compute penetration and depenetrate the colliders on the skinned mesh?
/// </summary>
[SerializeField] public bool AutoSkinnedDepenetrate;
/// <summary>
/// Are we displaying with indentation?
/// </summary>
[SerializeField] public bool AutoSkinnedIndents = true;
/// <summary>
/// number of times to run depenetration methods before stopping.
/// </summary>
[SerializeField] public int AutoSkinnedIterativeDepenetrationCount = 15;
/// <summary>
/// Are we displaying with paired bones?
/// </summary>
[SerializeField] public bool AutoSkinnedPairing = true;
/// <summary>
/// Are we using per-bone settings
/// </summary>
[SerializeField] public bool AutoSkinnedPerBoneSettings;
/// <summary>
/// Amount of collider shrinking (along the various shift's) to do before trying to shift depenetrate.
/// </summary>
[SerializeField] public float AutoSkinnedShrinkAmount = 0.5f;
[Tooltip("Enables using bone position distances during pairing of bones. (AutoSkinnedPairedDistanceDelta controls the distance when enabled.")]
[SerializeField] public bool AutoSkinnedUseDistanceDeltaPairing = true;
[Tooltip("Max distance difference between possible bone pairs to still be considered as a pair. Checked along with length of child bone-chain.")]
[SerializeField] public float AutoSkinnedPairedDistanceDelta = 0.01f;
/// <summary>
/// The way we should sort the bone list in auto-skinned.
/// </summary>
[SerializeField] public SKINNED_MESH_DEPENETRATE_ORDER AutoSkinnedDepenetrateOrder;
/// <summary>
/// Key to hold before box selection to only add vertices in the box.
/// </summary>
[SerializeField] public KeyCode BoxSelectPlusKey;
/// <summary>
/// Key to hold before box selection to only remove vertices in the box.
/// </summary>
[SerializeField] public KeyCode BoxSelectMinusKey;
/// <summary>
/// Capsule collider generation method to use when creating a capsule collider.
/// </summary>
[SerializeField] public CAPSULE_COLLIDER_METHOD CapsuleColliderMethod;
/// <summary>
/// when enabled, when generating multiple convex mesh colliders with vhacd, they are all combined and stored in a single asset file.
/// </summary>
[SerializeField] public bool CombinedVHACDColliders;
/// <summary>
/// A helpful common multiplier for all scales when using any scaling method.
/// </summary>
[SerializeField] public float CommonScalingMultiplier = 1.0f;
/// <summary>
/// should created meshes used in convex mesh colliders be read/write enabled
/// </summary>
[SerializeField] public bool ConvexMeshReadWriteEnabled = true;
[Tooltip("Default scale of the displayed boxes / gizmos around vertices. Combined with common scaling multiplier.")]
/// <summary>
/// Default scale of displayed vertices used along with the common scaling multiplier.
/// </summary>
[SerializeField] public float DefaultScale = 0.01f;
/// <summary>
/// scale for vertices that are hovered / will be added to the selected vertices
/// </summary>
[SerializeField] public float HoveredScaleMult = 1.0f;
/// <summary>
/// scale multiplier for vertices when using display all vertices
/// </summary>
[SerializeField] public float DisplayAllScaleMult = 1.0f;
/// <summary>
/// scale multiplier for vertices that will be removed from the selected vertices
/// </summary>
[SerializeField] public float OverlapScaleMult = 1.0f;
/// <summary>
/// scale multiplier for vertices that are currently selected.
/// </summary>
[SerializeField] public float SelectedScaleMult = 1.0f;
/// <summary>
/// The method to use when creating a collider: if and how a gameobject should be made to hold the collider.
/// </summary>
[SerializeField] public COLLIDER_HOLDER ColliderHolder = COLLIDER_HOLDER.Default;
/// <summary>
/// If true, puts rotated colliders on the same layer as the selected gameobject.
/// </summary>
[SerializeField] public bool CopyParentObjectLayer;
/// <summary>
/// key to press to create from the current preview.
/// </summary>
[SerializeField] public KeyCode CreateFromPreviewKey;
/// <summary>
/// For editor window tab tracking, maintains previously open tab.
/// </summary>
[SerializeField] public ECE_WINDOW_TAB CurrentWindowTab;
/// <summary>
/// Should cylinder orientation field apply to capsules as well.
/// </summary>
[SerializeField] public bool CylinderAsCapsuleOrientation = false;
/// <summary>
/// number of sides when creating a cylinder collider.
/// </summary>
[SerializeField] public int CylinderNumberOfSides = 16;
/// <summary>
/// Method to use to decide which axis a cylinder should be oriented on.
/// </summary>
[SerializeField] public CYLINDER_ORIENTATION CylinderOrientation;
/// <summary>
/// Offset in degrees when creating a cylinder.
/// </summary>
[SerializeField] public float CylinderRotationOffset = 0.0f;
/// <summary>
/// Should tips be displayed?
/// </summary>
[SerializeField] public bool DisplayTips;
/// <summary>
/// Should we display compute shader / gizmos on all the vertices?
/// </summary>
[SerializeField] public bool DisplayAllVertices;
/// <summary>
/// Display vertices colour
/// </summary>
[SerializeField] public Color DisplayVerticesColour;
[SerializeField] public bool EnableVertexToolsShortcuts = true;
/// <summary>
/// Type of gizmos to use when drawing gizmos for vertices
/// </summary>
public GIZMO_TYPE GizmoType;
/// <summary>
/// Hover vertices scaling colour
/// </summary>
[SerializeField] public Color HoverVertColour;
/// <summary>
/// Number of points to generate around a rounded portion of a collider like sphere or capsules
/// </summary>
[SerializeField] public int MergeCollidersRoundnessAccuracy = 10;
/// <summary>
/// Method to use when generating mesh colliders
/// </summary>
[SerializeField] public MESH_COLLIDER_METHOD MeshColliderMethod;
/// <summary>
/// Overlapped vertice scaling colour
/// </summary>
[SerializeField] public Color OverlapSelectedVertColour;
/// <summary>
/// Key used to select points (any point on a mesh that isn't a vertex)
/// </summary>
[SerializeField] public KeyCode PointSelectKeyCode;
[SerializeField] public bool PopupDialogOnFinish;
/// <summary>
/// Collider type we want to preview
/// </summary>
[SerializeField] public CREATE_COLLIDER_TYPE PreviewColliderType;
/// <summary>
/// Color of lines to draw previewed colliders with.
/// </summary>
[SerializeField] public Color PreviewDrawColor;
/// <summary>
/// Are previews enabled?
/// </summary>
[SerializeField] public bool PreviewEnabled;
/// <summary>
/// Raycast delay time, ie only check / select at increments of this time.
/// </summary>
[SerializeField] public float RaycastDelayTime;
/// <summary>
/// Render point method
/// </summary>
[SerializeField] public RENDER_POINT_TYPE RenderPointType;
/// <summary>
/// Should colliders that are merged together be removed after merging is completed?
/// </summary>
[SerializeField] public bool RemoveMergedColliders;
/// <summary>
/// Float that controls the amount an output collider's size should be increased or decreased, essentially scaling the output.
/// </summary>
[SerializeField] public float ShrinkGrow;
/// <summary>
/// Should the rotated colliders pivot be created at the center of the points, or at 0?
/// </summary>
[SerializeField] public bool RotatedColliderPivotAtCenter;
/// <summary>
/// Settings of the current rotate and duplicate section in collider creation.
/// </summary>
[SerializeField] public EasyColliderRotateDuplicate rotatedDupeSettings;
/// <summary>
/// When true, meshes created from creating convex hulls are saved as assets.
/// </summary>
[SerializeField] public bool SaveConvexHullAsAsset;
/// <summary>
/// Specifies how to search for a location to save the convex hull .asset files.
/// </summary>
[SerializeField] public CONVEX_HULL_SAVE_METHOD ConvexHullSaveMethod = CONVEX_HULL_SAVE_METHOD.PrefabMesh;
/// <summary>
/// if SaveConvexHullMeshAtSelected is false, saves at the path specified.
/// </summary>
[SerializeField] public string SaveConvexHullPath;
/// <summary>
/// Provides a subfolder to save colliders in an asset path when saving near the mesh
/// IE: if the mesh/prefab is found in an Environments/Meshes folder, an Environments/Meshes/ConvexHulls folder would be created to store the collision meshes
/// if using anything other than CONVEX_HULL_SAVE_METHOD.Folder
/// </summary>
[SerializeField] public string SaveConvexHullSubFolder;
/// <summary>
/// Suffix with which to save convex hulls.
/// </summary>
[SerializeField] public string SaveConvexHullSuffix;
/// <summary>
/// Selected vertice scaling colour
/// </summary>
[SerializeField] public Color SelectedVertColour;
[SerializeField] public KeyCode ShortcutInvert = KeyCode.I;
[SerializeField] public KeyCode ShortcutGrow = KeyCode.G;
[SerializeField] public KeyCode ShortcutGrowLast = KeyCode.L;
[SerializeField] public KeyCode ShortcutClear = KeyCode.C;
[SerializeField] public KeyCode ShortcutRing = KeyCode.R;
/// <summary>
/// Should the number of selected vertices be displayed in the ui?
/// </summary>
[SerializeField] public bool ShowSelectedVertexCount;
/// <summary>
/// Sphere method to use when creating a sphere collider.
/// </summary>
public SPHERE_COLLIDER_METHOD SphereColliderMethod;
/// <summary>
/// Should HandleUtility.GetHandleSize be used when using gizmos to draw to keep gizmo size constant regardless of distance to camera?
/// </summary>
[SerializeField] public bool UseFixedGizmoScale;
/// <summary>
/// Enables using left click to select vertices, and right click to select points.
/// </summary>
[SerializeField] public bool UseMouseClickSelection = true;
[SerializeField] public NORMAL_OFFSET VertexNormalOffsetType = NORMAL_OFFSET.Both;
/// <summary>
/// Amount to offset the vertex (in direction of it's averaged normal)
/// </summary>
[SerializeField] public float VertexNormalOffset = 0f;
/// <summary>
/// Amount to inset the vertex (in opposite direction of it's averaged normal)
/// </summary>
[SerializeField] public float VertexNormalInset = 0f;
/// <summary>
/// Method used when raycasting for closest vertices, add (only snap to unselected verts), remove (only snap to selected verts), both (default)
/// </summary>
[SerializeField] public VERTEX_SNAP_METHOD VertexSnapMethod;
/// <summary>
/// Key used to select vertices.
/// </summary>
[SerializeField] public KeyCode VertSelectKeyCode;
/// <summary>
/// Should we update the VHACD calculation and preview as parameters change?
/// </summary>
[SerializeField] public bool VHACDPreview;
/// <summary>
/// Sets all values to default values.
/// </summary>
public void SetDefaultValues()
{
#region VHACD settings
VHACDParameters = new VHACDParameters();
VHACDPreview = true;
#endregion
#region other settings
AutoIncludeChildSkinnedMeshes = true;
AutoSelectOnPrefabOpen = false;
DisplayTips = true;
DisplayAllVertices = false;
PopupDialogOnFinish = false;
PreviewEnabled = true;
RaycastDelayTime = 0.1f;
ShowSelectedVertexCount = false;
rotatedDupeSettings = new EasyColliderRotateDuplicate();
RotatedColliderPivotAtCenter = false;
CylinderAsCapsuleOrientation = false;
#endregion
#region autoskinned preferences
AutoSkinnedMinBoneWeight = 0.5f;
AutoSkinnedDepenetrate = false;
AutoSkinnedIterativeDepenetrationCount = 15;
AutoSkinnedPairing = true;
AutoSkinnedIndents = true;
AutoSkinnedColliderType = SKINNED_MESH_COLLIDER_TYPE.Box;
AutoSkinnedShrinkAmount = 0.5f;
// I find outside in to give the best results generally.
AutoSkinnedDepenetrateOrder = SKINNED_MESH_DEPENETRATE_ORDER.OutsideIn;
AutoSkinnedForce256Triangles = true;
AutoSkinnedUseDistanceDeltaPairing = true;
AutoSkinnedPairedDistanceDelta = 0.01f;
#endregion
#region inputs
// shifts do not work.
BoxSelectMinusKey = KeyCode.S;
BoxSelectPlusKey = KeyCode.A;
CreateFromPreviewKey = KeyCode.BackQuote;
PointSelectKeyCode = KeyCode.B;
UseMouseClickSelection = true;
VertSelectKeyCode = KeyCode.V;
EnableVertexToolsShortcuts = true;
ShortcutInvert = KeyCode.I;
ShortcutGrow = KeyCode.G;
ShortcutGrowLast = KeyCode.L;
ShortcutClear = KeyCode.C;
ShortcutRing = KeyCode.R;
#endregion
#region Collider Methods
CapsuleColliderMethod = CAPSULE_COLLIDER_METHOD.MinMax;
MeshColliderMethod = MESH_COLLIDER_METHOD.QuickHull;
PreviewColliderType = CREATE_COLLIDER_TYPE.BOX;
SphereColliderMethod = SPHERE_COLLIDER_METHOD.MinMax;
#endregion
#region Collider Settings / Paramaters
ShrinkGrow = 1f;
MergeCollidersRoundnessAccuracy = 10;
VertexNormalOffset = 0f;
VertexNormalInset = 0f;
VertexNormalOffsetType = NORMAL_OFFSET.Both;
ColliderHolder = COLLIDER_HOLDER.Default;
CylinderNumberOfSides = 16;
CylinderOrientation = CYLINDER_ORIENTATION.Automatic;
CylinderRotationOffset = 0.0f;
MeshColliderMethod = MESH_COLLIDER_METHOD.QuickHull;
RemoveMergedColliders = true;
CopyParentObjectLayer = true;
#endregion
#region drawing
CommonScalingMultiplier = 1.0f;
DefaultScale = 0.01f;
HoveredScaleMult = 1.0f;
DisplayAllScaleMult = 1.0f;
OverlapScaleMult = 1.0f;
SelectedScaleMult = 1.0f;
DisplayVerticesColour = Color.blue;
GizmoType = GIZMO_TYPE.SPHERE;
HoverVertColour = Color.cyan;
OverlapSelectedVertColour = Color.red;
PreviewDrawColor = Color.cyan;
if (SystemInfo.graphicsShaderLevel < 45)
{
RenderPointType = RENDER_POINT_TYPE.GIZMOS;
}
else
{
RenderPointType = RENDER_POINT_TYPE.SHADER;
}
SelectedVertColour = Color.green;
UseFixedGizmoScale = true;
#endregion
#region Save Convex Hull Settings
ConvexHullSaveMethod = CONVEX_HULL_SAVE_METHOD.PrefabMesh;
ResetDefaultSavePath();
SaveConvexHullAsAsset = true;
SaveConvexHullSuffix = "_ConvexHull_";
ConvexMeshReadWriteEnabled = true;
SaveConvexHullSubFolder = "";
#endregion
}
private static EasyColliderPreferences _Prefereneces;
public static EasyColliderPreferences Preferences
{
get
{
if (_Prefereneces == null)
{
// lazy load preferences when needed.
_Prefereneces = FindOrCreatePreferences();
}
return _Prefereneces;
}
}
private static EasyColliderPreferences FindOrCreatePreferences()
{
EasyColliderPreferences preferences;
string[] ecp = AssetDatabase.FindAssets("EasyColliderPreferences t:ScriptableObject");
string assetPath = "";
if (ecp.Length > 0)
{
assetPath = AssetDatabase.GUIDToAssetPath(ecp[0]);
if (ecp.Length > 1)
{
Debug.LogWarning("Easy Collider Editor has found multiple preferences files. Using the one located at " + assetPath);
}
preferences = AssetDatabase.LoadAssetAtPath(assetPath, typeof(EasyColliderPreferences)) as EasyColliderPreferences;
}
else
{
ecp = AssetDatabase.FindAssets("EasyColliderWindow t:script");
if (ecp.Length > 0)
{
assetPath = AssetDatabase.GUIDToAssetPath(ecp[0]);
if (ecp.Length > 1)
{
Debug.LogWarning("Easy Collider Editor has found multiple preferences files. Using the one located at " + assetPath);
}
}
// preferences = AssetDatabase.LoadAssetAtPath(assetPath, typeof(EasyColliderPreferences)) as EasyColliderPreferences;
// Create a new preferences file.
string prefPath = assetPath.Remove(assetPath.Length - 21) + "EasyColliderPreferences.asset";
preferences = CreateInstance<EasyColliderPreferences>();
preferences.SetDefaultValues();
AssetDatabase.CreateAsset(preferences, prefPath);
AssetDatabase.SaveAssets();
Debug.LogWarning("Easy Collider Editor did not find a preferences file, new preferences file created at " + prefPath);
}
return preferences;
}
static string defaultFolderName = "Convex Hulls";
/// <summary>
/// Resets the default save path to the location of the preferences scriptable object.
/// </summary>
public bool ResetDefaultSavePath()
{
// path to this preferences object.
SaveConvexHullPath = AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(this));
SaveConvexHullPath = SaveConvexHullPath.Remove(SaveConvexHullPath.LastIndexOf("/")) + "/";
string rootPath = SaveConvexHullPath.Remove(SaveConvexHullPath.LastIndexOf("/Scripts/"), 9);
// if the preferences is in soemthing other than Assets (like packages, create a new folder at the root to hold convex hulls)
if (!SaveConvexHullPath.StartsWith("Assets"))
{
if (!AssetDatabase.IsValidFolder("Assets/Convex Hulls"))
{
AssetDatabase.CreateFolder("Assets", "Convex Hulls");
AssetDatabase.Refresh();
Debug.LogWarning("A folder has been created at: Assets/Convex Hulls to save convex mesh collider assets because Easy Collider exists in the packages folder. Folder to save assets in can be changed in Easy Collider Editor's preferences foldout.");
}
SaveConvexHullPath = "Assets/Convex Hulls/";
return true;
}
// remove invalid characters.
SaveConvexHullPath = string.Join("", SaveConvexHullPath.Split(Path.GetInvalidPathChars()));
// try creating and saving a Convex Hull specific folder if it doesn't exist.
if (!AssetDatabase.IsValidFolder(rootPath + "/" + defaultFolderName))
{
AssetDatabase.CreateFolder(rootPath, defaultFolderName);
AssetDatabase.Refresh();
if (AssetDatabase.IsValidFolder(rootPath + "/" + defaultFolderName))
{
SaveConvexHullPath = rootPath + "/" + defaultFolderName + "/";
return true;
}
}
else
{
SaveConvexHullPath = rootPath + "/" + defaultFolderName + "/";
}
return false;
}
public int GetCreationValuesHashCode()
{
return 0;
}
}
}
#endif

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: fb5e4193615d8464a82ea935f90494a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderPreferences.cs
uploadId: 885904

View File

@@ -0,0 +1,714 @@
#if (UNITY_EDITOR)
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace ECE
{
/// <summary>
/// Scriptable object to preview colliders that would be created from the given points
/// </summary>
[System.Serializable]
public class EasyColliderPreviewer : ScriptableObject
{
/// <summary>
/// Current calculation method of the collider type we are using as an int
/// </summary>
public int CurrentMethod = 0;
/// <summary>
/// Current attach to transform used in the calculation
/// </summary>
public Transform CurrentAttachTo;
/// <summary>
/// Current vertex count for the last calculation we did for a preview
/// </summary>
public int CurrentVertexCount = 0;
public float CurrentShrinkGrow = 0;
/// <summary>
/// Current count of the nubmer of colliders selected for the last preview calculation.
/// </summary>
public int CurrentColliderCount = 0;
public float CurrentVertexNormalOffset = 0;
public float CurrentVertexNormalInset = 0;
public NORMAL_OFFSET CurrentNormalOffset;
/// <summary>
/// Color to draw the preview lines with
/// </summary>
public Color DrawColor = Color.cyan;
private EasyColliderCreator _ECC;
/// <summary>
/// Creator that calculates the colliders we use to preview.
/// </summary>
/// <value></value>
public EasyColliderCreator ECC
{
get
{
if (_ECC == null)
{
_ECC = new EasyColliderCreator();
}
return _ECC;
}
set { _ECC = value; }
}
/// <summary>
/// Shader used to draw mesh colliders.
/// </summary>
private Shader MeshColliderShader;
/// <summary>
/// All the data from the current preview calculation
/// </summary>
public EasyColliderData PreviewData;
public List<EasyColliderData> RotateAndDuplicateData = new List<EasyColliderData>();
public bool HasValidRotateAndDuplicateData()
{
if (RotateAndDuplicateData == null || RotateAndDuplicateData.Count == 0) return false;
foreach (EasyColliderData d in RotateAndDuplicateData)
{
if (!d.IsValid)
{
return false;
}
}
return true;
}
//TODO: integrate calculation of auto skinned into normal update-preview stuff.
public List<EasyColliderData> AutoSkinnedData = new List<EasyColliderData>();
/// <summary>
/// Preview data hides that rotated colliders are different "collider types" so this keeps track of that for updating the preview.
/// </summary>
public CREATE_COLLIDER_TYPE ActualColliderType;
public ECE_WINDOW_TAB CurrentPreviewTab;
#region DrawPreviews
/// <summary>
/// Draws a preview from the current preview data.
/// </summary>
private void DrawPreview()
{
if (RotateAndDuplicateData != null && RotateAndDuplicateData.Count > 0)
{
// Debug.Log("Rotate and duplicate preview");
DrawList(RotateAndDuplicateData);
}
else if (AutoSkinnedData != null && AutoSkinnedData.Count > 0)
{
// Debug.Log("Auto skinned preivew");
DrawList(AutoSkinnedData);
}
else
{
// make sure we have data, and it's valid.
if (PreviewData != null && PreviewData.IsValid)
{
// Draw based on the preview type.
switch (PreviewData.ColliderType)
{
case CREATE_COLLIDER_TYPE.BOX:
case CREATE_COLLIDER_TYPE.ROTATED_BOX:
DrawPreviewBox(PreviewData as BoxColliderData, DrawColor);
break;
case CREATE_COLLIDER_TYPE.SPHERE:
DrawPreviewSphere(PreviewData as SphereColliderData, DrawColor);
break;
case CREATE_COLLIDER_TYPE.CAPSULE:
case CREATE_COLLIDER_TYPE.ROTATED_CAPSULE:
DrawPreviewCapsule(PreviewData as CapsuleColliderData, DrawColor);
break;
case CREATE_COLLIDER_TYPE.CONVEX_MESH:
case CREATE_COLLIDER_TYPE.CYLINDER:
DrawPreviewConvexMesh(PreviewData as MeshColliderData, DrawColor);
break;
}
}
}
}
public void DrawList(List<EasyColliderData> data)
{
foreach (EasyColliderData PreviewData in data)
{
if (!PreviewData.IsValid) { continue; }
// Draw based on the preview type.
switch (PreviewData.ColliderType)
{
case CREATE_COLLIDER_TYPE.BOX:
case CREATE_COLLIDER_TYPE.ROTATED_BOX:
DrawPreviewBox(PreviewData as BoxColliderData, DrawColor);
break;
case CREATE_COLLIDER_TYPE.SPHERE:
DrawPreviewSphere(PreviewData as SphereColliderData, DrawColor);
break;
case CREATE_COLLIDER_TYPE.CAPSULE:
case CREATE_COLLIDER_TYPE.ROTATED_CAPSULE:
DrawPreviewCapsule(PreviewData as CapsuleColliderData, DrawColor);
break;
case CREATE_COLLIDER_TYPE.CONVEX_MESH:
case CREATE_COLLIDER_TYPE.CYLINDER:
DrawPreviewConvexMesh(PreviewData as MeshColliderData, DrawColor);
break;
}
}
}
/// <summary>
/// Draws a mesh collider preview
/// </summary>
/// <param name="data">Data from quickhull calculation</param>
private void DrawPreviewConvexMesh(MeshColliderData data, Color color)
{
// try to find mesh shader
if (MeshColliderShader == null)
{
MeshColliderShader = Shader.Find("Custom/EasyColliderMeshColliderPreview");
}
// if we have the shader, draw it using the wireframe and the color
if (MeshColliderShader != null && data.ConvexMesh != null)
{
Material wireMat = new Material(MeshColliderShader);
wireMat.SetColor("_Color", color);
wireMat.SetPass(0);
GL.wireframe = true;
Graphics.DrawMeshNow(data.ConvexMesh, data.Matrix);
GL.wireframe = false;
Graphics.DrawMeshNow(data.ConvexMesh, data.Matrix);
}
}
/// <summary>
/// Draws a box collider
/// </summary>
/// <param name="data">Data from box calculation</param>
private void DrawPreviewBox(BoxColliderData data, Color color)
{
// half size and center
Vector3 hs = data.Size / 2;
Vector3 c = data.Center;
// transform each point of the cube to world space with the transformation matrix
Vector3[] points = new Vector3[8]{
data.Matrix.MultiplyPoint3x4(c + hs),
data.Matrix.MultiplyPoint3x4(c + new Vector3(hs.x, hs.y, -hs.z)),
data.Matrix.MultiplyPoint3x4(c + new Vector3(hs.x, -hs.y, hs.z)),
data.Matrix.MultiplyPoint3x4(c + new Vector3(hs.x, -hs.y, -hs.z)),
data.Matrix.MultiplyPoint3x4(c + new Vector3(-hs.x, hs.y, hs.z)),
data.Matrix.MultiplyPoint3x4(c + new Vector3(-hs.x, hs.y, -hs.z)),
data.Matrix.MultiplyPoint3x4(c + new Vector3(-hs.x, -hs.y, hs.z)),
data.Matrix.MultiplyPoint3x4(c - hs)
};
// draw the lines connecting corners of the cube.
Handles.color = color;
Handles.DrawLine(points[0], points[1]);
Handles.DrawLine(points[0], points[2]);
Handles.DrawLine(points[0], points[4]);
Handles.DrawLine(points[7], points[5]);
Handles.DrawLine(points[7], points[6]);
Handles.DrawLine(points[7], points[3]);
Handles.DrawLine(points[1], points[5]);
Handles.DrawLine(points[1], points[3]);
Handles.DrawLine(points[2], points[6]);
Handles.DrawLine(points[2], points[3]);
Handles.DrawLine(points[4], points[5]);
Handles.DrawLine(points[4], points[6]);
}
public void DrawCapsuleCollider(CapsuleColliderData data, Color color)
{
DrawPreviewCapsule(data, color);
}
private void DrawPreviewCapsule(CapsuleColliderData data, Color color)
{
Handles.color = color;
// calculate top and bottom center sphere locations.
float offset = data.Height / 2;
Vector3 top, bottom = top = data.Center;
float radius = data.Radius;
#if (UNITY_2017_2_OR_NEWER)
Vector3 scale = data.Matrix.lossyScale;
#else
Vector3 scale = CurrentAttachTo.transform.lossyScale;
#endif
switch (data.Direction)
{
case 0: //x axis
//adjust radius by the bigger scale.
radius *= scale.y > scale.z ? scale.y : scale.z;
// adjust the offset to top and bottom mid points for spheres based on radius / scale in that direction
offset -= radius / scale.x;
// offset top and bottom points.
top.x += offset;
bottom.x -= offset;
break;
case 1:
radius *= scale.x > scale.z ? scale.x : scale.z;
offset -= radius / scale.y;
top.y += offset;
bottom.y -= offset;
break;
case 2:
radius *= scale.x > scale.y ? scale.x : scale.y;
offset -= radius / scale.z;
top.z += offset;
bottom.z -= offset;
break;
}
// dont know why mathf.approx wasn't working here, but the others don't work in rare cases. (top==bottom in this case works)
// which fixes issue where a preview would not be drawn in some extremely weird rare case.
if (data.Height < data.Radius * 2 || Mathf.Approximately(data.Height, data.Radius * 2) || top == bottom)
{
// draw just the sphere if the radius and the height will make a sphere.
Vector3 worldCenter = data.Matrix.MultiplyPoint(data.Center);
Handles.DrawWireDisc(worldCenter, Vector3.forward, radius);
Handles.DrawWireDisc(worldCenter, Vector3.right, radius);
Handles.DrawWireDisc(worldCenter, Vector3.up, radius);
return;
}
Vector3 worldTop = data.Matrix.MultiplyPoint3x4(top);
Vector3 worldBottom = data.Matrix.MultiplyPoint3x4(bottom);
Vector3 up = worldTop - worldBottom;
Vector3 cross1 = Vector3.up;
// dont want to cross if in same direction, forward works in this case as the first cross
if (up.normalized == cross1 || up.normalized == -cross1)
{
cross1 = Vector3.forward;
}
Vector3 right = Vector3.Cross(up, -cross1).normalized;
Vector3 forward = Vector3.Cross(up, -right).normalized;
// full circles at top and bottom
Handles.DrawWireDisc(worldTop, up, radius);
Handles.DrawWireDisc(worldBottom, up, radius);
// half arcs at top and bottom
Handles.DrawWireArc(worldTop, forward, right, 180f, radius);
Handles.DrawWireArc(worldTop, -right, forward, 180f, radius);
Handles.DrawWireArc(worldBottom, -forward, right, 180f, radius);
Handles.DrawWireArc(worldBottom, right, forward, 180f, radius);
// connect bottom and top side points
Handles.DrawLine(worldTop + right * radius, worldBottom + right * radius);
Handles.DrawLine(worldTop - right * radius, worldBottom - right * radius);
Handles.DrawLine(worldTop + forward * radius, worldBottom + forward * radius);
Handles.DrawLine(worldTop - forward * radius, worldBottom - forward * radius);
}
public void DrawSphereCollider(SphereColliderData data, Color color)
{
DrawPreviewSphere(data, color);
}
/// <summary>
/// Draws a sphere collider
/// </summary>
/// <param name="data">Data from sphere calculation</param>
private void DrawPreviewSphere(SphereColliderData data, Color color)
{
Handles.color = color;
Vector3 worldCenter = data.Matrix.MultiplyPoint3x4(data.Center);
// Draw all normal axis' rings at the world center location for both perspective and isometric/orthographic
float radius = data.Radius;
#if (UNITY_2017_2_OR_NEWER)
Vector3 scale = data.Matrix.lossyScale;
#else
Vector3 scale = CurrentAttachTo.transform.lossyScale;
#endif
float largestScale = Mathf.Max(Mathf.Max(scale.x, scale.y), scale.z);
radius *= largestScale;
Handles.DrawWireDisc(worldCenter, Vector3.forward, radius);
Handles.DrawWireDisc(worldCenter, Vector3.right, radius);
Handles.DrawWireDisc(worldCenter, Vector3.up, radius);
// orthographic camera
if (Camera.current != null)
{
if (Camera.current.orthographic)
{
// simple, use cameras forward in orthographic
Handles.DrawWireDisc(worldCenter, Camera.current.transform.forward, radius);
}
else
{
// draw a circle facing the camera covering all the radius in prespective mode
Vector3 normal = worldCenter - Handles.inverseMatrix.MultiplyPoint(Camera.current.transform.position);
float sqrMagnitude = normal.sqrMagnitude;
float r2 = radius * radius;
float r4m = r2 * r2 / sqrMagnitude;
float newRadius = Mathf.Sqrt(r2 - r4m);
Handles.DrawWireDisc(worldCenter - r2 * normal / sqrMagnitude, normal, newRadius);
}
}
}
#endregion
public void ClearPreview()
{
// PreviewData = new EasyColliderData();
PreviewData = null;
RotateAndDuplicateData = null;
AutoSkinnedData = null;
}
/// <summary>
/// Gets the method for the current preview collider type
/// </summary>
/// <param name="colliderType">type of collider we are previewing</param>
/// <returns>enum of method selected for collider type as an int</returns>
private int GetMethodForColliderPreviewType(EasyColliderPreferences preferences)
{
if (preferences.PreviewColliderType == CREATE_COLLIDER_TYPE.CAPSULE || preferences.PreviewColliderType == CREATE_COLLIDER_TYPE.ROTATED_CAPSULE)
{
return (int)preferences.CapsuleColliderMethod;
}
else if (preferences.PreviewColliderType == CREATE_COLLIDER_TYPE.SPHERE)
{
return (int)preferences.SphereColliderMethod;
}
else if (preferences.PreviewColliderType == CREATE_COLLIDER_TYPE.CONVEX_MESH)
{
return (int)preferences.MeshColliderMethod;
}
else if (preferences.PreviewColliderType == CREATE_COLLIDER_TYPE.CYLINDER)
{
return (int)preferences.CylinderNumberOfSides + (int)preferences.CylinderOrientation + ((int)preferences.CylinderRotationOffset * 1000);
}
else
{
return 0;
}
}
#region CalculatePreviews
/// <summary>
/// Calculates the preview data to be used to display.
/// </summary>
/// <param name="preferences">current preferences</param>
/// <param name="ece">current editor</param>
private void CalculatePreviewCollider(EasyColliderPreferences preferences, EasyColliderEditor ece)
{
// private void CalculatePreviewCollider(CREATE_COLLIDER_TYPE type, List<Vector3> worldVertices, List<Vector3> normals, GameObject attachTo, int method)
// CalculatePreviewCollider(preferences.PreviewColliderType, editor.GetWorldVertices(), editor.GetNormals(), editor.AttachToObject, GetMethodForColliderPreviewType(preferences));
List<Vector3> worldVertices = ece.GetWorldVertices(true);
switch (ActualColliderType)
{
case CREATE_COLLIDER_TYPE.BOX:
case CREATE_COLLIDER_TYPE.ROTATED_BOX:
PreviewData = ECC.CalculateBox(worldVertices, CurrentAttachTo.transform, ActualColliderType == CREATE_COLLIDER_TYPE.ROTATED_BOX, true);
break;
case CREATE_COLLIDER_TYPE.SPHERE:
PreviewData = CalculatePreviewSphere(worldVertices, CurrentAttachTo.transform, preferences.SphereColliderMethod);
break;
case CREATE_COLLIDER_TYPE.ROTATED_CAPSULE:
case CREATE_COLLIDER_TYPE.CAPSULE:
PreviewData = CalculatePreviewCapsule(worldVertices, CurrentAttachTo.transform, preferences.CapsuleColliderMethod, ActualColliderType == CREATE_COLLIDER_TYPE.ROTATED_CAPSULE);
break;
case CREATE_COLLIDER_TYPE.CONVEX_MESH:
PreviewData = CalculatePreviewMesh(worldVertices, ece.GetNormals(), CurrentAttachTo.transform, preferences.MeshColliderMethod);
break;
case CREATE_COLLIDER_TYPE.CYLINDER:
PreviewData = CalculatePreviewCylinder(worldVertices, CurrentAttachTo.transform);
break;
}
}
/// <summary>
/// Calculates the merge colliders preview data
/// </summary>
/// <param name="preferences">current preferences</param>
/// <param name="ece">current editor</param>
private void CalculatePreviewMerge(EasyColliderPreferences preferences, EasyColliderEditor ece)
{
// private void CalculatePreviewMerge(CREATE_COLLIDER_TYPE mergeTo, List<Collider> selectedColliders, GameObject attachTo, int method)
// CalculatePreviewMerge(preferences.PreviewColliderType, editor.SelectedColliders, editor.AttachToObject, GetMethodForColliderPreviewType(preferences));
if (CurrentColliderCount > 0)
{
PreviewData = ECC.MergeCollidersPreview(ece.SelectedColliders, preferences.PreviewColliderType, CurrentAttachTo);
}
else
{
PreviewData = new EasyColliderData();
}
}
/// <summary>
/// Calculates the rotate and duplicate preview data.
/// </summary>
/// <param name="preferences">current preferences</param>
/// <param name="ece">current editor</param>
private void CalculatePreviewRotateAndDuplicate(EasyColliderPreferences preferences, EasyColliderEditor ece)
{
if (ece.AttachToObject == null || ece.SelectedGameObject == null || preferences.rotatedDupeSettings.pivot == null) return;
RotateAndDuplicateData = ECC.CalculateRotateAndDuplicate(preferences, ece);
}
/// <summary>
/// Calculates a preview capsule
/// </summary>
/// <param name="worldVertices">world vertices used to calculate the collider</param>
/// <param name="attachTo">gameobject the collider will be attached to</param>
/// <param name="method">calculation method used to calculate the collider type as an int</param>
/// <param name="isRotated">will the collider be a rotated collider?</param>
/// <returns>Calculated capsule collider data</returns>
private EasyColliderData CalculatePreviewCapsule(List<Vector3> worldVertices, Transform attachTo, CAPSULE_COLLIDER_METHOD method, bool isRotated)
{
switch (method)
{
case CAPSULE_COLLIDER_METHOD.BestFit:
return ECC.CalculateCapsuleBestFit(worldVertices, attachTo, isRotated, true);
default:
return ECC.CalculateCapsuleMinMax(worldVertices, attachTo, method, isRotated, true);
}
}
/// <summary>
/// Calculates a preview cylinder
/// </summary>
/// <param name="worldVertices">world vertices used to calculate the collider</param>
/// <param name="attachTo">transform the collider will be attached to</param>
/// <returns>Calculated cylinder shaped mesh collider data</returns>
private MeshColliderData CalculatePreviewCylinder(List<Vector3> worldVertices, Transform attachTo)
{
MeshColliderData data = ECC.CalculateCylinderCollider(worldVertices, attachTo);
return data;
}
/// <summary>
/// Calculates the preview data for a convex mesh collider. (uses quickhull calculation for both messy and quickhull method)
/// </summary>
/// <param name="worldVertices">World-Space vertices that are selected</param>
/// <param name="attachTo">Current AttachTo object</param>
/// <param name="method">Mesh Collider generation method</param>
/// <returns>EasyCollider data with a mesh value set.</returns>
private MeshColliderData CalculatePreviewMesh(List<Vector3> worldVertices, List<Vector3> normals, Transform attachTo, MESH_COLLIDER_METHOD method)
{
// Messy-hull not suited for preview as the intermediate mesh is essentially useless
// and the actual important result is from the internal calculation by the mesh collider, so it would have to be added.
// but since internall it uses a similar hull method, the result should be similar as well.
// previewer now goes through ECC for meshes as well, as it should.
return ECC.CalculateHullData(worldVertices, attachTo);
}
/// <summary>
/// Calculates a preview sphere
/// </summary>
/// <param name="worldVertices">world vertices used to calculate the collider</param>
/// <param name="attachTo">gameobject the collider will be attached to</param>
/// <param name="method">calculation method used to calculate the collider type as an int</param>
/// <returns>Calculated sphere collider data</returns>
private EasyColliderData CalculatePreviewSphere(List<Vector3> worldVertices, Transform attachTo, SPHERE_COLLIDER_METHOD method)
{
switch (method)
{
case SPHERE_COLLIDER_METHOD.Distance:
return ECC.CalculateSphereDistance(worldVertices, attachTo);
case SPHERE_COLLIDER_METHOD.BestFit:
return ECC.CalculateSphereBestFit(worldVertices, attachTo);
default:
return ECC.CalculateSphereMinMax(worldVertices, attachTo);
}
}
#endregion
/// <summary>
/// Checks to see if the collider needs to be calculated, so the preview is updated.
/// </summary>
/// <param name="editor"></param>
/// <param name="colliderType"></param>
/// <param name="method"></param>
/// <returns>true if the preview needs to be updated.</returns>
private bool NeedsUpdate(EasyColliderPreferences preferences, EasyColliderEditor editor)
{
// private bool NeedsUpdate(EasyColliderEditor editor, CREATE_COLLIDER_TYPE colliderType, int method)
//(NeedsUpdate(editor, preferences.PreviewColliderType, GetMethodForColliderPreviewType(preferences)) || forceUpdate)
if (preferences.CurrentWindowTab == ECE_WINDOW_TAB.Creation)
{
if (CurrentVertexCount != editor.SelectedVertices.Count
|| (PreviewData == null && RotateAndDuplicateData == null && preferences.rotatedDupeSettings.enabled)
|| (PreviewData == null && preferences.rotatedDupeSettings.enabled == false)
|| (PreviewData != null && PreviewData.ColliderType != preferences.PreviewColliderType)
|| CurrentMethod != GetMethodForColliderPreviewType(preferences)
|| CurrentAttachTo != editor.AttachToObject.transform
|| ActualColliderType != preferences.PreviewColliderType
|| editor.HasTransformMoved()
|| CurrentVertexNormalOffset != preferences.VertexNormalOffset
|| CurrentVertexNormalInset != preferences.VertexNormalInset
|| CurrentShrinkGrow != preferences.ShrinkGrow
|| CurrentNormalOffset != preferences.VertexNormalOffsetType
)
{
return true;
}
}
else if (preferences.CurrentWindowTab == ECE_WINDOW_TAB.Editing)
{
if (CurrentColliderCount != editor.SelectedColliders.Count
|| PreviewData == null
|| CurrentMethod != GetMethodForColliderPreviewType(preferences)
|| CurrentAttachTo != editor.AttachToObject.transform
|| editor.HasTransformMoved()
|| ActualColliderType != preferences.PreviewColliderType)
{
return true;
}
return false;
}
return false;
}
/// <summary>
/// Updates the current preview if needed.
/// </summary>
/// <param name="editor"></param>
/// <param name="preferences"></param>
public void UpdatePreview(EasyColliderEditor editor, EasyColliderPreferences preferences, bool forceUpdate = false)
{
if (editor != null && preferences != null && editor.SelectedGameObject != null && editor.AttachToObject != null)
{
DrawColor = preferences.PreviewDrawColor;
if (NeedsUpdate(preferences, editor) || forceUpdate)
{
ActualColliderType = preferences.PreviewColliderType;
CurrentAttachTo = editor.AttachToObject.transform;
CurrentColliderCount = editor.SelectedColliders.Count;
CurrentMethod = GetMethodForColliderPreviewType(preferences);
CurrentPreviewTab = preferences.CurrentWindowTab;
CurrentVertexCount = editor.SelectedVertices.Count;
CurrentVertexNormalOffset = preferences.VertexNormalOffset;
CurrentVertexNormalInset = preferences.VertexNormalInset;
CurrentShrinkGrow = preferences.ShrinkGrow;
CurrentNormalOffset = preferences.VertexNormalOffsetType;
if (PreviewData == null)
{
PreviewData = new EasyColliderData();
}
if (preferences.CurrentWindowTab == ECE_WINDOW_TAB.Creation)
{
if (preferences.rotatedDupeSettings.enabled == true)
{
RotateAndDuplicateData = new List<EasyColliderData>();
CurrentAttachTo = preferences.rotatedDupeSettings.pivot.transform;
CalculatePreviewRotateAndDuplicate(preferences, editor);
}
else
{
CalculatePreviewCollider(preferences, editor);
}
PreviewData.ColliderType = ActualColliderType;
}
else if (preferences.CurrentWindowTab == ECE_WINDOW_TAB.Editing)
{
CalculatePreviewMerge(preferences, editor);
}
}
DrawPreview();
}
}
#region VHACDPREVIEW
/// <summary>
/// Array of triangles for use in VHACDResultPreview
/// </summary>
private int[] triangles;
/// <summary>
/// Array of vertices for use in VHACDResultPreview
/// </summary>
private Vector3[] vertices;
/// <summary>
/// List of randomized colors for use in VHACDResultPreview
/// </summary>
private List<Color> colors = new List<Color>();
public void DrawVHACDConversionPreview(List<EasyColliderData> data, VHACD_CONVERSION convertTo)
{
foreach (EasyColliderData d in data)
{
if (d == null) continue;
if (convertTo == VHACD_CONVERSION.Boxes)
{
BoxColliderData bcd = d as BoxColliderData;
if (bcd == null) continue;
DrawPreviewBox(bcd, DrawColor);
}
else if (convertTo == VHACD_CONVERSION.Capsules)
{
CapsuleColliderData ccd = d as CapsuleColliderData;
if (ccd == null) continue;
DrawPreviewCapsule(ccd, DrawColor);
}
else if (convertTo == VHACD_CONVERSION.Spheres)
{
SphereColliderData scd = d as SphereColliderData;
if (scd == null) continue;
DrawPreviewSphere(scd, DrawColor);
}
}
}
/// <summary>
/// Draws each mesh in the dictionary with a black wireframe, and a random color semi-transparent mesh.
/// </summary>
/// <param name="previewResult">Dictionary of transforms and meshes from the result of VHACD</param>
public void DrawVHACDResultPreview(Dictionary<Transform, Mesh[]> previewResult)
{
Shader s = Shader.Find("Custom/EasyColliderMeshColliderPreview");
if (s != null)
{
Material wireMat = new Material(s);
wireMat.SetColor("_Color", Color.black);
Material flatMat = new Material(s);
foreach (KeyValuePair<Transform, Mesh[]> kvp in previewResult)
{
if (kvp.Key == null) continue; // transform can be null if it's deleted.
if (colors.Count < kvp.Value.Length)
{
int addColors = kvp.Value.Length - colors.Count;
for (int i = 0; i < addColors; i++)
{
colors.Add(new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f)));
}
}
for (int i = 0; i < kvp.Value.Length; i++)
{
flatMat.SetColor("_Color", colors[i]);
flatMat.SetPass(1);
Graphics.DrawMeshNow(kvp.Value[i], kvp.Key.localToWorldMatrix);
wireMat.SetPass(1);
GL.wireframe = true;
Graphics.DrawMeshNow(kvp.Value[i], kvp.Key.localToWorldMatrix);
GL.wireframe = false;
}
}
}
else
{
Debug.LogWarning("EasyColliderEditor: Unable to find shader for preview.");
}
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 0975e5f3c5571d940891fd8dc17e7587
timeCreated: 1592761340
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderPreviewer.cs
uploadId: 885904

View File

@@ -0,0 +1,100 @@
using UnityEngine;
namespace ECE
{
/// <summary>
/// Properties to use when creating a collider.
/// </summary>
public struct EasyColliderProperties
{
/// <summary>
/// Marks the collider's isTrigger property
/// </summary>
public bool IsTrigger;
/// <summary>
/// Layer of gameobject when creating a rotated collider.
/// </summary>
public int Layer;
#if (UNITY_6000_0_OR_NEWER)
/// <summary>
/// Physic material to set on collider.
/// </summary>
public PhysicsMaterial PhysicMaterial;
#else
/// <summary>
/// Physic material to set on collider.
/// </summary>
public PhysicMaterial PhysicMaterial;
public void SetPhysicMat(PhysicMaterial physmat)
{
PhysicMaterial = physmat;
}
#endif
#if (UNITY_2022_2_OR_NEWER)
/// <summary>
/// whether or not the collidere generates contacts for physics.contact event.
/// </summary>
public bool ProvidesContacts;
/// <summary>
/// layer overrides - layer override priority property on a collider.
/// </summary>
public int LayerOverridePriority;
/// <summary>
/// layer overrides exclude layer mask property on colliders.
/// </summary>
public LayerMask ExcludeLayers;
/// <summary>
/// layer overrides include layer mask property on colliders.
/// </summary>
public LayerMask IncludeLayers;
#endif
/// <summary>
/// Orientation of created collider.
/// </summary>
public COLLIDER_ORIENTATION Orientation;
/// <summary>
/// Gameobject collider gets added to.
/// </summary>
public GameObject AttachTo;
/// <summary>
/// Properties with which to create a collider
/// </summary>
/// <param name="isTrigger">Should the collider's isTrigger property be true?</param>
/// <param name="layer">Layer of gameobject when creating a rotated collider</param>
/// <param name="physicMaterial">Physic Material to apply to a collider</param>
/// <param name="attachTo">GameObject to attach the collider to</param>
/// <param name="orientation">Orientation of the collider for generation</param>
public EasyColliderProperties(bool isTrigger, int layer,
#if (UNITY_6000_0_OR_NEWER)
PhysicsMaterial physicMaterial,
#else
PhysicMaterial physicMaterial,
#endif
GameObject attachTo, COLLIDER_ORIENTATION orientation = COLLIDER_ORIENTATION.NORMAL)
{
IsTrigger = isTrigger;
Layer = layer;
PhysicMaterial = physicMaterial;
AttachTo = attachTo;
Orientation = orientation;
#if (UNITY_2022_2_OR_NEWER)
ProvidesContacts = false;
LayerOverridePriority = 0;
IncludeLayers = 0;
ExcludeLayers = 0;
#endif
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 6beb8fffd8449374b81cf9857e315469
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderProperties.cs
uploadId: 885904

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: ed797196cc351a34db4a5f88338cc1fe
timeCreated: 1600696552
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderQuickHull.cs
uploadId: 885904

View File

@@ -0,0 +1,28 @@
using UnityEngine;
namespace ECE
{
[System.Serializable]
public class EasyColliderRotateDuplicate
{
public enum ROTATE_AXIS
{
X,
Y,
Z,
}
public bool enabled;
public ROTATE_AXIS axis;
public int NumberOfDuplications = 4;
public float StartRotation = 0.0f;
public float EndRotation = 360f;
public GameObject pivot;
public GameObject attachTo;
}
}

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 5e6a373c203fb6b459f89497990e1b24
timeCreated: 1618839991
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderRotateDuplicate.cs
uploadId: 885904

View File

@@ -0,0 +1,397 @@
#if(UNITY_EDITOR)
using UnityEngine;
using UnityEditor;
using System.IO;
#if (UNITY_2021_2_OR_NEWER)
// prefab stage out of experimental.
using UnityEditor.SceneManagement;
#elif (UNITY_2018_3_OR_NEWER)
// prefabstage is still experimental
// but what it inherits from, PreviewSceneStage/Stage is not experimental as of 2020.1
using UnityEditor.Experimental.SceneManagement;
#endif
namespace ECE
{
public static class EasyColliderSaving
{
public class PrefabData
{
public UnityEngine.Object FoundObject;
public string AssetPath;
}
static PrefabData TryFindPrefabObject(GameObject go)
{
UnityEngine.Object foundObject = null;
PrefabData foundData = new PrefabData();
#if UNITY_2018_2_OR_NEWER
// 2018_2+
PrefabStage stage = PrefabStageUtility.GetCurrentPrefabStage();
if (stage != null)
{
if (stage.prefabContentsRoot != null)
{
foundObject = PrefabUtility.GetCorrespondingObjectFromSource(stage.prefabContentsRoot);
}
#if (UNITY_2020_1_OR_NEWER)
// asset path in 2020.1+
foundData.AssetPath = stage.assetPath;
#elif (UNITY_2018_3_OR_NEWER)
// prefab asset path 2018.3 to 2019.4
foundData.AssetPath = stage.prefabAssetPath;
#endif
}
// try using just the GO if were not in a prefab stage.
if (foundObject == null)
{
foundObject = PrefabUtility.GetCorrespondingObjectFromSource(go);
if (foundObject == null)
{
foundObject = PrefabUtility.GetOutermostPrefabInstanceRoot(go);
}
}
#else
// legacy unity support. -- (I dont test in earlier than 2019.4+ anymore)
foundObject = PrefabUtility.GetPrefabParent(go);
if (foundObject == null)
{
foundObject = PrefabUtility.FindPrefabRoot(go);
}
#endif
foundData.FoundObject = foundObject;
return foundData;
}
static PrefabData TryFindMeshOrSkinnedMeshObject(GameObject go)
{
PrefabData foundPrefabData = new PrefabData();
MeshFilter mf = go.GetComponent<MeshFilter>();
if (mf != null)
{
foundPrefabData.FoundObject = mf.sharedMesh;
}
else
{
SkinnedMeshRenderer smr = go.GetComponent<SkinnedMeshRenderer>();
if (smr != null)
{
foundPrefabData.FoundObject = smr.sharedMesh;
}
}
return foundPrefabData;
}
/// <summary>
/// Static preferences asset that is currently loaded.
/// </summary>
/// <value></value>
static EasyColliderPreferences ECEPreferences { get { return EasyColliderPreferences.Preferences; } }
/// <summary>
/// removes invalid characters (so path is valid) and trailing slashes (for compatibility with older versions of unity)
/// </summary>
/// <param name="path"></param>
/// <returns>Assets/Folder1/Folder</returns>
static string CleanAssetPath(string path)
{
//remove any invalid path characters.
path = string.Join("", path.Split(Path.GetInvalidPathChars()));
// no trailing slash is more compatible with older version of unity and AssetDatabase.IsValidFolder, so prefer no trailing slash when checking.
// folder path is saved with / at the end, so remove if we have to.
if (path[path.Length - 1] == '/')
{
path = path.Remove(path.Length - 1);
}
return path;
}
/// <summary>
/// Gets a valid path to save a convex hull at to feed into save convex hull meshes function.
/// </summary>
/// <param name="go">selected gameobject</param>
/// <param name="ECEPreferences">preferences object</param>
/// <returns>assetdb path like: Assets/Folder/OptionSubfolder/baseObjectsName</returns>
public static string GetValidConvexHullPath(GameObject go)
{
// use default specified path
// remove invalid characters from file name, just in case (user reported error, thanks!)
string goName = string.Join("_", go.name.Split(Path.GetInvalidFileNameChars()));
// start with the default path specified in preferences.
string path = ECEPreferences.SaveConvexHullPath;
// get path to gameobject
if (ECEPreferences.ConvexHullSaveMethod != CONVEX_HULL_SAVE_METHOD.Folder)
{
// bandaid for scaled temporary skinned mesh:
// as the scaled mesh filter is added during setup with the name Scaled Mesh Filter (Temporary)
if (go.name.Contains("Scaled Mesh Filter"))
{
go = go.transform.parent.gameObject; // set the gameobject to the temp's parent (as that will be a part of the prefab if it is one and thus should work.)
}
PrefabData foundPrefabData = null;
if (ECEPreferences.ConvexHullSaveMethod == CONVEX_HULL_SAVE_METHOD.Prefab)
{
foundPrefabData = TryFindPrefabObject(go);
}
else if (ECEPreferences.ConvexHullSaveMethod == CONVEX_HULL_SAVE_METHOD.Mesh)
{
foundPrefabData = TryFindMeshOrSkinnedMeshObject(go);
}
else if (ECEPreferences.ConvexHullSaveMethod == CONVEX_HULL_SAVE_METHOD.PrefabMesh)
{
foundPrefabData = TryFindPrefabObject(go);
if (foundPrefabData.FoundObject == null && string.IsNullOrEmpty(foundPrefabData.AssetPath))
{
foundPrefabData = TryFindMeshOrSkinnedMeshObject(go);
}
}
else if (ECEPreferences.ConvexHullSaveMethod == CONVEX_HULL_SAVE_METHOD.MeshPrefab)
{
foundPrefabData = TryFindMeshOrSkinnedMeshObject(go);
if (foundPrefabData.FoundObject == null)
{
foundPrefabData = TryFindPrefabObject(go);
}
}
// by default, use the found AssetPath, this should be the outermost prefab which is what is wanted.
string pathToPrefabOrMesh = foundPrefabData.AssetPath;
if (string.IsNullOrEmpty(pathToPrefabOrMesh) && foundPrefabData.FoundObject != null)
{
pathToPrefabOrMesh = AssetDatabase.GetAssetPath(foundPrefabData.FoundObject);
}
// but only use the path it if it exists.
// here we trim the object name just down to the last / so Asset/FolderWithPrefabInIt/
if (!string.IsNullOrEmpty(pathToPrefabOrMesh))
{
int index = pathToPrefabOrMesh.LastIndexOf("/");
if (index >= 0)
{
// removes object name.
path = pathToPrefabOrMesh.Remove(index + 1);
}
}
}
string originalPath = path;
path = CleanAssetPath(path);
// AssetDatabase.IsValidFolder("Assets/"); // not valid in 2019
// AssetDatabase.IsValidFolder("Assets"); // valid in 2019 and 6000. Prefer this one!
// prefab/mesh searched for a folder to save in and failed to find a valid path, default to the save convex hull path specified in preferences.
if ((!AssetDatabase.IsValidFolder(path) && path + "/" != ECEPreferences.SaveConvexHullPath)
// saving in a non-asset path and does not have allow saving convex hulls in packages enabled
|| (!path.StartsWith("Assets") && !ECEPreferences.AllowSavingConvexHullsInPackages))
{
path = ECEPreferences.SaveConvexHullPath;
path = CleanAssetPath(path);
// could not find a valid mesh/prefab location, but the fallback save convex hull folder DOES work.
if (AssetDatabase.IsValidFolder(path))
{
Debug.LogWarning("Easy Collider Editor: Could not find a valid location to save the collider. Saving in the folder specified in preferences: " + path);
}
}
// path and path fallback both are clean and have no trailing / here.
// this will automatically be true if we're using a folder (and it failed) OR the fallback on prefab/mesh fails (which also uses SaveConvexHullPath)
if (!AssetDatabase.IsValidFolder(path) && (path + "/").Contains(ECEPreferences.SaveConvexHullPath))
{
// path to ece preferences (in scripts typically)
path = AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(ECEPreferences));
// because the above is the full path to the file including the files name.
path = path.Remove(path.LastIndexOf("/"));
path = path.Replace("/Scripts", "");
path = string.Join("", path.Split(Path.GetInvalidPathChars()));
// asset path for preferences file is invalid, not in assets folder a
if (path.StartsWith("Assets") || ECEPreferences.AllowSavingConvexHullsInPackages)
{
if (!AssetDatabase.IsValidFolder(path + "/Convex Hulls"))
{
AssetDatabase.CreateFolder(path, "Convex Hulls");
AssetDatabase.Refresh();
}
path = path + "/Convex Hulls";
if (originalPath == ECEPreferences.SaveConvexHullPath)
{
// original path was saving to a folder.
ECEPreferences.SaveConvexHullPath = path + "/";
Debug.LogWarning("Easy Collider Editor: Convex Hull save path specified in Easy Collider Editor's preferences could not be found, or it is an invalid asset folder. Saving in: " + path + " as a fallback and updating preferences. If the folder has been moved or deleted, update to a different folder in the edit preferences foldout.\n\n Original path: " + originalPath);
}
// so that if we already have a valid
else if (!ECEPreferences.SaveConvexHullPath.StartsWith("Assets"))
{
// used an alternative mesh/prefab/prefabmesh save method.
ECEPreferences.SaveConvexHullPath = path + "/";
Debug.LogWarning("Easy Collider Editor: Could not find a valid location to save the collider and the save path specified in preferences could not be found, or it is an invalid asset folder. Saving in: " + path + " and updated preferences to this folder. If the folder has been moved or deleted, update to a different folder in the edit preferences foldout.\n\n Original path: " + originalPath);
}
}
else // in a packages folder probably without AllowSavingConvexHullsInPackages enabled.
{
// final fallback.
path = "Assets/Convex Hulls";
if (originalPath == ECEPreferences.SaveConvexHullPath)
{
// change default path to a valid path.
ECEPreferences.SaveConvexHullPath = path + "/";
#if (UNITY_2020_3_OR_NEWER)
AssetDatabase.SaveAssetIfDirty(ECEPreferences);
#endif
}
if (!AssetDatabase.IsValidFolder(path))
{
AssetDatabase.CreateFolder("Assets", "Convex Hulls");
AssetDatabase.Refresh();
if (originalPath == ECEPreferences.SaveConvexHullPath)
{
// original path was saving to a folder.
Debug.LogWarning("Easy Collider Editor: Convex Hull save path specified in Easy Collider Editor's preferences could not be found, or it is an invalid asset folder. A folder to save collider assets was created at: " + path + " and automatically set in preferences. A different folder in Easy Collider Editor's preferences foldout can be specified if desired.\n\n Original path: " + originalPath);
}
else
{
// used an alternative mesh/prefab/prefabmesh save method.
Debug.LogWarning("Easy Collider Editor: Could not find a valid location to save the collider and the save path specified in preferences could not be found, or it is an invalid asset folder. A new folder has been created at " + path + " to save mesh collider assets and automatically set in preferences. A different folder in Easy Collider Editor's preferences foldout can be specified if desired. \n\n Original path: " + originalPath);
}
}
}
}
// if they want a subfolder, create it if needed and use it.
if (!string.IsNullOrEmpty(ECEPreferences.SaveConvexHullSubFolder))
{
if (!AssetDatabase.IsValidFolder(path + "/" + ECEPreferences.SaveConvexHullSubFolder))
{
AssetDatabase.CreateFolder(path, ECEPreferences.SaveConvexHullSubFolder);
}
path += "/" + ECEPreferences.SaveConvexHullSubFolder + "/";
path = CleanAssetPath(path);
}
string fullPath = path + "/" + goName;
return fullPath;
}
/// <summary>
/// goes thorugh the path and finds the first non-existing path that can be used to save.
/// </summary>
/// <param name="path">Full path up to save location: ie C:/UnityProjects/ProjectName/Assets/Folder/baseObject</param>
/// <param name="suffix">Suffix to add to save files ie _Suffix_</param>
/// <returns>first valid path for AssetDatabase.CreateAsset ie baseObject_Suffix_0</returns>
private static string GetFirstValidAssetPath(string path, string suffix)
{
string validPath = path;
if (File.Exists(validPath + suffix + "0.asset"))
{
int i = 1;
while (File.Exists(validPath + suffix + i + ".asset"))
{
i += 1;
}
validPath += suffix + i + ".asset";
}
else
{
validPath += suffix + "0.asset";
}
// replace application's data path (Unity Editor: <path to project folder>/Assets)
// "Assets" earlier in the path should no longer cause issues.
validPath = validPath.Replace(Application.dataPath, "Assets");
return validPath;
}
/// <summary>
/// Creates and saves a mesh asset in the asset database with appropriate path and suffix.
/// </summary>
/// <param name="mesh">mesh</param>
/// <param name="attachTo">gameobject the mesh will be attached to, used to find asset path.</param>
public static void CreateAndSaveMeshAsset(Mesh mesh, GameObject attachTo)
{
if (mesh != null && !DoesMeshAssetExists(mesh))
{
string savePath = GetValidConvexHullPath(attachTo);
if (savePath != "")
{
string assetPath = GetFirstValidAssetPath(savePath, ECEPreferences.SaveConvexHullSuffix);
AssetDatabase.CreateAsset(mesh, assetPath);
AssetDatabase.SaveAssets();
}
}
}
/// <summary>
/// Checks if the asset already exists (needed for rotate and duplicate, as the mesh is the same mesh repeated.)
/// </summary>
/// <param name="mesh"></param>
/// <returns></returns>
public static bool DoesMeshAssetExists(Mesh mesh)
{
string p = AssetDatabase.GetAssetPath(mesh);
if (p == null || p.Length == 0)
{
return false;
}
return true;
}
/// <summary>
/// Creates and saves an array of mesh assets in the assetdatabase at the path with the the format "savePath"+"suffix"+[0-n].asset
/// </summary>
/// <param name="savePath">Full path up to save location: ie C:/UnityProjects/ProjectName/Assets/Folder/baseObject</param>
/// <param name="suffix">Suffix to add to save files ie _Suffix_</param>
public static Mesh[] CreateAndSaveMeshAssets(Mesh[] meshes, string savePath, string suffix)
{
string firstAssetPath = null;
int assetSuffixIndex = -1;
for (int i = 0; i < meshes.Length; i++)
{
// get a new valid path for each mesh to save.
string path = GetFirstValidAssetPath(savePath, suffix);
try
{
if (ECEPreferences.CombinedVHACDColliders && firstAssetPath != null)
{
//adding a name to the mesh even though it isn't required to match the first assets name as it by default has the path's name.
string name = firstAssetPath.Remove(assetSuffixIndex, firstAssetPath.Length - assetSuffixIndex);
name = name.Remove(0, name.LastIndexOf("/") + 1);
meshes[i].name = name + suffix + i.ToString();
AssetDatabase.AddObjectToAsset(meshes[i], firstAssetPath);
}
else
{
AssetDatabase.CreateAsset(meshes[i], path);
}
}
catch (System.Exception error)
{
Debug.LogError("Error saving at path:" + path + ". Try changing the save Convex Hull path in Easy Collider Editor's preferences to a different folder.\n" + error.ToString());
}
if (firstAssetPath == null)
{
firstAssetPath = path;
assetSuffixIndex = firstAssetPath.IndexOf(suffix);
}
}
AssetDatabase.SaveAssets();
if (ECEPreferences.CombinedVHACDColliders)
{
// need to reload the assets and update the meshes array otherwise they don't point to the correct object
// only the first one will without this as for whatever reason create asset will correctly link the objects but adding an object to an asset will not.
var assets = AssetDatabase.LoadAllAssetsAtPath(firstAssetPath);
for (int i = 0; i < assets.Length; i++)
{
meshes[i] = (Mesh)assets[i];
}
}
return meshes;
}
}
}
#endif

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 6ddf66fc4a34fe740aee3cf08e0549af
timeCreated: 1600696849
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderSaving.cs
uploadId: 885904

View File

@@ -0,0 +1,26 @@
#if (UNITY_EDITOR)
namespace ECE
{
/// <summary>
/// A list of tips for users of easy collider editor.
/// </summary>
public static class EasyColliderTips
{
public const string TRY_MOUSE_CONTROL = "Want to be able to select vertices with the mouse? Try enabling the mouse controls in preferences.";
public const string NEW_MOUSE_CONTROL = "Use left click to select the highlighted vertex, and the right click to select the point under the mouse.";
public const string COMPUTE_SHADER_TIP = "You're system's shader model does not support shaders with a compute buffer. Be sure to use the gizmo display method instead of shader in the preferences.";
public const string EDIT_PREFS_FORCED_FOCUSED = "You are editing preferences with forced window focus enabled. To make this easier, try disabling vertex selection, or the force focus scene option in preferences.";
public const string FORCED_FOCUSED_WINDOW = "Forced window focus is enabled, you may not be able to edit values easily by typing. Disable vertex selection, or the force focus scene option in preferences.";
public const string IN_PLAY_MODE = "Vertex selection is not enabled when in play mode.";
public const string NO_MESH_FILTER_FOUND = "No mesh filter is on the selected gameobject, try enabling include child meshes.";
public const string WRONG_FOCUSED_WINDOW = "Vertex selection only works when the scene view window is focused.";
public const string ROTATED_BOX_COLLIDER_TIP = "The first 3 points determine the orientation of a rotated box collider.";
public const string ROTATED_CAPSULE_COLLIDER_TIP = "The first 2 points determine the orientation of a rotated capsule collider.";
public const string COLLIDER_CREATION_SHORTCUTS_1 = "Shortcuts:\n\t[1-7] Change collider preview\n\t[~] Create the collider being previewed\n\tDouble Tap [1-7] Create the collider";
public const string AUTO_SKILLED_CONTROL_PARAMETERS = "Holding CTRL while adjusting a parameter in Per Bone Settings will also adjust all of it's children.";
}
}
#endif

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 3855a2c50be7c1742950276affa94392
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderTips.cs
uploadId: 885904

View File

@@ -0,0 +1,918 @@
#if (UNITY_EDITOR)
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
namespace ECE
{
public static class EasyColliderUIHelpers
{
/// <summary>
/// Stores all the collider icons
/// </summary>
public static Texture2D[] ColliderIcons;
public static Texture2D[] ColliderMergeIcons;
/// <summary>
/// Creates a bunch of buttons that function similar to an enum popup where only one can be selected.
/// </summary>
/// <param name="selected">Current selected enum</param>
/// <returns>Selected enum</returns>
public static Enum EnumButtonArray(Enum selected, string[] labels, string[] toolTips)
{
GUIStyle style = new GUIStyle(GUI.skin.button);
style.padding.left = 5;
style.padding.right = 5;
style.padding.bottom = 2;
style.padding.top = 0;
Array a = Enum.GetValues(selected.GetType());
int currentValue = Convert.ToInt32(selected);
for (int i = 0; i < a.Length; i++)
{
GUIContent content = new GUIContent(labels[i], toolTips[i]);
if ((int)a.GetValue(i) == currentValue)
{
Color TempGUIColor = GUI.color;
GUI.color = _DisabledButtonColor;
GUILayout.Button(content, style);
GUI.color = TempGUIColor;
}
else
{
if (GUILayout.Button(content, style))
{
return (Enum)a.GetValue(i);
}
}
}
return selected;
}
/// <summary>
/// Creates buttons with icons as content that return an Enum when clicked.
/// </summary>
/// <param name="selected"></param>
/// <param name="iconContentNames"></param>
/// <param name="toolTips"></param>
/// <returns></returns>
public static Enum EnumIconButtonArray(Enum selected, string[] iconContentNames, string[] toolTips)
{
GUIStyle style = new GUIStyle(GUI.skin.box);
style.padding = new RectOffset(0, 0, 0, 0);
style.margin = new RectOffset(0, 2, 4, 0);
Array a = Enum.GetValues(selected.GetType());
int currentValue = Convert.ToInt32(selected);
for (int i = 0; i < a.Length; i++)
{
GUIContent content = EditorGUIUtility.IconContent(iconContentNames[i], toolTips[i]);
if ((int)a.GetValue(i) == currentValue)
{
Color TempGUIColor = GUI.color;
GUI.color = _DisabledButtonColor;
GUILayout.Button(content, style);
GUI.color = TempGUIColor;
}
else
{
if (GUILayout.Button(content, style))
{
return (Enum)a.GetValue(i);
}
}
}
return selected;
}
/// <summary>
/// Gets all the editor icons and loads them and stores them in an array
/// </summary>
public static void GetIcons()
{
ColliderIcons = new Texture2D[7];
ColliderMergeIcons = new Texture2D[7];
string[] locs = AssetDatabase.FindAssets("ECEUIBox t:texture2D");
if (locs.Length > 0)
{
ColliderIcons[0] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[0]));
ColliderMergeIcons[0] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[1]));
}
locs = AssetDatabase.FindAssets("ECEUIRotatedBox t:texture2D");
if (locs.Length > 0)
{
ColliderIcons[1] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[0]));
ColliderMergeIcons[1] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[1]));
}
locs = AssetDatabase.FindAssets("ECEUISphere t:texture2D");
if (locs.Length > 0)
{
ColliderIcons[2] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[0]));
ColliderMergeIcons[2] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[1]));
}
locs = AssetDatabase.FindAssets("ECEUICapsule t:texture2D");
if (locs.Length > 0)
{
ColliderIcons[3] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[0]));
ColliderMergeIcons[3] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[1]));
}
locs = AssetDatabase.FindAssets("ECEUIRotatedCapsule t:texture2D");
if (locs.Length > 0)
{
ColliderIcons[4] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[0]));
ColliderMergeIcons[4] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[1]));
}
locs = AssetDatabase.FindAssets("ECEUIConvexMesh t:texture2D");
if (locs.Length > 0)
{
ColliderIcons[5] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[0]));
ColliderMergeIcons[5] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[1]));
}
locs = AssetDatabase.FindAssets("ECEUICylinder t:texture2D");
if (locs.Length > 0)
{
ColliderIcons[6] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[0]));
ColliderMergeIcons[6] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[1]));
// ColliderMergeIcons[3] = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(locs[1]));
}
}
/// <summary>
/// checks to see if the icons have moved / need to be found.
/// </summary>
public static void VerifyIcons()
{
bool needsUpdate = false;
if (ColliderIcons == null || ColliderMergeIcons == null)
{
GetIcons();
}
else
{
foreach (Texture2D t2d in ColliderIcons)
{
if (t2d == null)
{
needsUpdate = true;
}
}
foreach (Texture2D t2d in ColliderMergeIcons)
{
if (t2d == null)
{
needsUpdate = true;
}
}
if (needsUpdate)
{
GetIcons();
}
}
}
/// <summary>
/// Helper method to create a button with a 32x32 Icon where the icons are found seperately and stored in an array.
/// </summary>
/// <param name="tooltip">tooltip to display when button is enabled</param>
/// <param name="disabledToolTip">tooltip to display when disabled</param>
/// <param name="iconNumber">icon number in texture2d array</param>
/// <param name="isEnabled">is this icon enable?</param>
/// <returns>true if enabled and the button is clicked, false otherwise</returns>
public static bool DisableableIconButton(string tooltip, string disabledToolTip, int iconNumber, bool isEnabled)
{
VerifyIcons();
if (ColliderIcons[iconNumber] == null) return false; // an icon was deleted.
GUIStyle style = new GUIStyle(GUI.skin.button);
style.imagePosition = ImagePosition.ImageAbove;
style.padding = new RectOffset(4, 4, 4, 4);
GUIContent content = new GUIContent("Text", ColliderIcons[iconNumber]);
GUI.enabled = isEnabled;
bool button = GUILayout.Button(content, style, GUILayout.ExpandWidth(false));
GUI.enabled = true;
return button;
}
static string[] alphaKeys = new string[7] { "1", "2", "3", "4", "5", "6", "7" };
private static string KeyCodeToString(KeyCode keyCode)
{
return alphaKeys[((int)keyCode - 257)];
}
private static GUIStyle _highlightedStyle;
private static GUIStyle HighLightedStyle
{
get
{
if (_highlightedStyle == null)
{
_highlightedStyle = new GUIStyle(GUI.skin.box);
Texture2D text = new Texture2D(1, 1);
text.SetPixel(0, 0, Color.red);
_highlightedStyle.normal.background = text;
_highlightedStyle.fixedHeight = 0;
_highlightedStyle.padding = new RectOffset(4, 4, 1, 16);
}
return _highlightedStyle;
}
}
private static GUIStyle _iconButtonLabelStyle;
private static GUIStyle IconButtonLabelStyle
{
get
{
if (_iconButtonLabelStyle == null)
{
_iconButtonLabelStyle = new GUIStyle(GUI.skin.box);
_iconButtonLabelStyle.richText = true;
_iconButtonLabelStyle.fixedHeight = 16;
_iconButtonLabelStyle.fixedWidth = 40;
_iconButtonLabelStyle.padding.bottom = 1;
_iconButtonLabelStyle.alignment = TextAnchor.LowerCenter;
}
return _iconButtonLabelStyle;
}
}
/// <summary>
/// Helper method to create a button with a 32x32 Icon where the icons are found seperately and stored in an array.
/// </summary>
/// <param name="tooltip">tooltip to display when button is enabled</param>
/// <param name="disabledToolTip">tooltip to display when disabled</param>
/// <param name="iconNumber">icon number in texture2d array</param>
/// <param name="isEnabled">is this icon enable?</param>
/// <returns>true if enabled and the button is clicked, false otherwise</returns>
public static bool DisableableIconButtonShortcutCreation(string tooltip, string disabledToolTip, int iconNumber, bool isEnabled, KeyCode shortCut, bool highlight)
{
VerifyIcons();
if (ColliderIcons.Length - 1 < iconNumber || ColliderIcons[iconNumber] == null) return false; // an icon was deleted.
GUIStyle style = new GUIStyle(GUI.skin.button);
style.padding = new RectOffset(4, 4, 1, 16);
GUIStyle labelStyle = new GUIStyle(GUI.skin.box);
labelStyle.richText = true;
labelStyle.fixedHeight = 16;
labelStyle.fixedWidth = 40;
labelStyle.padding.bottom = 1;
labelStyle.alignment = TextAnchor.LowerCenter;
GUIContent content = new GUIContent(ColliderIcons[iconNumber]);
Rect r = GUILayoutUtility.GetRect(content, style);
style.fixedHeight = 48;
GUI.enabled = isEnabled;
if (highlight && isEnabled)
{
Rect rect = new Rect(r.x - 2, r.y - 2, r.width + 4, r.height + 3);
Color bc = GUI.backgroundColor;
GUI.backgroundColor = new Color(0, 0.5f, 1f, 1f);
GUI.Box(rect, GUIContent.none, HighLightedStyle);
GUI.backgroundColor = bc;
}
style.fixedHeight = 48;
content.tooltip = isEnabled ? tooltip : disabledToolTip;
bool button = GUI.Button(r, content, style);
r.y += 32;
// better dark mode colors, also light mode enabled/disabled button colors.
string colorCode = isEnabled ? "black" : "#525252";
if (EditorGUIUtility.isProSkin)
{
colorCode = isEnabled ? "#C4C4C4" : "#6C6C6C";
}
GUI.Label(r, "<color=" + colorCode + "><b>" + KeyCodeToString(shortCut) + "</b></color>", IconButtonLabelStyle);
GUI.enabled = true;
return button;
}
public static bool DisableableIconButtonShortcutMerge(string tooltip, string disabledToolTip, int iconNumber, bool isEnabled, KeyCode shortCut, bool highlight)
{
VerifyIcons();
if (ColliderMergeIcons.Length - 1 < iconNumber || ColliderMergeIcons[iconNumber] == null) return false; // an icon was deleted.
GUIStyle style = new GUIStyle(GUI.skin.button);
style.padding = new RectOffset(4, 4, 1, 16);
GUIStyle labelStyle = new GUIStyle(GUI.skin.box);
labelStyle.richText = true;
labelStyle.fixedHeight = 16;
labelStyle.fixedWidth = 40;
labelStyle.padding.bottom = 1;
labelStyle.alignment = TextAnchor.LowerCenter;
GUIContent content = new GUIContent(ColliderMergeIcons[iconNumber]);
Rect r = GUILayoutUtility.GetRect(content, style);
style.fixedHeight = 48;
GUI.enabled = isEnabled;
if (highlight && isEnabled)
{
Rect rect = new Rect(r.x - 2, r.y - 2, r.width + 4, r.height + 3);
Color bc = GUI.backgroundColor;
GUI.backgroundColor = new Color(0, 0.5f, 1f, 1f);
GUI.Box(rect, GUIContent.none, HighLightedStyle);
GUI.backgroundColor = bc;
}
content.tooltip = isEnabled ? tooltip : disabledToolTip;
bool button = GUI.Button(r, content, style);
r.y += 32;
// better dark mode colors, also light mode enabled/disabled button colors.
string colorCode = isEnabled ? "black" : "#525252";
if (EditorGUIUtility.isProSkin)
{
colorCode = isEnabled ? "#C4C4C4" : "#6C6C6C";
}
GUI.Label(r, "<color=" + colorCode + "><b>" + KeyCodeToString(shortCut) + "</b></color>", IconButtonLabelStyle);
GUI.enabled = true;
return button;
}
/// <summary>
/// Background GUI Color to use for buttons when they are disabled
/// </summary>
public static Color _DisabledButtonColor = new Color(0.7f, 0.7f, 0.7f, 1f);
/// <summary>
/// Background GUI Color for toggles when they are disabled
/// </summary>
public static Color _DisabledToggleColor = new Color(1, 1, 1, 0.33f);
/// <summary>
/// Creates a disableable and undoable foldout list.
/// Allows you to pass a method to check if an item a user is trying to add is valid before adding to the list.
/// Has an X button beside each item to directly remove it, and a clear list button at the bottom.
/// </summary>
/// <param name="obj">Object to record undo on</param>
/// <param name="foldoutContent">GUI Content of the foldout</param>
/// <param name="disabledText">Text to be displayed when the foldout is disabled and open</param>
/// <param name="isOpen">references to the bool controlling if the foldout is open</param>
/// <param name="list">List of items to display</param>
/// <param name="objType">Type to use in object field</param>
/// <param name="OnAddMethod">Method that returns true if the object should be added to the list</param>
/// <param name="isEnabled">Is the foldout enabled?</param>
/// <typeparam name="T">List's type</typeparam>
public static void DisableableFoldoutList<T>(
UnityEngine.Object obj,
GUIContent foldoutContent,
string disabledText, ref bool isOpen,
ref List<T> list,
System.Type objType,
Func<T, bool> OnAddMethod,
bool isEnabled) where T : UnityEngine.Object
{
// createa foldout.
isOpen = EditorGUILayout.Foldout(isOpen, foldoutContent);
if (isOpen) // only display if the foldout is open.
{
if (isEnabled) // if the list is enabled, display it
{
// Variables to keep track of current item being displayed
T previous; // current item prior to it changing (if it does)
T current; // current item after changing (if it does)
List<T> itemsToRemove = new List<T>();
for (int i = 0; i < list.Count; i++)
{
// each item is horizontally displayed
EditorGUILayout.BeginHorizontal();
// quick removal button
if (GUILayout.Button("X", GUILayout.ExpandWidth(false)))
{
itemsToRemove.Add(list[i]);
}
else
{
// Create a field for each list
previous = list[i];
current = (T)EditorGUILayout.ObjectField(list[i], objType, true);
if (current == null) // if the new item is null, mark for removal.
{
itemsToRemove.Add(list[i]);
}
// otherwise, call the onadd method to see if the item in the field should be added to the list
else if (!OnAddMethod(current))
{
// if it shouldn't be added, then set the item to the previous item
// this cleans up items that are in the list when the onadd method uses different parameters
if (!OnAddMethod(previous))
{
// if that item is also invalid, remove it fromt he list.
itemsToRemove.Add(list[i]);
}
}
else
{
// the new item is valid, set that list item to that value.
list[i] = current;
}
}
EditorGUILayout.EndHorizontal();
}
if (itemsToRemove.Count > 0)
{
// record the removal of all items to remove.
Undo.RecordObject(obj, "Change List");
foreach (T item in itemsToRemove) list.Remove(item);
}
// Use an empty object field at the bottom as a way to quickly add to the list.
current = (T)EditorGUILayout.ObjectField(null, objType, true);
// if its not null and passes the OnAddMethod function
if (current != null && OnAddMethod(current))
{
// record the undo of adding an object
Undo.RecordObject(obj, "Change List");
list.Add(current);
}
if (GUILayout.Button("Clear List"))
{
Undo.RecordObject(obj, "Clear List");
list.Clear();
}
}
else // list is disabled, just display the disabled text as a lebel when the foldout is opened.
{
GUIStyle label = new GUIStyle(GUI.skin.label);
label.wordWrap = true;
EditorGUILayout.LabelField(disabledText, label);
}
}
}
/// <summary>
/// Creates a button that allows undoable changing of a keycode value.
/// Button displays current keycode, then press any key when pressed and listens for a keypress, then updates the keycode.
/// </summary>
/// <param name="obj">Object to record undo on.</param>
/// <param name="label">Label to display beside button</param>
/// <param name="key">KeyCode to change. Should be unique for each button.</param>
/// <param name="isChanging">Bool representing whether it should be listening to key presses. Should be unique for each button.</param>
public static bool ChangeButtonKeyCodeUndoable(UnityEngine.Object obj, string label, string labelTooltip, ref KeyCode key, ref bool isChanging, float windowWidth, bool drawlabel = false)
{
float labelWidth = 100;
// -15 to add padding to prevent a horizontal scrollbar always being present, this can probably be actually calculated from some unity internal padding values but whatever.
float buttonWidth = windowWidth - labelWidth - 25;
if (buttonWidth < 120) { buttonWidth = 120; }
GUIStyle pressedButtonStyle = new GUIStyle(GUI.skin.box);
pressedButtonStyle.fontStyle = FontStyle.Bold;
pressedButtonStyle.fixedWidth = buttonWidth;
GUIStyle buttonStyle = new GUIStyle(GUI.skin.button);
buttonStyle.fixedWidth = buttonWidth;
//buttonStyle.min
//buttonStyle.stretchWidth = true;
// EditorGUILayout.BeginHorizontal();
// GUILayout.Label(new GUIContent(label, labelTooltip));
// EditorGUILayout.LabelField(new GUIContent(label, labelTooltip), GUILayout.ExpandWidth(false));
string buttonTitle = isChanging ? "Press a key" : key.ToString();
if (drawlabel)
{
EditorGUILayout.BeginHorizontal();
// GUILayout.Label(new GUIContent(label, labelTooltip), GUILayout.ExpandWidth(false));
LabelWidth(label, labelTooltip, labelWidth);
}
if (GUILayout.Button(new GUIContent(buttonTitle, "Click then press a key to change.\nModifier keys (like alt, ctrl, space, shift, etc.) can not be used."), isChanging ? pressedButtonStyle : buttonStyle))
{
isChanging = true;
}
if (drawlabel)
{
EditorGUILayout.EndHorizontal();
}
// EditorGUILayout.EndHorizontal();
if (isChanging)
{
if (CheckKeypressChangeUndoable(obj, ref key))
{
isChanging = false;
}
}
return isChanging;
}
/// <summary>
/// Changes the KeyCode of keyCode through an undoable action when a key is pressed down.
/// </summary>
/// <param name="obj">Object to record undo on.</param>
/// <param name="keyCode">KeyCode to change to new key</param>
/// <returns>true if key was changed.</returns>
private static bool CheckKeypressChangeUndoable(UnityEngine.Object obj, ref KeyCode keyCode)
{
if (Event.current != null // have an event.
&& Event.current.type == EventType.KeyDown // a key down event.
&& Event.current.keyCode != KeyCode.None && !IsModifierKeyUsed(Event.current.keyCode)) // a key down event that wasn't None.
{
Undo.RecordObject(obj, "Change keycode");
keyCode = Event.current.keyCode;
return true;
}
return false;
}
public static void HorizontalLineLight()
{
HorizontalLine(new Color(0, 0, 0, 0.25f));
}
/// <summary>
/// Draws a vertical line of thickness and color at the current control rect at a single line height.
/// </summary>
/// <param name="color"></param>
/// <param name="lineThickness"></param>
/// <param name="paddingLeft"></param>
/// <param name="extraHeight"></param>
public static void VerticalLine(Color color, float lineThickness = 1f, float paddingLeft = 0f, float extraHeight = 2f)
{
Rect r = EditorGUILayout.GetControlRect(GUILayout.Width(lineThickness));
r.height = EditorGUIUtility.singleLineHeight + extraHeight;
r.width = lineThickness;
r.x += paddingLeft;
EditorGUI.DrawRect(r, color);
}
/// <summary>
/// draws a horizontal line of a given color, thickness, and padding. Centered in the rect.
/// </summary>
/// <param name="color">color of the line</param>
/// <param name="lineThickness">thickness of the line</param>
/// <param name="padding"></param>
public static void HorizontalLine(Color color, float lineThickness = 2f, float padding = 6f)
{
Rect r = EditorGUILayout.GetControlRect(GUILayout.Height(padding));
// thickness of line to draw is the height
r.height = lineThickness;
// center the line in the rect.
r.y = r.y + (padding - lineThickness) / 2;
// draw the rect.
EditorGUI.DrawRect(r, color);
}
public static void VerticalSpace(float size)
{
Rect r = EditorGUILayout.GetControlRect(GUILayout.Height(size));
EditorGUI.DrawRect(r, new Color(0, 0, 0, 0));
}
/// <summary>
/// checks to see if the keycode is one of the many modifier keys.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static bool IsModifierKeyUsed(KeyCode value)
{
switch (value)
{
case KeyCode.LeftShift:
case KeyCode.RightShift:
case KeyCode.LeftControl:
case KeyCode.RightControl:
case KeyCode.LeftAlt:
case KeyCode.RightAlt:
case KeyCode.LeftCommand:
case KeyCode.RightCommand:
case KeyCode.Numlock:
case KeyCode.CapsLock:
case KeyCode.LeftWindows: // covers both keycodes for right/left apple as well.
case KeyCode.RightWindows:
return true;
default:
return false;
}
}
/// <summary>
/// In case we want to modify all labels used in the future more easily.
/// Just makes a GUILayout.Label(label)
/// </summary>
/// <param name="label"></param>
public static void Label(string label, string tooltip = "")
{
GUILayout.Label(new GUIContent(label, tooltip));
}
public static void LabelWidth(string label, string tooltip = "", float width = -1)
{
GUIStyle labelStyle = new GUIStyle(GUI.skin.label);
if (width > 0) { labelStyle.fixedWidth = width; }
GUILayout.Label(new GUIContent(label, tooltip), labelStyle);
}
public static void LabelEmptyNoStretch(float size = 50f)
{
// float currentSize = EditorGUIUtility.labelWidth;
// EditorGUIUtility.labelWidth = size;
GUIStyle style = new GUIStyle(GUI.skin.label);
style.stretchWidth = false;
GUILayout.Label("", style);
// EditorGUIUtility.labelWidth = currentSize;
}
public static void LabelBold(string label, string tooltip = "")
{
GUIStyle style = new GUIStyle(GUI.skin.label);
style.fontStyle = FontStyle.Bold;
style.stretchWidth = false;
if (tooltip == "")
{
GUILayout.Label(label, style);
}
else
{
GUILayout.Label(new GUIContent(label, tooltip), style);
}
}
public static bool FoldoutBold(string label, ref bool foldout, string tooltip = "")
{
GUIStyle style = new GUIStyle(EditorStyles.foldout);
style.fontStyle = FontStyle.Bold;
style.stretchWidth = false;
if (tooltip == "")
{
// GUILayout.Label(label, style);
foldout = EditorGUILayout.Foldout(foldout, label, style);
}
else
{
foldout = EditorGUILayout.Foldout(foldout, new GUIContent(label, tooltip), style);
}
return foldout;
}
public static void LabelIcon(string label, string iconName, string tooltip = "")
{
GUIStyle style = new GUIStyle(GUI.skin.label);
style.wordWrap = true;
GUIContent icon = EditorGUIUtility.IconContent(iconName, tooltip);
EditorGUILayout.BeginHorizontal();
GUILayout.Label(icon, GUILayout.ExpandWidth(false));
GUILayout.Label(new GUIContent(label, tooltip), style);
GUILayout.Label(icon, GUILayout.ExpandWidth(false));
EditorGUILayout.EndHorizontal();
}
/// <summary>
/// Creates an undoable color field
/// </summary>
/// <param name="obj">Object to record the undo on</param>
/// <param name="content">GUI Content for the auto-layout field</param>
/// <param name="undoString">String to use for undos</param>
/// <param name="value">Value of the color</param>
public static void ColorFieldUndoable(UnityEngine.Object obj, string undoString, ref Color value)
{
Color _ColorField = value;
EditorGUI.BeginChangeCheck();
_ColorField = EditorGUILayout.ColorField(_ColorField);
if (EditorGUI.EndChangeCheck())
{
Undo.RegisterCompleteObjectUndo(obj, undoString);
value = _ColorField;
}
}
public static bool DisableableButtonWithShortcut(string text, string enabledTooltip, string disabledTooltip, bool isEnabled, KeyCode shortcut, bool isShortcutEnabled)
{
if (isShortcutEnabled)
{
text = text + " (" + shortcut.ToString() + ")";
}
GUI.enabled = isEnabled;
bool button = GUILayout.Button(new GUIContent(text, isEnabled ? enabledTooltip : disabledTooltip));
GUI.enabled = true;
return button;
}
/// <summary>
/// Creates a button that displays different if it is enabled or disabled. Button always returns false if disabled.
/// <param name="title">text of button</param>
/// <param name="enabledTooltip">tool tip for button when enabled</param>
/// <param name="disabledTooltip">tool tip for box when disabled</param>
/// <param name="isEnabled">is the button enabled?</param>
/// <returns>false if disabled, true if enabled and button is clicked</returns>
public static bool DisableableButton(string text, string enabledTooltip, string disabledTooltip, bool isEnabled)
{
GUI.enabled = isEnabled;
bool button = GUILayout.Button(new GUIContent(text, isEnabled ? enabledTooltip : disabledTooltip));
GUI.enabled = true;
return button;
}
/// <summary>
/// Creates an undoable float field that can also be disabled
/// </summary>
/// <param name="obj">Object to record the undo on</param>
/// <param name="label">Label of the float field</param>
/// <param name="tooltip">Tooltip to display when enabled</param>
/// <param name="disabledTooltip">Tooltip to display when disabled</param>
/// <param name="undoString">String to use for undos</param>
/// <param name="value">Value of the float</param>
/// <param name="isEnabled">Is the float field enabled?</param>
public static void DisableableFloatFieldUndoable(UnityEngine.Object obj, string label, string tooltip, string disabledTooltip, string undoString, ref float value, bool isEnabled)
{
GUI.enabled = isEnabled;
FloatFieldUndoable(obj, new GUIContent(label, isEnabled ? tooltip : disabledTooltip), undoString, ref value);
GUI.enabled = true;
}
/// <summary>
/// Creates a left toggle if the toggle is enabled that functions normally,
/// otherwise creates a style toggle that is not toggleable and grayed-out.
/// </summary>
/// <param name="text">Text to show beside the toggle</param>
/// <param name="enabledTooltip">Tool tip when toggle is enabled</param>
/// <param name="disabledTooltip">Tool tip when toggle is disabled</param>
/// <param name="isEnabled">Is the toggle enabled</param>
/// <param name="toggle">Bool the toggle controls</param>
/// <returns>Value of toggle</returns>
public static bool DisableableToggleLeft(string text, string enabledTooltip, string disabledTooltip, bool isEnabled, bool toggle)
{
GUI.enabled = isEnabled;
bool toggleValue = GUILayout.Toggle(toggle, new GUIContent(text, isEnabled ? enabledTooltip : disabledTooltip));
GUI.enabled = true;
return toggleValue;
}
/// <summary>
/// Creates an undoable float field.
/// </summary>
/// <param name="obj">Object to record the undo on</param>
/// <param name="content">GUI Content for the auto-layout field</param>
/// <param name="undoString">String to use for undos</param>
/// <param name="value">Value of the float</param>
public static void FloatFieldUndoable(UnityEngine.Object obj, GUIContent content, string undoString, ref float value, int labelSize = -1)
{
float _FloatField = value;
EditorGUI.BeginChangeCheck();
float w = EditorGUIUtility.labelWidth;
if (labelSize > 0)
{
EditorGUIUtility.labelWidth = labelSize;
}
_FloatField = EditorGUILayout.FloatField(content, _FloatField);
if (EditorGUI.EndChangeCheck())
{
Undo.RegisterCompleteObjectUndo(obj, undoString);
value = _FloatField;
}
EditorGUIUtility.labelWidth = w;
}
static GUIStyle ButtonStyle;
public static bool IconButton(string iconContentName, string tooltip)
{
ButtonStyle = new GUIStyle(GUI.skin.button);
ButtonStyle.padding = new RectOffset(4, 4, 1, 1);
ButtonStyle.margin = new RectOffset(4, 4, 2, 0);
ButtonStyle.stretchWidth = false;
GUIContent icon = EditorGUIUtility.IconContent(iconContentName, tooltip);
// text was not tooltip!
icon.tooltip = tooltip;
if (GUILayout.Button(icon, ButtonStyle))
{
return true;
}
return false;
}
/// <summary>
/// Creates a float slider that converts basePow^current to an integer in actual result.
/// </summary>
/// <param name="current">Current Value of the float slider</param>
/// <param name="min">Min Value of the float slider</param>
/// <param name="max">Max value of the float slider</param>
/// <param name="actualResult">Result of all calculations that is actually used</param>
/// <param name="aMin">Min value to clamp result to</param>
/// <param name="aMax">Max value to clamp result to</param>
/// <param name="basePow">power to use when calculating actual result in Mathf.Pow(basePow, current)</param>
/// <returns>Current value of the slider itself</returns>
public static float SliderFloatToIntBase2(GUIContent label, float current, float min, float max, ref int actualResult, int aMin, int aMax, float basePow = 2f)
{
EditorGUILayout.BeginHorizontal();
// get the current control rect.
Rect r = EditorGUILayout.GetControlRect();
// quarter of width goes to the label.
r.width = r.width / 4;
// label of the slider
EditorGUI.LabelField(r, label);
// set up the control name for the slider
GUI.SetNextControlName("FloatSlider" + current);
// keep track if the slider changes
EditorGUI.BeginChangeCheck();
//sliderbar uses half of space.
r.x += r.width;
r.width *= 2;
// draw the slider.
current = GUI.HorizontalSlider(r, current, min, max);
// if it changes, and is not focused, change the focus to the slider
// this helps keep the area where you can directly enter the number with the keyboard updated as the slider moves.
if (EditorGUI.EndChangeCheck() && GUI.GetNameOfFocusedControl() != "FloatSlider" + current)
{
GUI.FocusControl("FloatSlider" + current);
}
// Set the actual result using the current slider.
actualResult = (int)Mathf.Clamp(Mathf.Pow(basePow, current), aMin, aMax);
// check if the user has updated the int field input
EditorGUI.BeginChangeCheck();
// adjust rect to use last quarter of space.
r.x += r.width + 8;
r.width = r.width / 2 - 8;
actualResult = EditorGUI.IntField(r, actualResult);
// actualResult = EditorGUILayout.IntField(actualResult, GUILayout.ExpandWidth(false));
if (EditorGUI.EndChangeCheck())
{
actualResult = Mathf.Clamp(actualResult, aMin, aMax);
// update the current value if the text has changed.
current = Mathf.Log(actualResult, 2);
}
EditorGUILayout.EndHorizontal();
// were done, return the current value.
return current;
}
/// <summary>
/// Creates an undoable toggle field.
/// </summary>
/// <param name="obj">Object to record the undo on</param>
/// <param name="content">GUI Content for the auto-layout field</param>
/// <param name="undoString">String to use for undos</param>
/// <param name="value">Value of the toggle</param>
public static void ToggleLeftUndoable(UnityEngine.Object obj, GUIContent content, string undoString, ref bool value, float labelWidth = 10f)
{
bool _ToggleField = value;
EditorGUI.BeginChangeCheck();
// _ToggleField = EditorGUILayout.ToggleLeft(content, _ToggleField);
float lw = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = labelWidth;
// _ToggleField = GUILayout.Toggle(_ToggleField, content, GUILayout.ExpandWidth(false));
_ToggleField = EditorGUILayout.ToggleLeft(content, _ToggleField);
EditorGUIUtility.labelWidth = lw;
if (EditorGUI.EndChangeCheck())
{
// again record only works in some cases, and complete works significantly better.
// ie can't record changing DrawGizmos without the complete object undo.
Undo.RegisterCompleteObjectUndo(obj, undoString);
value = _ToggleField;
}
}
/// <summary>
/// creates a toggle left with no change check
/// </summary>
/// <param name="content"></param>
/// <param name="value"></param>
/// <param name="labelWidth"></param>
public static bool ToggleLeft(GUIContent content, bool value, float labelWidth = 10f)
{
bool _ToggleField = value;
float lw = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = labelWidth;
_ToggleField = EditorGUILayout.ToggleLeft(content, _ToggleField);
EditorGUIUtility.labelWidth = lw;
return _ToggleField;
}
public static Enum EnumPopup(GUIContent content, Enum selected, float labelWidth = 50f)
{
float lw = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = labelWidth;
GUIStyle miniPopupStyle = GUI.skin.GetStyle("MiniPopup");
if (miniPopupStyle != null)
{
GUIStyle enumStyle = new GUIStyle(miniPopupStyle);
Enum val = EditorGUILayout.EnumPopup(content, selected, enumStyle);
EditorGUIUtility.labelWidth = lw;
return val;
}
else
{
Enum val = EditorGUILayout.EnumPopup(content, selected);
EditorGUIUtility.labelWidth = lw;
return val;
}
}
}
}
#endif

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 6d01889b53b9585409077f8e53708c46
timeCreated: 1592405766
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderUIHelpers.cs
uploadId: 885904

View File

@@ -0,0 +1,478 @@
#if (UNITY_EDITOR)
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;
using System;
using System.Linq;
namespace ECE
{
//Future potential features:
// The option to covert the convex hulls generated into other colliders, like box colliders (boxelization is a fun term).
// So that we can leverage VHACD results into alternative basic colliders.
// New version of vhacd is out but in my testing it is much slower than the older performance branch version
// additionally, it offers less adjustable parameters, which makes it harder to get a good fit,
// even though the fit isn't perfect with any vhacd implementation since it's approximate convex decomposition
// and even though the current parameters aren't particularily understandable, you can adjust them and see the output quickly until something is close enough.
public class EasyColliderVHACD
{
// If you're getting an error about DLL not found exception, you'll likely be pointed to this line by the error
// near the top of this file you'll find " const string dllName = "ECE_VHACD"; " ,
// this is where the dll name is placed (these same comments are there as well)
// To fix this on Mac: sometimes it can not recognize the .bundle, try either "ECE_VHACD.bundle" or "ECE_VHACD" as the dllName string
// Occasionally this can also happen when the dll/bundles are updated, and imported into unity after they were already used
// to correctly update when vhacd is updated, be sure to close unity, and immediately update the asset on opening the project
// currently only supports windows, and OSX (arm / silicon and intel) versions of unity.
const string dllName = "ECE_VHACD";
[DllImport(dllName, EntryPoint = "GetMaxNumVerticesPerCH")]
private static extern uint GetMaxNumVerticesPerCH();
// extern "C" VHACD_API double* GetConvexHullCenter();
[DllImport(dllName, EntryPoint = "GetConvexHullCenter")]
private static extern IntPtr GetConvexHullCenter();
// extern "C" VHACD_API unsigned int* GetConvexHullTriangles();
[DllImport(dllName, EntryPoint = "GetConvexHullTriangles")]
private static extern IntPtr GetConvexHullTriangles();
// extern "C" VHACD_API double* GetConvexHullPoints();
[DllImport(dllName, EntryPoint = "GetConvexHullPoints")]
private static extern IntPtr GetConvexHullPoints();
// extern "C" VHACD_API void Compute();
[DllImport(dllName, EntryPoint = "Compute")]
private static extern void Compute();
// extern "C" VHACD_API bool Create();
[DllImport(dllName, EntryPoint = "Create")]
private static extern bool Create();
// extern "C" VHACD_API bool Create_ASYNC();
[DllImport(dllName, EntryPoint = "Create_ASYNC")]
private static extern bool Create_ASYNC();
// extern "C" VHACD_API void Destroy();
[DllImport(dllName, EntryPoint = "Destroy")]
private static extern void Destroy();
// extern "C" VHACD_API int GetConvexHullNumPoints();
[DllImport(dllName, EntryPoint = "GetConvexHullNumPoints")]
private static extern int GetConvexHullNumPoints();
// extern "C" VHACD_API int GetConvexHullNumTriangles();
[DllImport(dllName, EntryPoint = "GetConvexHullNumTriangles")]
private static extern int GetConvexHullNumTriangles();
// extern "C" VHACD_API double GetConvexHullPoint(int index);
[DllImport(dllName, EntryPoint = "GetConvexHullPoint")]
private static extern double GetConvexHullPoint(int index);
// extern "C" VHACD_API int GetConvexHullTriangle(int index);
[DllImport(dllName, EntryPoint = "GetConvexHullTriangle")]
private static extern int GetConvexHullTriangle(int index);
// extern "C" VHACD_API double GetConvexHullVolume();
[DllImport(dllName, EntryPoint = "GetConvexHullVolume")]
private static extern double GetConvexHullVolume();
// extern "C" VHACD_API int GetNumberOfConvexHulls();
[DllImport(dllName, EntryPoint = "GetNumberOfConvexHulls")]
private static extern int GetNumberOfConvexHulls();
// extern "C" VHACD_API int GetPointSize();
[DllImport(dllName, EntryPoint = "GetPointSize")]
private static extern int GetPointSize();
// extern "C" VHACD_API int GetPointSize();
[DllImport(dllName, EntryPoint = "IsReady")]
private static extern bool IsReady();
// extern "C" VHACD_API void SetConvexHull(int index);
[DllImport(dllName, EntryPoint = "SetConvexHull")]
private static extern void SetConvexHull(int index);
// extern "C" VHACD_API void SetMaxHulls(int value);
[DllImport(dllName, EntryPoint = "SetMaxHulls")]
private static extern void SetMaxHulls(int value);
// extern "C" VHACD_API void SetMaxVerticesPerHull(int value);
[DllImport(dllName, EntryPoint = "SetMaxVerticesPerHull")]
private static extern void SetMaxVerticesPerHull(int value);
// For branch PERFORMANCE ENHANCEMENTS
// extern "C" VHACD_API void SetParameters(
// double concavity,
// double alpha,
// double beta,
// double minVolumePerConvexHull,
// int resolution,
// int maxNumVerticesPerCH,
// int planeDownsampling,
// int convexhullDownsampling,
// int maxConvexHulls,
// bool projectHullVertices,
// unsigned int fillMode);
[DllImport(dllName, EntryPoint = "SetParameters")]
private static extern void SetParameters(
double concavity,
double alpha,
double beta,
double minVolumePerConvexHull,
int resolution,
int maxNumVerticesPerCH,
int planeDownsampling,
int convexhullDownsampling,
int maxConvexHulls,
bool projectHullVertices,
uint fillMode
);
// extern "C" VHACD_API void SetPoint(int index, float value);
[DllImport(dllName, EntryPoint = "SetPoint")]
private static extern void SetPoint(int index, float value);
// extern "C" VHACD_API void SetPoints(float pointsArr[], int size);
[DllImport(dllName, EntryPoint = "SetPoints")]
private static extern void SetPoints(float[] pointsArr, int size);
// extern "C" VHACD_API void SetPointSize(int size);
[DllImport(dllName, EntryPoint = "SetPointSize")]
private static extern void SetPointSize(int size);
// extern "C" VHACD_API void SetResolution(int value);
[DllImport(dllName, EntryPoint = "SetResolution")]
private static extern void SetResolution(int value);
// extern "C" VHACD_API void SetTriangle(int index, int value);
[DllImport(dllName, EntryPoint = "SetTriangle")]
private static extern void SetTriangle(int index, int value);
// extern "C" VHACD_API void SetTriangles(int trianglesArr[], int size);
[DllImport(dllName, EntryPoint = "SetTriangles")]
private static extern void SetTriangles(int[] trianglesArr, int size);
// extern "C" VHACD_API void SetTriangleSize(int size);
[DllImport(dllName, EntryPoint = "SetTriangleSize")]
private static extern void SetTriangleSize(int size);
/// <summary>
/// Is an instance of vhacd initialized?
/// </summary>
/// this is a fix for the new version of vhacd which is not used yet for various reasons.
private bool isInitialized = false;
/// <summary>
/// Initializes a VHACD instance
/// </summary>
/// <param name="async">Use async process?</param>
/// <returns></returns>
public bool Init(bool async = true)
{
Clean();
if (async)
{
// fixes an issue in new vhacd without changing the api.
isInitialized = true;
// If you're getting an error about DLL not found exception, you'll likely be pointed to this line by the error
// near the top of this file you'll find " const string dllName = "ECE_VHACD"; " ,
// this is where the dll name is placed (these same comments are there as well)
// To fix this on Mac: sometimes it can not recognize the .bundle, try either "ECE_VHACD.bundle" or "ECE_VHACD" as the dllName string
// Occasionally this can also happen when the dll/bundles are updated, and imported into unity after they were already used
// to correctly update when vhacd is updated, be sure to close unity, and immediately update the asset on opening the project
// currently only supports windows, and OSX (arm / silicon and intel) versions of unity.
return Create_ASYNC();
}
else
{
isInitialized = true;
return Create();
}
}
/// <summary>
/// Destroys the VHACD instance, if it is already initialized.
/// </summary>
/// <returns>true if destroyed, false if not destroyed(because it wasn't initialized yet)</returns>
public bool Clean()
{
// fixes issue where vhacd isn't initialized and tries to destroy itself (in new vhacd)
if (isInitialized)
{
// Debug.Log("Clean" + dllName);
isInitialized = false;
Destroy();
return true;
}
else
{
return false;
}
}
/// <summary>
/// Gets all calculated convex hulls and turn them into meshes.
/// </summary>
/// <returns>convex hull meshes</returns>
public Mesh[] CreateConvexHullMeshes()
{
int numHulls = GetNumberOfConvexHulls();
Mesh[] meshes = new Mesh[numHulls];
for (int i = 0; i < numHulls; i++)
{
// get the current convex hull
SetConvexHull(i);
// get the ch data
int pointCount = GetConvexHullNumPoints();
int triangleCount = GetConvexHullNumTriangles();
// create new vertex and triangles array.
Vector3[] vertices = new Vector3[pointCount];
int[] triangles = new int[triangleCount * 3];
for (int j = 0; j < triangleCount * 3; j++)
{
triangles[j] = GetConvexHullTriangle(j);
}
// assing each point to a vertex in the array
Vector3 point = Vector3.zero;
for (int j = 0; j < pointCount * 3; j += 3)
{
// note that in VHACD, each vertex is not a vector.
// instead each vertex is simply the 3 values in order.
point.x = (float)GetConvexHullPoint(j);
point.y = (float)GetConvexHullPoint(j + 1);
point.z = (float)GetConvexHullPoint(j + 2);
vertices[j / 3] = point;
}
// create and save the mesh.
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
// be sure to add it to our meshes array
meshes[i] = mesh;
}
//return the array of meshes so they can be added as convex mesh colliders.
return meshes;
}
/// <summary>
/// Gets the number of convex hulls calcalated
/// </summary>
/// <returns># convex hulls computed</returns>
public int GetConvexHullCount()
{
return GetNumberOfConvexHulls();
}
/// <summary>
/// Checks if the async computation of convex hulls is complete
/// </summary>
/// <returns>true if finished</returns>
public bool IsComputeFinished()
{
return IsReady();
}
/// <summary>
/// Checks to see if each convex hull is under 256 vertices and 256 triangles.
/// </summary>
/// <returns>True if under limits</returns>
public bool IsValid()
{
// calculate max triangle count and max vertex count
int maxTriangleCount = 0;
int maxVertexCount = 0;
int numHulls = GetConvexHullCount();
for (int i = 0; i < numHulls; i++)
{
SetConvexHull(i);
int currentTriCount = GetConvexHullNumTriangles();
int currentVertCount = GetConvexHullNumPoints();
if (currentTriCount > maxTriangleCount)
{
maxTriangleCount = currentTriCount;
}
if (currentVertCount > maxVertexCount)
{
maxVertexCount = currentVertCount;
}
}
// if both are under 256, unity will generate no errors.
// (these errors are hidden in some older versions of unity.)
if (maxVertexCount < 256 && maxTriangleCount < 256)
{
return true;
}
return false;
}
/// <summary>
/// Sets the vertices and triangles array for VHACD from mesh
/// </summary>
/// <param name="meshFilter">mesh filter of the source mesh</param>
/// <param name="attachTo">transform the mesh collider will be attached to</param>
/// <returns>true if preparation succeeds, false otherwise</returns>
public bool PrepareMeshData(MeshFilter meshFilter, Transform attachTo, Mesh mesh)
{
if (mesh == null) return false;
// convert from meshes' object to world space, to attach to's local space, then calculate, then add.
Vector3[] vertices = mesh.vertices;
int[] triangles = mesh.triangles;
List<Vector3> localAttachVertices = new List<Vector3>();
if (meshFilter != null && meshFilter.transform != attachTo && meshFilter.sharedMesh != null && meshFilter.sharedMesh == mesh)
{
foreach (Vector3 v in vertices)
{
// transform from mesh filters local space, to world space, to the attach to's local space.
localAttachVertices.Add(attachTo.transform.InverseTransformPoint(meshFilter.transform.TransformPoint(v)));
}
}
else
{
localAttachVertices = vertices.ToList();
}
// could have used an intptr but this way is fast enough
// and we can let VHACD take care of itself.
SetPointSize(localAttachVertices.Count * 3);
SetTriangleSize(triangles.Length);
for (int i = 0; i < localAttachVertices.Count; i++)
{
SetPoint(i * 3, localAttachVertices[i].x);
SetPoint(i * 3 + 1, localAttachVertices[i].y);
SetPoint(i * 3 + 2, localAttachVertices[i].z);
}
for (int i = 0; i < triangles.Length; i++)
{
SetTriangle(i, triangles[i]);
}
return true;
}
/// <summary>
/// prepares an array of meshfilters for a single convex hull decomposition.
/// </summary>
/// <param name="meshFilters">array of meshfilters</param>
public bool PrepareMeshData(List<MeshFilter> meshFilters, Transform attachTo)
{
// convert vertices from the mesh filters local space, to world space, to the attach to's local space.
int vertexCount = 0;
int triangleCount = 0;
List<Vector3> localAttachVertices = new List<Vector3>();
List<int> triangles = new List<int>();
foreach (MeshFilter mf in meshFilters)
{
// skip any mesh filters that were deleted, or had their shared mesh changed to null
if (mf == null || mf.sharedMesh == null) continue;
// convert to local vertices of the attach to object.
Vector3[] verts = mf.sharedMesh.vertices;
foreach (Vector3 v in verts)
{
localAttachVertices.Add(attachTo.transform.InverseTransformPoint(mf.transform.TransformPoint(v)));
}
// get current shared mesh triangles
int[] tris = mf.sharedMesh.triangles;
for (int i = 0; i < tris.Length; i++)
{
// add the vertex index, plus the offset of the total running vertex count.
triangles.Add(tris[i] + vertexCount);
}
vertexCount += mf.sharedMesh.vertices.Length;
triangleCount += mf.sharedMesh.triangles.Length;
}
// could have used intptr etc. to pass all the data at once
// but this way is still fast enough, and we can just let VHACD handle it's own stuff.
SetPointSize(vertexCount * 3);
SetTriangleSize(triangleCount);
for (int i = 0; i < localAttachVertices.Count; i++)
{
SetPoint(i * 3, localAttachVertices[i].x);
SetPoint(i * 3 + 1, localAttachVertices[i].y);
SetPoint(i * 3 + 2, localAttachVertices[i].z);
}
for (int i = 0; i < triangles.Count; i++)
{
SetTriangle(i, triangles[i]);
}
return true;
}
/// <summary>
/// Recalculates the current convex hulls based on max triangles and vertices with an aim to get max triangles below 256
/// </summary>
/// <returns></returns>
public bool RecomputeVHACD()
{
int maxTriangleCount = 0;
int maxVertexCount = 0;
int numHulls = GetConvexHullCount();
// calculate max triangles and vertices from convex hulls.
for (int i = 0; i < numHulls; i++)
{
SetConvexHull(i);
int currentTriCount = GetConvexHullNumTriangles();
int currentVertCount = GetConvexHullNumPoints();
if (currentTriCount > maxTriangleCount)
{
maxTriangleCount = currentTriCount;
}
if (currentVertCount > maxVertexCount)
{
maxVertexCount = currentVertCount;
}
}
// reduce the max number of vertices.
float trisPerVertMax = (float)maxTriangleCount / maxVertexCount;
int maxVerticesPerConvexHull = (int)(255 / trisPerVertMax);
// set the new max number of vertices
SetMaxVerticesPerHull(maxVerticesPerConvexHull);
// compute again.
Compute();
return true;
}
/// <summary>
/// Calls compute method on the current VHACD instance
/// </summary>
/// <returns></returns>
public bool RunVHACD()
{
Compute();
return true;
}
/// <summary>
/// Sets parameters on the current VHACD instance
/// </summary>
/// <param name="parameters">parameters to set</param>
public bool SetParameters(VHACDParameters parameters)
{
SetParameters(
parameters.concavity,
parameters.alpha,
parameters.beta,
parameters.minVolumePerCH,
parameters.resolution,
parameters.maxNumVerticesPerConvexHull,
parameters.planeDownsampling,
parameters.convexhullDownSampling,
parameters.maxConvexHulls,
parameters.projectHullVertices,
(uint)parameters.fillMode
);
return true;
}
}
/// <summary>
/// Fill mode for VHACD
/// </summary>
public enum VHACD_FILL_MODE
{
FLOOD_FILL,
SURFACE_ONLY,
RAYCAST_FILL,
}
}
#endif

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 492957b54e69e0944a816663cdf414ff
timeCreated: 1591919081
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderVHACD.cs
uploadId: 885904

View File

@@ -0,0 +1,60 @@
#if (UNITY_EDITOR)
using System;
using UnityEngine;
namespace ECE
{
/// <summary>
/// A vertex represented by the transform it's attached to and it's local position.
/// </summary>
[System.Serializable]
public class EasyColliderVertex : IEquatable<EasyColliderVertex>
{
/// <summary>
/// Local position of the vertex on the transform.
/// </summary>
public Vector3 LocalPosition;
public Vector3 Normal = Vector3.zero;
/// <summary>
/// Transform the vertex comes from.
/// </summary>
public Transform T;
/// <summary>
/// Create a new Easy Collider Vertex
/// </summary>
/// <param name="transform">Transform the vertex is on</param>
/// <param name="localPosition">Local position of the vertex</param>
public EasyColliderVertex(Transform transform, Vector3 localPosition)
{
this.T = transform;
this.LocalPosition = localPosition;
}
public EasyColliderVertex(EasyColliderVertex ecv)
{
this.T = ecv.T;
this.LocalPosition = ecv.LocalPosition;
}
// since we've used hashsets prior to adding normals, and we calculate smoothed normals
// when things get selected and store the those as the selected vertices,
// various things would have to change to include the normals in the equals and get hash code.
// so for now, we're still just position based.
public bool Equals(EasyColliderVertex other)
{
return (other.LocalPosition == this.LocalPosition && other.T == this.T);// && other.Normal == this.Normal);
}
public override int GetHashCode()
{
int hashCode = 13 * 31 + LocalPosition.GetHashCode();
// hashCode += 17 * this.Normal.GetHashCode();
return hashCode * 31 + T.GetHashCode();
}
}
}
#endif

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 41abfd88235d8c444be04e8d0ddd38b7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderVertex.cs
uploadId: 885904

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8aba5803d0eee804792b9405ce7990cf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/EasyColliderWindow.cs
uploadId: 885904

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ac9df4839a2693149a285fc07e42c21f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace ECE
{
public interface IEasyColliderPostProcessor
{
/// <summary>
/// post processes a box collider, properties orientation indiciates if it's a rotated collider.
/// </summary>
/// <param name="box"></param>
/// <param name="properties"></param>
void PostProcessCollider(BoxCollider boxCollider, EasyColliderProperties properties);
/// <summary>
/// post processes a capsule collider, properties orientation indiciates if it's a rotated collider.
/// </summary>
/// <param name="box"></param>
/// <param name="properties"></param>
void PostProcessCollider(CapsuleCollider capsuleCollider, EasyColliderProperties properties);
/// <summary>
/// post processes a mesh collider. cylinder colliders are mesh colliders as well.
/// </summary>
/// <param name="box"></param>
/// <param name="properties"></param>
void PostProcessCollider(MeshCollider meshCollider, EasyColliderProperties properties);
/// <summary>
/// post processes a sphere collider
/// </summary>
/// <param name="box"></param>
/// <param name="properties"></param>
void PostProcessCollider(SphereCollider sphereCollider, EasyColliderProperties properties);
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: b6cf4bc0f3d036f46a48313c8a796bed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/Interfaces/IEasyColliderPostProcessor.cs
uploadId: 885904

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: a8a38e163b87eb748aebb1b989f8503b
folderAsset: yes
timeCreated: 1591980098
licenseType: Store
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,96 @@
fileFormatVersion: 2
guid: 68a88bb9c40937341bf6536bbe774f0d
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 0
Exclude Linux: 1
Exclude Linux64: 1
Exclude LinuxUniversal: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: Windows
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 0
settings:
CPU: x86
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: LinuxUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/Plugins/ECE_VHACD.dll
uploadId: 885904

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d834607d4f50eef45918d26ac1d3e340
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
fileFormatVersion: 2
guid: 253ee65f4209bc24ab1c970ff13bf752
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 0
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: Linux
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 67880
packageName: Easy Collider Editor
packageVersion: 6.20.1
assetPath: Assets/EasyColliderEditor/Scripts/Plugins/Linux/ECE_VHACD.so
uploadId: 885904

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 88f8f3ea0a40624418d9c27ab616b7ea
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,74 @@
fileFormatVersion: 2
guid: a9491b77ec748994585680ed2c3066b5
folderAsset: yes
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 0
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
: OSXIntel
second:
enabled: 1
settings: {}
- first:
: OSXIntel64
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: OSX
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6a8585019d15a9a46bcd1c5a4672a0dc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More