finish(maybe...)
This commit is contained in:
parent
785e92ec8b
commit
2c61ef07ff
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6d323088abea7f842969756cfc4a7c85
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"name": "DOTween.Modules"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b1a18c052caf77a44a8bbb8a5e4acd11
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,257 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &1060830381606531078
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 5254461416733766296}
|
||||||
|
- component: {fileID: 9116820539264542060}
|
||||||
|
- component: {fileID: 3449792322087179520}
|
||||||
|
m_Layer: 5
|
||||||
|
m_Name: Text (TMP)
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!224 &5254461416733766296
|
||||||
|
RectTransform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1060830381606531078}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 2054960486242836156}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
|
m_SizeDelta: {x: -20, y: -20}
|
||||||
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
|
--- !u!222 &9116820539264542060
|
||||||
|
CanvasRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1060830381606531078}
|
||||||
|
m_CullTransparentMesh: 1
|
||||||
|
--- !u!114 &3449792322087179520
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1060830381606531078}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
|
m_OnCullStateChanged:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
m_text: Step
|
||||||
|
m_isRightToLeft: 0
|
||||||
|
m_fontAsset: {fileID: 11400000, guid: 6d323088abea7f842969756cfc4a7c85, type: 2}
|
||||||
|
m_sharedMaterial: {fileID: -1106088975554028259, guid: 6d323088abea7f842969756cfc4a7c85, type: 2}
|
||||||
|
m_fontSharedMaterials: []
|
||||||
|
m_fontMaterial: {fileID: 0}
|
||||||
|
m_fontMaterials: []
|
||||||
|
m_fontColor32:
|
||||||
|
serializedVersion: 2
|
||||||
|
rgba: 4281479730
|
||||||
|
m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
||||||
|
m_enableVertexGradient: 0
|
||||||
|
m_colorMode: 3
|
||||||
|
m_fontColorGradient:
|
||||||
|
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_fontColorGradientPreset: {fileID: 0}
|
||||||
|
m_spriteAsset: {fileID: 0}
|
||||||
|
m_tintAllSprites: 0
|
||||||
|
m_StyleSheet: {fileID: 0}
|
||||||
|
m_TextStyleHashCode: -1183493901
|
||||||
|
m_overrideHtmlColors: 0
|
||||||
|
m_faceColor:
|
||||||
|
serializedVersion: 2
|
||||||
|
rgba: 4294967295
|
||||||
|
m_fontSize: 60.6
|
||||||
|
m_fontSizeBase: 24
|
||||||
|
m_fontWeight: 400
|
||||||
|
m_enableAutoSizing: 1
|
||||||
|
m_fontSizeMin: 18
|
||||||
|
m_fontSizeMax: 72
|
||||||
|
m_fontStyle: 1
|
||||||
|
m_HorizontalAlignment: 2
|
||||||
|
m_VerticalAlignment: 512
|
||||||
|
m_textAlignment: 65535
|
||||||
|
m_characterSpacing: 0
|
||||||
|
m_wordSpacing: 0
|
||||||
|
m_lineSpacing: 0
|
||||||
|
m_lineSpacingMax: 0
|
||||||
|
m_paragraphSpacing: 0
|
||||||
|
m_charWidthMaxAdj: 0
|
||||||
|
m_enableWordWrapping: 1
|
||||||
|
m_wordWrappingRatios: 0.4
|
||||||
|
m_overflowMode: 0
|
||||||
|
m_linkedTextComponent: {fileID: 0}
|
||||||
|
parentLinkedComponent: {fileID: 0}
|
||||||
|
m_enableKerning: 1
|
||||||
|
m_enableExtraPadding: 0
|
||||||
|
checkPaddingRequired: 0
|
||||||
|
m_isRichText: 1
|
||||||
|
m_parseCtrlCharacters: 1
|
||||||
|
m_isOrthographic: 1
|
||||||
|
m_isCullingEnabled: 0
|
||||||
|
m_horizontalMapping: 0
|
||||||
|
m_verticalMapping: 0
|
||||||
|
m_uvLineOffset: 0
|
||||||
|
m_geometrySortingOrder: 0
|
||||||
|
m_IsTextObjectScaleStatic: 0
|
||||||
|
m_VertexBufferAutoSizeReduction: 0
|
||||||
|
m_useMaxVisibleDescender: 1
|
||||||
|
m_pageToDisplay: 1
|
||||||
|
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_isUsingLegacyAnimationComponent: 0
|
||||||
|
m_isVolumetricText: 0
|
||||||
|
m_hasFontAssetChanged: 0
|
||||||
|
m_baseMaterial: {fileID: 0}
|
||||||
|
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
--- !u!1 &3222343946699274350
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 2054960486242836156}
|
||||||
|
- component: {fileID: 6712085097152413335}
|
||||||
|
- component: {fileID: 6068113733588841294}
|
||||||
|
- component: {fileID: 3935588939355834315}
|
||||||
|
m_Layer: 5
|
||||||
|
m_Name: CommonButton
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!224 &2054960486242836156
|
||||||
|
RectTransform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 3222343946699274350}
|
||||||
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 5254461416733766296}
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
|
m_SizeDelta: {x: 250, y: 100}
|
||||||
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
|
--- !u!222 &6712085097152413335
|
||||||
|
CanvasRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 3222343946699274350}
|
||||||
|
m_CullTransparentMesh: 1
|
||||||
|
--- !u!114 &6068113733588841294
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 3222343946699274350}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
|
m_OnCullStateChanged:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
m_Sprite: {fileID: 21300000, guid: 9f847ec5e66e03e4ead1d3c5f7b510e8, type: 3}
|
||||||
|
m_Type: 1
|
||||||
|
m_PreserveAspect: 0
|
||||||
|
m_FillCenter: 1
|
||||||
|
m_FillMethod: 4
|
||||||
|
m_FillAmount: 1
|
||||||
|
m_FillClockwise: 1
|
||||||
|
m_FillOrigin: 0
|
||||||
|
m_UseSpriteMesh: 0
|
||||||
|
m_PixelsPerUnitMultiplier: 1
|
||||||
|
--- !u!114 &3935588939355834315
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 3222343946699274350}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Navigation:
|
||||||
|
m_Mode: 3
|
||||||
|
m_WrapAround: 0
|
||||||
|
m_SelectOnUp: {fileID: 0}
|
||||||
|
m_SelectOnDown: {fileID: 0}
|
||||||
|
m_SelectOnLeft: {fileID: 0}
|
||||||
|
m_SelectOnRight: {fileID: 0}
|
||||||
|
m_Transition: 1
|
||||||
|
m_Colors:
|
||||||
|
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||||
|
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||||
|
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||||
|
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||||
|
m_ColorMultiplier: 1
|
||||||
|
m_FadeDuration: 0.1
|
||||||
|
m_SpriteState:
|
||||||
|
m_HighlightedSprite: {fileID: 0}
|
||||||
|
m_PressedSprite: {fileID: 0}
|
||||||
|
m_SelectedSprite: {fileID: 0}
|
||||||
|
m_DisabledSprite: {fileID: 0}
|
||||||
|
m_AnimationTriggers:
|
||||||
|
m_NormalTrigger: Normal
|
||||||
|
m_HighlightedTrigger: Highlighted
|
||||||
|
m_PressedTrigger: Pressed
|
||||||
|
m_SelectedTrigger: Selected
|
||||||
|
m_DisabledTrigger: Disabled
|
||||||
|
m_Interactable: 1
|
||||||
|
m_TargetGraphic: {fileID: 6068113733588841294}
|
||||||
|
m_OnClick:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a87e3a74be955cd489afbc0a2017918c
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &2045156765410135627
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 6829790168465005869}
|
||||||
|
- component: {fileID: 7162218751441840752}
|
||||||
|
- component: {fileID: 9173331527254647834}
|
||||||
|
- component: {fileID: 5123401824409210736}
|
||||||
|
m_Layer: 5
|
||||||
|
m_Name: LogItem
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!224 &6829790168465005869
|
||||||
|
RectTransform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2045156765410135627}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
m_AnchorMin: {x: 0, y: 1}
|
||||||
|
m_AnchorMax: {x: 0, y: 1}
|
||||||
|
m_AnchoredPosition: {x: 259, y: -23.5}
|
||||||
|
m_SizeDelta: {x: 518, y: 47}
|
||||||
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
|
--- !u!222 &7162218751441840752
|
||||||
|
CanvasRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2045156765410135627}
|
||||||
|
m_CullTransparentMesh: 1
|
||||||
|
--- !u!114 &9173331527254647834
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2045156765410135627}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
|
m_OnCullStateChanged:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
m_text: '[hit] '
|
||||||
|
m_isRightToLeft: 0
|
||||||
|
m_fontAsset: {fileID: 11400000, guid: 02c06ea46dc9ddc4298265b674b5c1f3, type: 2}
|
||||||
|
m_sharedMaterial: {fileID: -2272909990543428095, guid: 02c06ea46dc9ddc4298265b674b5c1f3, type: 2}
|
||||||
|
m_fontSharedMaterials: []
|
||||||
|
m_fontMaterial: {fileID: 0}
|
||||||
|
m_fontMaterials: []
|
||||||
|
m_fontColor32:
|
||||||
|
serializedVersion: 2
|
||||||
|
rgba: 4278519045
|
||||||
|
m_fontColor: {r: 0.019607844, g: 0.019607844, b: 0.019607844, a: 1}
|
||||||
|
m_enableVertexGradient: 0
|
||||||
|
m_colorMode: 3
|
||||||
|
m_fontColorGradient:
|
||||||
|
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_fontColorGradientPreset: {fileID: 0}
|
||||||
|
m_spriteAsset: {fileID: 0}
|
||||||
|
m_tintAllSprites: 0
|
||||||
|
m_StyleSheet: {fileID: 0}
|
||||||
|
m_TextStyleHashCode: -1183493901
|
||||||
|
m_overrideHtmlColors: 0
|
||||||
|
m_faceColor:
|
||||||
|
serializedVersion: 2
|
||||||
|
rgba: 4294967295
|
||||||
|
m_fontSize: 45
|
||||||
|
m_fontSizeBase: 45
|
||||||
|
m_fontWeight: 400
|
||||||
|
m_enableAutoSizing: 0
|
||||||
|
m_fontSizeMin: 18
|
||||||
|
m_fontSizeMax: 72
|
||||||
|
m_fontStyle: 0
|
||||||
|
m_HorizontalAlignment: 1
|
||||||
|
m_VerticalAlignment: 256
|
||||||
|
m_textAlignment: 65535
|
||||||
|
m_characterSpacing: 0
|
||||||
|
m_wordSpacing: 0
|
||||||
|
m_lineSpacing: 0
|
||||||
|
m_lineSpacingMax: 0
|
||||||
|
m_paragraphSpacing: 0
|
||||||
|
m_charWidthMaxAdj: 0
|
||||||
|
m_enableWordWrapping: 1
|
||||||
|
m_wordWrappingRatios: 0.4
|
||||||
|
m_overflowMode: 0
|
||||||
|
m_linkedTextComponent: {fileID: 0}
|
||||||
|
parentLinkedComponent: {fileID: 0}
|
||||||
|
m_enableKerning: 1
|
||||||
|
m_enableExtraPadding: 0
|
||||||
|
checkPaddingRequired: 0
|
||||||
|
m_isRichText: 1
|
||||||
|
m_parseCtrlCharacters: 1
|
||||||
|
m_isOrthographic: 1
|
||||||
|
m_isCullingEnabled: 0
|
||||||
|
m_horizontalMapping: 0
|
||||||
|
m_verticalMapping: 0
|
||||||
|
m_uvLineOffset: 0
|
||||||
|
m_geometrySortingOrder: 0
|
||||||
|
m_IsTextObjectScaleStatic: 0
|
||||||
|
m_VertexBufferAutoSizeReduction: 0
|
||||||
|
m_useMaxVisibleDescender: 1
|
||||||
|
m_pageToDisplay: 1
|
||||||
|
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_isUsingLegacyAnimationComponent: 0
|
||||||
|
m_isVolumetricText: 0
|
||||||
|
m_hasFontAssetChanged: 0
|
||||||
|
m_baseMaterial: {fileID: 0}
|
||||||
|
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
--- !u!114 &5123401824409210736
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2045156765410135627}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: d594815f47f84f758ecf3e198de8d8de, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
textComponent: {fileID: 9173331527254647834}
|
||||||
|
horizontalPadding: 0
|
||||||
|
verticalPadding: 0
|
||||||
|
clampToParentWidth: 1
|
||||||
|
minWidth: 200
|
||||||
|
minHeight: 47
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ef8d46c253ef36e4ab74f4106405ecbf
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -50,6 +50,6 @@ MonoBehaviour:
|
||||||
deAudioEnabled: 0
|
deAudioEnabled: 0
|
||||||
deUnityExtendedEnabled: 0
|
deUnityExtendedEnabled: 0
|
||||||
epoOutlineEnabled: 0
|
epoOutlineEnabled: 0
|
||||||
createASMDEF: 0
|
createASMDEF: 1
|
||||||
showPlayingTweens: 0
|
showPlayingTweens: 0
|
||||||
showPausedTweens: 0
|
showPausedTweens: 0
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 85bc7cc748291a344ba0188b5c2c378b
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace VMdemo.Core
|
||||||
|
{
|
||||||
|
public enum AddressGenerationMode
|
||||||
|
{
|
||||||
|
RandomUniform = 0,
|
||||||
|
SequentialArrayLoop = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7d91aaaf0f71455ba5f1707f02b3f7b7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -40,9 +40,21 @@ namespace VMdemo.Core
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.vaBits != 32 && config.vaBits != 48 && config.vaBits != 64)
|
if (config.machineBits <= 0 || config.machineBits > 64)
|
||||||
{
|
{
|
||||||
errorMessage = "vaBits 仅支持 32、48、64。";
|
errorMessage = "machineBits 必须在 1 到 64 之间。";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.vaBits != 8 && config.vaBits != 16 && config.vaBits != 24)
|
||||||
|
{
|
||||||
|
errorMessage = "vaBits 仅支持 8、16、24。";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.vaBits > config.machineBits)
|
||||||
|
{
|
||||||
|
errorMessage = $"vaBits 不能大于 machineBits,当前 vaBits={config.vaBits}, machineBits={config.machineBits}。";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,6 +94,31 @@ namespace VMdemo.Core
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.arrayLengthBytes <= 0)
|
||||||
|
{
|
||||||
|
errorMessage = "arrayLengthBytes 必须是正整数。";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.arrayElementBytes <= 0)
|
||||||
|
{
|
||||||
|
errorMessage = "arrayElementBytes 必须是正整数。";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.arrayBaseAddress < 0)
|
||||||
|
{
|
||||||
|
errorMessage = "arrayBaseAddress 不能为负数。";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.addressGenerationMode == AddressGenerationMode.SequentialArrayLoop &&
|
||||||
|
config.arrayLengthBytes < config.arrayElementBytes)
|
||||||
|
{
|
||||||
|
errorMessage = "SequentialArrayLoop 模式下 arrayLengthBytes 必须 >= arrayElementBytes。";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var pageSizeBytes = config.PageSizeBytes;
|
var pageSizeBytes = config.PageSizeBytes;
|
||||||
if (!TryGetLog2(pageSizeBytes, out var offsetBits))
|
if (!TryGetLog2(pageSizeBytes, out var offsetBits))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,32 @@ namespace VMdemo.Core
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class SimulationConfig
|
public class SimulationConfig
|
||||||
{
|
{
|
||||||
public int vaBits = 32;
|
public const int FixedMachineBits = 32;
|
||||||
public int pageSizeKB = 4;
|
public const int FixedVaBits = 24;
|
||||||
public int physicalMemoryMB = 64;
|
public const int FixedPageSizeKB = 4;
|
||||||
public int tlbEntries = 16;
|
public const int FixedPhysicalMemoryMB = 1;
|
||||||
|
public const int FixedTlbEntries = 8;
|
||||||
|
|
||||||
|
public int machineBits = FixedMachineBits;
|
||||||
|
public int vaBits = FixedVaBits;
|
||||||
|
public int pageSizeKB = FixedPageSizeKB;
|
||||||
|
public int physicalMemoryMB = FixedPhysicalMemoryMB;
|
||||||
|
public int tlbEntries = FixedTlbEntries;
|
||||||
public int accessCount = 100;
|
public int accessCount = 100;
|
||||||
public int pageFaultPenalty = 100;
|
public int pageFaultPenalty = 100;
|
||||||
|
public AddressGenerationMode addressGenerationMode = AddressGenerationMode.SequentialArrayLoop;
|
||||||
|
public int arrayLengthBytes = 256;
|
||||||
|
public int arrayElementBytes = 4;
|
||||||
|
public int arrayBaseAddress = 0;
|
||||||
|
|
||||||
|
public void ApplyFixedCoreSpec()
|
||||||
|
{
|
||||||
|
machineBits = FixedMachineBits;
|
||||||
|
vaBits = FixedVaBits;
|
||||||
|
pageSizeKB = FixedPageSizeKB;
|
||||||
|
physicalMemoryMB = FixedPhysicalMemoryMB;
|
||||||
|
tlbEntries = FixedTlbEntries;
|
||||||
|
}
|
||||||
|
|
||||||
public ulong PageSizeBytes => pageSizeKB > 0 ? (ulong)pageSizeKB * 1024UL : 0UL;
|
public ulong PageSizeBytes => pageSizeKB > 0 ? (ulong)pageSizeKB * 1024UL : 0UL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using VMdemo.Core;
|
||||||
|
|
||||||
namespace VMdemo.Simulation
|
namespace VMdemo.Simulation
|
||||||
{
|
{
|
||||||
|
|
@ -6,28 +7,74 @@ namespace VMdemo.Simulation
|
||||||
{
|
{
|
||||||
public const int DefaultSeed = 12345;
|
public const int DefaultSeed = 12345;
|
||||||
|
|
||||||
private readonly int _vaBits;
|
|
||||||
private readonly ulong _vaMask;
|
private readonly ulong _vaMask;
|
||||||
private readonly Random _random;
|
private readonly Random _random;
|
||||||
private readonly byte[] _buffer = new byte[8];
|
private readonly byte[] _buffer = new byte[8];
|
||||||
|
private readonly AddressGenerationMode _mode;
|
||||||
|
private readonly ulong _arrayBaseAddress;
|
||||||
|
private readonly ulong _arrayElementBytes;
|
||||||
|
private readonly ulong _arrayElementCount;
|
||||||
|
private ulong _nextArrayIndex;
|
||||||
|
|
||||||
public AddressGenerator(int vaBits, int? seed = null)
|
public AddressGenerator(
|
||||||
|
int vaBits,
|
||||||
|
int? seed = null,
|
||||||
|
AddressGenerationMode mode = AddressGenerationMode.RandomUniform,
|
||||||
|
int arrayLengthBytes = 256,
|
||||||
|
int arrayElementBytes = 4,
|
||||||
|
int arrayBaseAddress = 0)
|
||||||
{
|
{
|
||||||
if (vaBits != 32 && vaBits != 48 && vaBits != 64)
|
if (vaBits != 8 && vaBits != 16 && vaBits != 24)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(vaBits), "vaBits 仅支持 32、48、64。");
|
throw new ArgumentOutOfRangeException(nameof(vaBits), "vaBits 仅支持 8、16、24。");
|
||||||
}
|
}
|
||||||
|
|
||||||
_vaBits = vaBits;
|
_vaMask = (1UL << vaBits) - 1UL;
|
||||||
_vaMask = vaBits == 64 ? ulong.MaxValue : (1UL << vaBits) - 1UL;
|
|
||||||
_random = new Random(seed ?? DefaultSeed);
|
_random = new Random(seed ?? DefaultSeed);
|
||||||
|
_mode = mode;
|
||||||
|
|
||||||
|
if (arrayLengthBytes <= 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(arrayLengthBytes), "arrayLengthBytes 必须是正整数。");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrayElementBytes <= 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(arrayElementBytes), "arrayElementBytes 必须是正整数。");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrayBaseAddress < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(arrayBaseAddress), "arrayBaseAddress 不能为负数。");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == AddressGenerationMode.SequentialArrayLoop && arrayLengthBytes < arrayElementBytes)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(
|
||||||
|
nameof(arrayLengthBytes),
|
||||||
|
"SequentialArrayLoop 模式下 arrayLengthBytes 必须 >= arrayElementBytes。");
|
||||||
|
}
|
||||||
|
|
||||||
|
_arrayBaseAddress = (ulong)arrayBaseAddress;
|
||||||
|
_arrayElementBytes = (ulong)arrayElementBytes;
|
||||||
|
_arrayElementCount = Math.Max(1UL, (ulong)arrayLengthBytes / _arrayElementBytes);
|
||||||
|
|
||||||
|
var maxGenerated = _arrayBaseAddress + (_arrayElementCount - 1UL) * _arrayElementBytes;
|
||||||
|
if (maxGenerated > _vaMask)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(
|
||||||
|
nameof(arrayLengthBytes),
|
||||||
|
$"数组访问地址超出 vaBits 范围。maxGenerated={maxGenerated}, maxVA={_vaMask}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong MaxVirtualAddress => _vaMask;
|
public ulong MaxVirtualAddress => _vaMask;
|
||||||
|
|
||||||
public ulong NextVirtualAddress()
|
public ulong NextVirtualAddress()
|
||||||
{
|
{
|
||||||
return NextRawUlong() & _vaMask;
|
return _mode == AddressGenerationMode.SequentialArrayLoop
|
||||||
|
? NextArrayLoopAddress()
|
||||||
|
: (NextRawUlong() & _vaMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ulong NextRawUlong()
|
private ulong NextRawUlong()
|
||||||
|
|
@ -35,5 +82,12 @@ namespace VMdemo.Simulation
|
||||||
_random.NextBytes(_buffer);
|
_random.NextBytes(_buffer);
|
||||||
return BitConverter.ToUInt64(_buffer, 0);
|
return BitConverter.ToUInt64(_buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ulong NextArrayLoopAddress()
|
||||||
|
{
|
||||||
|
var address = _arrayBaseAddress + _nextArrayIndex * _arrayElementBytes;
|
||||||
|
_nextArrayIndex = (_nextArrayIndex + 1UL) % _arrayElementCount;
|
||||||
|
return address;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ namespace VMdemo.Simulation
|
||||||
public bool IsTlbHit { get; set; }
|
public bool IsTlbHit { get; set; }
|
||||||
public bool IsPageTableHit { get; set; }
|
public bool IsPageTableHit { get; set; }
|
||||||
public int CurrentCost { get; set; }
|
public int CurrentCost { get; set; }
|
||||||
|
public string LastDecisionReason { get; set; }
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
|
|
@ -31,6 +32,7 @@ namespace VMdemo.Simulation
|
||||||
IsTlbHit = false;
|
IsTlbHit = false;
|
||||||
IsPageTableHit = false;
|
IsPageTableHit = false;
|
||||||
CurrentCost = 0;
|
CurrentCost = 0;
|
||||||
|
LastDecisionReason = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ namespace VMdemo.Simulation
|
||||||
L1Bits = l1Bits;
|
L1Bits = l1Bits;
|
||||||
L2Bits = l2Bits;
|
L2Bits = l2Bits;
|
||||||
|
|
||||||
_addressGenerator = new AddressGenerator(_config.vaBits, _seed);
|
_addressGenerator = CreateAddressGenerator();
|
||||||
_tlbCache = new TlbCache(_config.tlbEntries);
|
_tlbCache = new TlbCache(_config.tlbEntries);
|
||||||
_pageTable = new TwoLevelPageTable(L1Bits, L2Bits);
|
_pageTable = new TwoLevelPageTable(L1Bits, L2Bits);
|
||||||
_physicalMemoryManager = new PhysicalMemoryManager(_derivedConfig.FrameCount);
|
_physicalMemoryManager = new PhysicalMemoryManager(_derivedConfig.FrameCount);
|
||||||
|
|
@ -91,6 +91,10 @@ namespace VMdemo.Simulation
|
||||||
|
|
||||||
public SimulationState State { get; }
|
public SimulationState State { get; }
|
||||||
public TranslationStep CurrentStep => State.CurrentStep;
|
public TranslationStep CurrentStep => State.CurrentStep;
|
||||||
|
public int MachineBits => _config.machineBits;
|
||||||
|
public int VaBits => _config.vaBits;
|
||||||
|
public int PageSizeKB => _config.pageSizeKB;
|
||||||
|
public int PhysicalMemoryMB => _config.physicalMemoryMB;
|
||||||
public int OffsetBits => _derivedConfig.OffsetBits;
|
public int OffsetBits => _derivedConfig.OffsetBits;
|
||||||
public int L1Bits { get; }
|
public int L1Bits { get; }
|
||||||
public int L2Bits { get; }
|
public int L2Bits { get; }
|
||||||
|
|
@ -109,7 +113,7 @@ namespace VMdemo.Simulation
|
||||||
_pendingForcedVirtualAddress = 0UL;
|
_pendingForcedVirtualAddress = 0UL;
|
||||||
Stats.Reset();
|
Stats.Reset();
|
||||||
|
|
||||||
_addressGenerator = new AddressGenerator(_config.vaBits, _seed);
|
_addressGenerator = CreateAddressGenerator();
|
||||||
_tlbCache = new TlbCache(_config.tlbEntries);
|
_tlbCache = new TlbCache(_config.tlbEntries);
|
||||||
_pageTable = new TwoLevelPageTable(L1Bits, L2Bits);
|
_pageTable = new TwoLevelPageTable(L1Bits, L2Bits);
|
||||||
_physicalMemoryManager = new PhysicalMemoryManager(_derivedConfig.FrameCount);
|
_physicalMemoryManager = new PhysicalMemoryManager(_derivedConfig.FrameCount);
|
||||||
|
|
@ -190,6 +194,7 @@ namespace VMdemo.Simulation
|
||||||
State.CurrentPhysicalAddress = 0UL;
|
State.CurrentPhysicalAddress = 0UL;
|
||||||
State.CurrentPfn = 0UL;
|
State.CurrentPfn = 0UL;
|
||||||
State.HasCurrentPfn = false;
|
State.HasCurrentPfn = false;
|
||||||
|
State.LastDecisionReason = "已生成本轮虚拟地址,准备进行地址拆分。";
|
||||||
_lastEviction = EvictionInfo.None;
|
_lastEviction = EvictionInfo.None;
|
||||||
|
|
||||||
if (_hasPendingForcedVirtualAddress)
|
if (_hasPendingForcedVirtualAddress)
|
||||||
|
|
@ -212,6 +217,7 @@ namespace VMdemo.Simulation
|
||||||
State.CurrentVirtualAddress,
|
State.CurrentVirtualAddress,
|
||||||
_config.vaBits,
|
_config.vaBits,
|
||||||
_derivedConfig.OffsetBits);
|
_derivedConfig.OffsetBits);
|
||||||
|
State.LastDecisionReason = "已拆分 VA 为 VPN/Offset,并从 VPN 拆分出 L1/L2 索引。";
|
||||||
|
|
||||||
State.CurrentStep = TranslationStep.LookupTLB;
|
State.CurrentStep = TranslationStep.LookupTLB;
|
||||||
}
|
}
|
||||||
|
|
@ -223,28 +229,42 @@ namespace VMdemo.Simulation
|
||||||
State.IsTlbHit = true;
|
State.IsTlbHit = true;
|
||||||
State.CurrentPfn = pfn;
|
State.CurrentPfn = pfn;
|
||||||
State.HasCurrentPfn = true;
|
State.HasCurrentPfn = true;
|
||||||
|
State.LastDecisionReason =
|
||||||
|
$"TLB 命中:VPN={State.CurrentAddressParts.Vpn} 命中 PFN={pfn},跳过页表,直接合成物理地址。";
|
||||||
State.CurrentStep = TranslationStep.ComposePA;
|
State.CurrentStep = TranslationStep.ComposePA;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
State.LastDecisionReason =
|
||||||
|
$"TLB 未命中:VPN={State.CurrentAddressParts.Vpn} 未找到映射,转入页表查询。";
|
||||||
State.CurrentStep = TranslationStep.LookupPageTable;
|
State.CurrentStep = TranslationStep.LookupPageTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecuteLookupPageTable()
|
private void ExecuteLookupPageTable()
|
||||||
{
|
{
|
||||||
if (_pageTable.TryGetPresentPfn(
|
var probe = _pageTable.Probe(State.CurrentAddressParts.L1Index, State.CurrentAddressParts.L2Index);
|
||||||
State.CurrentAddressParts.L1Index,
|
if (probe.Status == PageTableProbeStatus.PresentEntry)
|
||||||
State.CurrentAddressParts.L2Index,
|
|
||||||
out var pfn))
|
|
||||||
{
|
{
|
||||||
State.IsPageTableHit = true;
|
State.IsPageTableHit = true;
|
||||||
State.CurrentPfn = pfn;
|
State.CurrentPfn = probe.Entry.Pfn;
|
||||||
State.HasCurrentPfn = true;
|
State.HasCurrentPfn = true;
|
||||||
_tlbCache.InsertOrUpdate(State.CurrentAddressParts.Vpn, pfn);
|
_tlbCache.InsertOrUpdate(State.CurrentAddressParts.Vpn, probe.Entry.Pfn);
|
||||||
|
State.LastDecisionReason =
|
||||||
|
$"页表命中:L1={State.CurrentAddressParts.L1Index}, L2={State.CurrentAddressParts.L2Index}, PFN={probe.Entry.Pfn},并写回 TLB。";
|
||||||
State.CurrentStep = TranslationStep.ComposePA;
|
State.CurrentStep = TranslationStep.ComposePA;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
State.LastDecisionReason = probe.Status switch
|
||||||
|
{
|
||||||
|
PageTableProbeStatus.MissingL1Table =>
|
||||||
|
$"页表未命中:L1={State.CurrentAddressParts.L1Index} 对应二级页表不存在,触发缺页处理。",
|
||||||
|
PageTableProbeStatus.MissingL2Entry =>
|
||||||
|
$"页表未命中:L2={State.CurrentAddressParts.L2Index} 页表项不存在,触发缺页处理。",
|
||||||
|
PageTableProbeStatus.NotPresentEntry =>
|
||||||
|
$"页表项无效:L2={State.CurrentAddressParts.L2Index} present=false,触发缺页处理。",
|
||||||
|
_ => "页表未命中,触发缺页处理。"
|
||||||
|
};
|
||||||
State.CurrentStep = TranslationStep.HandlePageFault;
|
State.CurrentStep = TranslationStep.HandlePageFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -263,6 +283,9 @@ namespace VMdemo.Simulation
|
||||||
State.CurrentPfn = result.Pfn;
|
State.CurrentPfn = result.Pfn;
|
||||||
State.HasCurrentPfn = true;
|
State.HasCurrentPfn = true;
|
||||||
_lastEviction = result.Eviction;
|
_lastEviction = result.Eviction;
|
||||||
|
State.LastDecisionReason = result.Eviction.HasEvicted
|
||||||
|
? $"缺页处理完成:装入 PFN={result.Pfn},并按 FIFO 淘汰 VPN={result.Eviction.EvictedVpn}。"
|
||||||
|
: $"缺页处理完成:装入 PFN={result.Pfn},当前仍有空闲物理帧。";
|
||||||
State.CurrentStep = TranslationStep.ComposePA;
|
State.CurrentStep = TranslationStep.ComposePA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,6 +298,8 @@ namespace VMdemo.Simulation
|
||||||
|
|
||||||
State.CurrentPhysicalAddress =
|
State.CurrentPhysicalAddress =
|
||||||
(State.CurrentPfn << _derivedConfig.OffsetBits) | State.CurrentAddressParts.Offset;
|
(State.CurrentPfn << _derivedConfig.OffsetBits) | State.CurrentAddressParts.Offset;
|
||||||
|
State.LastDecisionReason =
|
||||||
|
$"物理地址合成:PA = (PFN << offsetBits) | offset = ({State.CurrentPfn} << {_derivedConfig.OffsetBits}) | {State.CurrentAddressParts.Offset}。";
|
||||||
|
|
||||||
State.CurrentStep = TranslationStep.Finalize;
|
State.CurrentStep = TranslationStep.Finalize;
|
||||||
}
|
}
|
||||||
|
|
@ -291,6 +316,11 @@ namespace VMdemo.Simulation
|
||||||
State.IsPageTableHit,
|
State.IsPageTableHit,
|
||||||
State.IsPageFault,
|
State.IsPageFault,
|
||||||
State.CurrentCost);
|
State.CurrentCost);
|
||||||
|
State.LastDecisionReason = State.IsPageFault
|
||||||
|
? $"本轮完成:TLB 未命中 + 页表未命中,发生缺页,开销={State.CurrentCost}。"
|
||||||
|
: State.IsTlbHit
|
||||||
|
? $"本轮完成:TLB 命中,开销={State.CurrentCost}。"
|
||||||
|
: $"本轮完成:TLB 未命中 + 页表命中,开销={State.CurrentCost}。";
|
||||||
|
|
||||||
State.CurrentRound += 1;
|
State.CurrentRound += 1;
|
||||||
State.CurrentStep = TranslationStep.GenerateVA;
|
State.CurrentStep = TranslationStep.GenerateVA;
|
||||||
|
|
@ -298,10 +328,21 @@ namespace VMdemo.Simulation
|
||||||
|
|
||||||
private void EnsureVirtualAddressInRange(ulong virtualAddress)
|
private void EnsureVirtualAddressInRange(ulong virtualAddress)
|
||||||
{
|
{
|
||||||
if (_config.vaBits < 64 && virtualAddress > _addressGenerator.MaxVirtualAddress)
|
if (virtualAddress > _addressGenerator.MaxVirtualAddress)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(virtualAddress), "virtualAddress 超出 vaBits 可表示范围。");
|
throw new ArgumentOutOfRangeException(nameof(virtualAddress), "virtualAddress 超出 vaBits 可表示范围。");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AddressGenerator CreateAddressGenerator()
|
||||||
|
{
|
||||||
|
return new AddressGenerator(
|
||||||
|
_config.vaBits,
|
||||||
|
_seed,
|
||||||
|
_config.addressGenerationMode,
|
||||||
|
_config.arrayLengthBytes,
|
||||||
|
_config.arrayElementBytes,
|
||||||
|
_config.arrayBaseAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,28 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace VMdemo.Simulation
|
namespace VMdemo.Simulation
|
||||||
{
|
{
|
||||||
|
public enum PageTableProbeStatus
|
||||||
|
{
|
||||||
|
MissingL1Table = 0,
|
||||||
|
MissingL2Entry = 1,
|
||||||
|
NotPresentEntry = 2,
|
||||||
|
PresentEntry = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct PageTableProbeResult
|
||||||
|
{
|
||||||
|
public PageTableProbeResult(PageTableProbeStatus status, bool hasEntry, PageTableEntry entry)
|
||||||
|
{
|
||||||
|
Status = status;
|
||||||
|
HasEntry = hasEntry;
|
||||||
|
Entry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PageTableProbeStatus Status { get; }
|
||||||
|
public bool HasEntry { get; }
|
||||||
|
public PageTableEntry Entry { get; }
|
||||||
|
}
|
||||||
|
|
||||||
public class TwoLevelPageTable
|
public class TwoLevelPageTable
|
||||||
{
|
{
|
||||||
private readonly Dictionary<ulong, Dictionary<ulong, PageTableEntry>> _table;
|
private readonly Dictionary<ulong, Dictionary<ulong, PageTableEntry>> _table;
|
||||||
|
|
@ -73,6 +95,40 @@ namespace VMdemo.Simulation
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PageTableProbeResult Probe(ulong l1Index, ulong l2Index)
|
||||||
|
{
|
||||||
|
ValidateIndices(l1Index, l2Index);
|
||||||
|
|
||||||
|
if (!_table.TryGetValue(l1Index, out var l2Table))
|
||||||
|
{
|
||||||
|
return new PageTableProbeResult(
|
||||||
|
PageTableProbeStatus.MissingL1Table,
|
||||||
|
hasEntry: false,
|
||||||
|
entry: PageTableEntry.NotPresent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!l2Table.TryGetValue(l2Index, out var entry))
|
||||||
|
{
|
||||||
|
return new PageTableProbeResult(
|
||||||
|
PageTableProbeStatus.MissingL2Entry,
|
||||||
|
hasEntry: false,
|
||||||
|
entry: PageTableEntry.NotPresent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entry.Present)
|
||||||
|
{
|
||||||
|
return new PageTableProbeResult(
|
||||||
|
PageTableProbeStatus.NotPresentEntry,
|
||||||
|
hasEntry: true,
|
||||||
|
entry: entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PageTableProbeResult(
|
||||||
|
PageTableProbeStatus.PresentEntry,
|
||||||
|
hasEntry: true,
|
||||||
|
entry: entry);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetPresent(ulong l1Index, ulong l2Index, ulong pfn, bool dirty = false)
|
public void SetPresent(ulong l1Index, ulong l2Index, ulong pfn, bool dirty = false)
|
||||||
{
|
{
|
||||||
ValidateIndices(l1Index, l2Index);
|
ValidateIndices(l1Index, l2Index);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,232 @@
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using VMdemo.Core;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public class SimulationConfigInputView : MonoBehaviour
|
||||||
|
{
|
||||||
|
[Header("Fixed Core Spec")] [SerializeField]
|
||||||
|
private TMP_Text fixedCoreSpecText;
|
||||||
|
|
||||||
|
[SerializeField] private TMP_InputField accessCountInput;
|
||||||
|
[SerializeField] private TMP_InputField pageFaultPenaltyInput;
|
||||||
|
[SerializeField] private TMP_Dropdown addressModeDropdown;
|
||||||
|
[SerializeField] private TMP_InputField arrayLengthBytesInput;
|
||||||
|
[SerializeField] private TMP_InputField arrayElementBytesInput;
|
||||||
|
[SerializeField] private TMP_InputField arrayBaseAddressInput;
|
||||||
|
|
||||||
|
[SerializeField] private Button saveButton;
|
||||||
|
[SerializeField] private Button cancelButton;
|
||||||
|
[SerializeField] private GameObject panelRoot;
|
||||||
|
|
||||||
|
public event Action SaveClicked;
|
||||||
|
public event Action CancelClicked;
|
||||||
|
public bool IsPanelVisible => panelRoot != null ? panelRoot.activeInHierarchy : gameObject.activeInHierarchy;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
BindButtons();
|
||||||
|
ApplyFixedCoreSpecVisual();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryBuildConfig(out SimulationConfig config, out string errorMessage)
|
||||||
|
{
|
||||||
|
config = new SimulationConfig
|
||||||
|
{
|
||||||
|
machineBits = SimulationConfig.FixedMachineBits,
|
||||||
|
vaBits = SimulationConfig.FixedVaBits,
|
||||||
|
pageSizeKB = SimulationConfig.FixedPageSizeKB,
|
||||||
|
physicalMemoryMB = SimulationConfig.FixedPhysicalMemoryMB,
|
||||||
|
tlbEntries = SimulationConfig.FixedTlbEntries,
|
||||||
|
accessCount = ParseInt(accessCountInput, 100),
|
||||||
|
pageFaultPenalty = ParseInt(pageFaultPenaltyInput, 100),
|
||||||
|
addressGenerationMode = ReadAddressGenerationMode(),
|
||||||
|
arrayLengthBytes = ParseInt(arrayLengthBytesInput, 256),
|
||||||
|
arrayElementBytes = ParseInt(arrayElementBytesInput, 4),
|
||||||
|
arrayBaseAddress = ParseInt(arrayBaseAddressInput, 0)
|
||||||
|
};
|
||||||
|
config.ApplyFixedCoreSpec();
|
||||||
|
|
||||||
|
return ConfigValidator.TryValidate(config, out errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PopulateFromConfig(SimulationConfig config)
|
||||||
|
{
|
||||||
|
if (config == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetInputText(accessCountInput, config.accessCount);
|
||||||
|
SetInputText(pageFaultPenaltyInput, config.pageFaultPenalty);
|
||||||
|
SetAddressGenerationMode(config.addressGenerationMode);
|
||||||
|
SetInputText(arrayLengthBytesInput, config.arrayLengthBytes);
|
||||||
|
SetInputText(arrayElementBytesInput, config.arrayElementBytes);
|
||||||
|
SetInputText(arrayBaseAddressInput, config.arrayBaseAddress);
|
||||||
|
|
||||||
|
ApplyFixedCoreSpecVisual();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPanelVisible(bool visible)
|
||||||
|
{
|
||||||
|
if (panelRoot != null)
|
||||||
|
{
|
||||||
|
panelRoot.SetActive(visible);
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
ApplyFixedCoreSpecVisual();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gameObject.SetActive(visible);
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
ApplyFixedCoreSpecVisual();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindButtons()
|
||||||
|
{
|
||||||
|
if (saveButton != null)
|
||||||
|
{
|
||||||
|
saveButton.onClick.RemoveAllListeners();
|
||||||
|
saveButton.onClick.AddListener(() => SaveClicked?.Invoke());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancelButton != null)
|
||||||
|
{
|
||||||
|
cancelButton.onClick.RemoveAllListeners();
|
||||||
|
cancelButton.onClick.AddListener(() => CancelClicked?.Invoke());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyFixedCoreSpecVisual()
|
||||||
|
{
|
||||||
|
if (fixedCoreSpecText != null)
|
||||||
|
{
|
||||||
|
fixedCoreSpecText.text =
|
||||||
|
$"{SimulationConfig.FixedMachineBits}位机\n" +
|
||||||
|
$"VA {SimulationConfig.FixedVaBits}位\n" +
|
||||||
|
$"页大小 {SimulationConfig.FixedPageSizeKB}KB\n" +
|
||||||
|
$"物理内存 {SimulationConfig.FixedPhysicalMemoryMB}MB\n" +
|
||||||
|
$"TLB {SimulationConfig.FixedTlbEntries}条全相联";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetInputText(TMP_InputField input, int value)
|
||||||
|
{
|
||||||
|
if (input != null)
|
||||||
|
{
|
||||||
|
input.text = value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetInteractable(Selectable selectable, bool interactable)
|
||||||
|
{
|
||||||
|
if (selectable != null)
|
||||||
|
{
|
||||||
|
selectable.interactable = interactable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AddressGenerationMode ReadAddressGenerationMode()
|
||||||
|
{
|
||||||
|
if (addressModeDropdown == null || addressModeDropdown.options == null ||
|
||||||
|
addressModeDropdown.options.Count == 0)
|
||||||
|
{
|
||||||
|
return AddressGenerationMode.SequentialArrayLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preferred convention:
|
||||||
|
// index 0 = RandomUniform, index 1 = SequentialArrayLoop.
|
||||||
|
if (addressModeDropdown.options.Count >= 2)
|
||||||
|
{
|
||||||
|
return addressModeDropdown.value == 0
|
||||||
|
? AddressGenerationMode.RandomUniform
|
||||||
|
: AddressGenerationMode.SequentialArrayLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
var option = addressModeDropdown.options[addressModeDropdown.value].text;
|
||||||
|
if (IsRandomOption(option))
|
||||||
|
{
|
||||||
|
return AddressGenerationMode.RandomUniform;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsSequentialOption(option))
|
||||||
|
{
|
||||||
|
return AddressGenerationMode.SequentialArrayLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AddressGenerationMode.SequentialArrayLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetAddressGenerationMode(AddressGenerationMode mode)
|
||||||
|
{
|
||||||
|
if (addressModeDropdown == null || addressModeDropdown.options == null ||
|
||||||
|
addressModeDropdown.options.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addressModeDropdown.options.Count >= 2)
|
||||||
|
{
|
||||||
|
addressModeDropdown.value = mode == AddressGenerationMode.RandomUniform ? 0 : 1;
|
||||||
|
addressModeDropdown.RefreshShownValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < addressModeDropdown.options.Count; i++)
|
||||||
|
{
|
||||||
|
var option = addressModeDropdown.options[i].text;
|
||||||
|
if ((mode == AddressGenerationMode.RandomUniform && IsRandomOption(option)) ||
|
||||||
|
(mode == AddressGenerationMode.SequentialArrayLoop && IsSequentialOption(option)))
|
||||||
|
{
|
||||||
|
addressModeDropdown.value = i;
|
||||||
|
addressModeDropdown.RefreshShownValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsRandomOption(string optionText)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(optionText))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return optionText.Contains("Random") ||
|
||||||
|
optionText.Contains("随机") ||
|
||||||
|
optionText.Contains("rand");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsSequentialOption(string optionText)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(optionText))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return optionText.Contains("Sequential") ||
|
||||||
|
optionText.Contains("ArrayLoop") ||
|
||||||
|
optionText.Contains("数组") ||
|
||||||
|
optionText.Contains("顺序") ||
|
||||||
|
optionText.Contains("for");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ParseInt(TMP_InputField input, int fallback)
|
||||||
|
{
|
||||||
|
if (input == null)
|
||||||
|
{
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
return int.TryParse(input.text, out var value) ? value : fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 93f3af00cf194cf4bf98f5df86f86ffc
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public class SimulationControlView : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private Button stepButton;
|
||||||
|
[SerializeField] private Button playButton;
|
||||||
|
[SerializeField] private Button pauseButton;
|
||||||
|
[SerializeField] private Button resetButton;
|
||||||
|
|
||||||
|
public event Action StepClicked;
|
||||||
|
public event Action PlayClicked;
|
||||||
|
public event Action PauseClicked;
|
||||||
|
public event Action ResetClicked;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
Bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPlaying(bool isPlaying)
|
||||||
|
{
|
||||||
|
if (stepButton != null)
|
||||||
|
{
|
||||||
|
stepButton.interactable = !isPlaying;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playButton != null)
|
||||||
|
{
|
||||||
|
playButton.interactable = !isPlaying;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pauseButton != null)
|
||||||
|
{
|
||||||
|
pauseButton.interactable = isPlaying;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resetButton != null)
|
||||||
|
{
|
||||||
|
resetButton.interactable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Bind()
|
||||||
|
{
|
||||||
|
if (stepButton != null)
|
||||||
|
{
|
||||||
|
stepButton.onClick.RemoveAllListeners();
|
||||||
|
stepButton.onClick.AddListener(() => StepClicked?.Invoke());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playButton != null)
|
||||||
|
{
|
||||||
|
playButton.onClick.RemoveAllListeners();
|
||||||
|
playButton.onClick.AddListener(() => PlayClicked?.Invoke());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pauseButton != null)
|
||||||
|
{
|
||||||
|
pauseButton.onClick.RemoveAllListeners();
|
||||||
|
pauseButton.onClick.AddListener(() => PauseClicked?.Invoke());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resetButton != null)
|
||||||
|
{
|
||||||
|
resetButton.onClick.RemoveAllListeners();
|
||||||
|
resetButton.onClick.AddListener(() => ResetClicked?.Invoke());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 40ec73de0f6f4717a043fc64ff3c3b13
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using VMdemo.Simulation;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public class SimulationDashboardView : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private TMP_Text stateSummaryText;
|
||||||
|
[SerializeField] private TMP_Text statsText;
|
||||||
|
[SerializeField] private TMP_Text errorText;
|
||||||
|
|
||||||
|
public void ShowNotInitialized()
|
||||||
|
{
|
||||||
|
SetText(stateSummaryText, "引擎:未初始化");
|
||||||
|
SetText(statsText, "统计:N/A");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render(TranslatorEngine engine)
|
||||||
|
{
|
||||||
|
if (engine == null)
|
||||||
|
{
|
||||||
|
ShowNotInitialized();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetText(
|
||||||
|
stateSummaryText,
|
||||||
|
SimulationUIFormatter.FormatStateSummary(
|
||||||
|
engine.State,
|
||||||
|
engine.MachineBits,
|
||||||
|
engine.VaBits,
|
||||||
|
engine.PageSizeKB,
|
||||||
|
engine.PhysicalMemoryMB,
|
||||||
|
engine.TlbCache.Capacity));
|
||||||
|
SetText(statsText, SimulationUIFormatter.FormatStats(engine.Stats));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetError(string message)
|
||||||
|
{
|
||||||
|
SetText(errorText, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetText(TMP_Text target, string value)
|
||||||
|
{
|
||||||
|
if (target != null)
|
||||||
|
{
|
||||||
|
target.text = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9b68de53ac3e4c49a27b25bf5f91821b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public class SimulationDetailDrawerView : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private GameObject drawerRoot;
|
||||||
|
[SerializeField] private GameObject tablesTabRoot;
|
||||||
|
[SerializeField] private GameObject eventsTabRoot;
|
||||||
|
[SerializeField] private bool openOnStart;
|
||||||
|
|
||||||
|
[Header("Drawer Buttons")] [SerializeField]
|
||||||
|
private Button tablesTabButton;
|
||||||
|
|
||||||
|
[SerializeField] private Button eventsTabButton;
|
||||||
|
[SerializeField] private Button closeDrawerButton;
|
||||||
|
|
||||||
|
private bool _isOpen;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
BindButtons();
|
||||||
|
_isOpen = openOnStart;
|
||||||
|
ApplyDrawerState();
|
||||||
|
|
||||||
|
ShowTablesTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleDrawer()
|
||||||
|
{
|
||||||
|
_isOpen = !_isOpen;
|
||||||
|
ApplyDrawerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenDrawer()
|
||||||
|
{
|
||||||
|
_isOpen = true;
|
||||||
|
ApplyDrawerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseDrawer()
|
||||||
|
{
|
||||||
|
_isOpen = false;
|
||||||
|
ApplyDrawerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowTablesTab()
|
||||||
|
{
|
||||||
|
SetActiveSafe(tablesTabRoot, true);
|
||||||
|
SetActiveSafe(eventsTabRoot, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowEventsTab()
|
||||||
|
{
|
||||||
|
SetActiveSafe(tablesTabRoot, false);
|
||||||
|
SetActiveSafe(eventsTabRoot, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindButtons()
|
||||||
|
{
|
||||||
|
if (tablesTabButton != null)
|
||||||
|
{
|
||||||
|
tablesTabButton.onClick.RemoveAllListeners();
|
||||||
|
tablesTabButton.onClick.AddListener(ShowTablesTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventsTabButton != null)
|
||||||
|
{
|
||||||
|
eventsTabButton.onClick.RemoveAllListeners();
|
||||||
|
eventsTabButton.onClick.AddListener(ShowEventsTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closeDrawerButton != null)
|
||||||
|
{
|
||||||
|
closeDrawerButton.onClick.RemoveAllListeners();
|
||||||
|
closeDrawerButton.onClick.AddListener(CloseDrawer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyDrawerState()
|
||||||
|
{
|
||||||
|
SetActiveSafe(drawerRoot, _isOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetActiveSafe(GameObject target, bool active)
|
||||||
|
{
|
||||||
|
if (target != null)
|
||||||
|
{
|
||||||
|
target.SetActive(active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 58e1bc0dfbbf46b7b64e6d6d74fd5f24
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using VMdemo.Simulation;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public class SimulationProcessHeaderView : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private TMP_Text currentStepText;
|
||||||
|
[SerializeField] private TMP_Text currentEventText;
|
||||||
|
|
||||||
|
public void RenderStep(SimulationState state)
|
||||||
|
{
|
||||||
|
if (state == null)
|
||||||
|
{
|
||||||
|
SetText(currentStepText, "步骤:N/A");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetText(currentStepText, $"步骤:{TranslationStepDisplay.ToChinese(state.CurrentStep)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetEvent(string message)
|
||||||
|
{
|
||||||
|
SetText(currentEventText, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetText(TMP_Text target, string text)
|
||||||
|
{
|
||||||
|
if (target != null)
|
||||||
|
{
|
||||||
|
target.text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 71f3b95f31a74ef98ffd50e2f6435c20
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using VMdemo.Simulation;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public class SimulationTablesView : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private TMP_Text tlbText;
|
||||||
|
[SerializeField] private TMP_Text pageTableText;
|
||||||
|
[SerializeField] private TMP_Text fifoText;
|
||||||
|
|
||||||
|
public void ShowNotInitialized()
|
||||||
|
{
|
||||||
|
SetText(tlbText, "TLB:N/A");
|
||||||
|
SetText(pageTableText, "页表:N/A");
|
||||||
|
SetText(fifoText, "FIFO:N/A");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render(TranslatorEngine engine)
|
||||||
|
{
|
||||||
|
if (engine == null)
|
||||||
|
{
|
||||||
|
ShowNotInitialized();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var vpnBits = engine.VaBits - engine.OffsetBits;
|
||||||
|
var pfnBits = SimulationUIFormatter.ComputeBitsForCount(engine.PhysicalMemoryManager.FrameCount);
|
||||||
|
SetText(
|
||||||
|
tlbText,
|
||||||
|
SimulationUIFormatter.FormatTlbTable(
|
||||||
|
engine.TlbCache.GetEntriesMostRecentFirst(),
|
||||||
|
vpnBits,
|
||||||
|
pfnBits));
|
||||||
|
SetText(pageTableText, SimulationUIFormatter.FormatCurrentPageTableEntry(engine.State, engine.PageTable, engine.LastEviction));
|
||||||
|
SetText(fifoText, SimulationUIFormatter.FormatFifoQueue(engine.PhysicalMemoryManager.GetFifoVpnOrder()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetText(TMP_Text target, string value)
|
||||||
|
{
|
||||||
|
if (target != null)
|
||||||
|
{
|
||||||
|
target.text = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 68f3ab1453614176a0f66589d29a55dd
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public class SimulationTimelineView : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private RectTransform logContainer;
|
||||||
|
[SerializeField] private TMP_Text logItemPrefab;
|
||||||
|
[SerializeField] private ScrollRect logScrollRect;
|
||||||
|
[SerializeField] private int maxLogEntries = 200;
|
||||||
|
|
||||||
|
private readonly Queue<TMP_Text> _logItems = new Queue<TMP_Text>();
|
||||||
|
|
||||||
|
public void Append(string message)
|
||||||
|
{
|
||||||
|
if (logContainer == null || logItemPrefab == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var item = Instantiate(logItemPrefab, logContainer);
|
||||||
|
item.gameObject.SetActive(true);
|
||||||
|
item.text = message;
|
||||||
|
item.ForceMeshUpdate();
|
||||||
|
|
||||||
|
var autoSize = item.GetComponent<TimelineLogItemAutoSize>();
|
||||||
|
if (autoSize != null)
|
||||||
|
{
|
||||||
|
autoSize.RefreshLayout();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback: adapt this text object's rect to preferred content size.
|
||||||
|
var preferred = item.GetPreferredValues(item.text, logContainer.rect.width, 0f);
|
||||||
|
var rect = item.rectTransform;
|
||||||
|
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, preferred.x);
|
||||||
|
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, preferred.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logItems.Enqueue(item);
|
||||||
|
|
||||||
|
while (_logItems.Count > Mathf.Max(1, maxLogEntries))
|
||||||
|
{
|
||||||
|
var old = _logItems.Dequeue();
|
||||||
|
if (old != null)
|
||||||
|
{
|
||||||
|
Destroy(old.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutRebuilder.ForceRebuildLayoutImmediate(logContainer);
|
||||||
|
Canvas.ForceUpdateCanvases();
|
||||||
|
if (logScrollRect != null)
|
||||||
|
{
|
||||||
|
logScrollRect.verticalNormalizedPosition = 0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
while (_logItems.Count > 0)
|
||||||
|
{
|
||||||
|
var item = _logItems.Dequeue();
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
Destroy(item.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c65bcc42d5bf440ca80a93cc5a2f1fc1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using VMdemo.Simulation;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public class SimulationTraceView : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private TMP_Text splitTraceText;
|
||||||
|
[SerializeField] private TMP_Text pageTableTraceText;
|
||||||
|
[SerializeField] private TMP_Text decisionReasonText;
|
||||||
|
[SerializeField] private TMP_Text pathSummaryText;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
EnsureRichTextEnabled(splitTraceText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowNotInitialized()
|
||||||
|
{
|
||||||
|
SetText(splitTraceText, "地址拆分可视化:N/A");
|
||||||
|
SetText(pageTableTraceText, "多级页表查询可视化:N/A");
|
||||||
|
SetText(decisionReasonText, "分支原因:N/A");
|
||||||
|
SetText(pathSummaryText, "路径摘要:N/A");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render(TranslatorEngine engine)
|
||||||
|
{
|
||||||
|
if (engine == null)
|
||||||
|
{
|
||||||
|
ShowNotInitialized();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetText(
|
||||||
|
splitTraceText,
|
||||||
|
SimulationUIFormatter.FormatAddressSplitTrace(
|
||||||
|
engine.State,
|
||||||
|
engine.VaBits,
|
||||||
|
engine.OffsetBits,
|
||||||
|
engine.L1Bits,
|
||||||
|
engine.L2Bits));
|
||||||
|
|
||||||
|
SetText(
|
||||||
|
pageTableTraceText,
|
||||||
|
SimulationUIFormatter.FormatPageTableWalkTrace(engine.State, engine.PageTable));
|
||||||
|
|
||||||
|
SetText(
|
||||||
|
decisionReasonText,
|
||||||
|
string.IsNullOrEmpty(engine.State.LastDecisionReason)
|
||||||
|
? "分支原因:暂无"
|
||||||
|
: $"分支原因:{engine.State.LastDecisionReason}");
|
||||||
|
|
||||||
|
SetText(pathSummaryText, BuildPathSummary(engine.State));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildPathSummary(SimulationState state)
|
||||||
|
{
|
||||||
|
if (state == null)
|
||||||
|
{
|
||||||
|
return "路径摘要:N/A";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.IsTlbHit)
|
||||||
|
{
|
||||||
|
return "路径摘要:TLB命中 -> 直接合成PA";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.IsPageTableHit)
|
||||||
|
{
|
||||||
|
return "路径摘要:TLB未命中 -> 页表命中 -> 合成PA";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.IsPageFault)
|
||||||
|
{
|
||||||
|
return "路径摘要:TLB未命中 -> 页表未命中 -> 缺页处理 -> 合成PA";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "路径摘要:进行中";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetText(TMP_Text target, string value)
|
||||||
|
{
|
||||||
|
if (target != null)
|
||||||
|
{
|
||||||
|
target.text = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EnsureRichTextEnabled(TMP_Text target)
|
||||||
|
{
|
||||||
|
if (target != null)
|
||||||
|
{
|
||||||
|
target.richText = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5f6f28922eb241649a4d14b8b6cc6bf7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,458 @@
|
||||||
|
using System.Collections;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using VMdemo.Core;
|
||||||
|
using VMdemo.Simulation;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public class SimulationUIController : MonoBehaviour
|
||||||
|
{
|
||||||
|
[Header("Sub Views")]
|
||||||
|
[SerializeField] private SimulationConfigInputView configInputView;
|
||||||
|
[SerializeField] private SimulationControlView controlView;
|
||||||
|
[SerializeField] private SimulationDashboardView dashboardView;
|
||||||
|
[SerializeField] private SimulationTablesView tablesView;
|
||||||
|
[SerializeField] private SimulationTraceView traceView;
|
||||||
|
[SerializeField] private SimulationTimelineView detailTimelineView;
|
||||||
|
[SerializeField] private SimulationProcessHeaderView processHeaderView;
|
||||||
|
[SerializeField] private StepFlowAnimator flowAnimator;
|
||||||
|
[SerializeField] private SimulationDetailDrawerView detailDrawerView;
|
||||||
|
|
||||||
|
[Header("Playback")]
|
||||||
|
[SerializeField] private float playIntervalSeconds = 0.3f;
|
||||||
|
|
||||||
|
private TranslatorEngine _engine;
|
||||||
|
private Coroutine _playRoutine;
|
||||||
|
private SimulationConfig _activeConfig;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
BindControlEvents();
|
||||||
|
controlView?.SetPlaying(false);
|
||||||
|
InitializeEngineIfNeeded();
|
||||||
|
RefreshUI(accessCompleted: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
if (Input.GetKeyDown(KeyCode.Space))
|
||||||
|
{
|
||||||
|
HandleStepHotkey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
StopPlayRoutine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenConfigPanel()
|
||||||
|
{
|
||||||
|
if (configInputView == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
configInputView.PopulateFromConfig(_activeConfig ?? new SimulationConfig());
|
||||||
|
configInputView.SetPanelVisible(true);
|
||||||
|
dashboardView?.SetError(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleDetailDrawer()
|
||||||
|
{
|
||||||
|
detailDrawerView?.ToggleDrawer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenDetailDrawer()
|
||||||
|
{
|
||||||
|
detailDrawerView?.OpenDrawer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseDetailDrawer()
|
||||||
|
{
|
||||||
|
detailDrawerView?.CloseDrawer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowTablesTab()
|
||||||
|
{
|
||||||
|
detailDrawerView?.ShowTablesTab();
|
||||||
|
detailDrawerView?.OpenDrawer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowEventsTab()
|
||||||
|
{
|
||||||
|
detailDrawerView?.ShowEventsTab();
|
||||||
|
detailDrawerView?.OpenDrawer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseConfigPanel()
|
||||||
|
{
|
||||||
|
configInputView?.SetPanelVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveConfigAndClosePanel()
|
||||||
|
{
|
||||||
|
if (configInputView == null)
|
||||||
|
{
|
||||||
|
dashboardView?.SetError("缺少 SimulationConfigInputView 引用。");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!configInputView.TryBuildConfig(out var config, out var error))
|
||||||
|
{
|
||||||
|
dashboardView?.SetError(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dashboardView?.SetError(string.Empty);
|
||||||
|
if (!IsSameConfig(_activeConfig, config))
|
||||||
|
{
|
||||||
|
ApplyConfig(config, appendInitLog: true, clearTimeline: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AppendEvent("配置未变更", "配置未变更,保留当前引擎。");
|
||||||
|
}
|
||||||
|
|
||||||
|
configInputView.SetPanelVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CancelConfigAndClosePanel()
|
||||||
|
{
|
||||||
|
if (configInputView == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
configInputView.PopulateFromConfig(_activeConfig ?? new SimulationConfig());
|
||||||
|
configInputView.SetPanelVisible(false);
|
||||||
|
dashboardView?.SetError(string.Empty);
|
||||||
|
AppendEvent("已取消配置", "已取消配置面板修改,保留当前引擎。");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindControlEvents()
|
||||||
|
{
|
||||||
|
if (controlView == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
controlView.StepClicked += HandleStepClicked;
|
||||||
|
controlView.PlayClicked += HandlePlayClicked;
|
||||||
|
controlView.PauseClicked += HandlePauseClicked;
|
||||||
|
controlView.ResetClicked += HandleResetClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeEngineIfNeeded()
|
||||||
|
{
|
||||||
|
if (_engine != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string initialError = string.Empty;
|
||||||
|
if (configInputView != null)
|
||||||
|
{
|
||||||
|
if (configInputView.TryBuildConfig(out var viewConfig, out var viewError))
|
||||||
|
{
|
||||||
|
dashboardView?.SetError(string.Empty);
|
||||||
|
ApplyConfig(viewConfig, appendInitLog: true, clearTimeline: true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
initialError = viewError;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fallback = new SimulationConfig();
|
||||||
|
if (configInputView != null)
|
||||||
|
{
|
||||||
|
configInputView.PopulateFromConfig(fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyConfig(fallback, appendInitLog: true, clearTimeline: true);
|
||||||
|
if (!string.IsNullOrEmpty(initialError))
|
||||||
|
{
|
||||||
|
dashboardView?.SetError(initialError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyConfig(SimulationConfig config, bool appendInitLog, bool clearTimeline)
|
||||||
|
{
|
||||||
|
if (config == null)
|
||||||
|
{
|
||||||
|
config = new SimulationConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
config.ApplyFixedCoreSpec();
|
||||||
|
StopPlayRoutine();
|
||||||
|
controlView?.SetPlaying(false);
|
||||||
|
|
||||||
|
_activeConfig = CloneConfig(config);
|
||||||
|
_engine = new TranslatorEngine(_activeConfig);
|
||||||
|
|
||||||
|
if (clearTimeline)
|
||||||
|
{
|
||||||
|
detailTimelineView?.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appendInitLog)
|
||||||
|
{
|
||||||
|
AppendEvent("模拟已就绪", "已按新配置初始化模拟。");
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshUI(accessCompleted: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator PlayRoutine()
|
||||||
|
{
|
||||||
|
while (_engine != null)
|
||||||
|
{
|
||||||
|
if (_activeConfig != null &&
|
||||||
|
_engine.Stats.TotalAccess >= _activeConfig.accessCount &&
|
||||||
|
_engine.State.CurrentStep == TranslationStep.GenerateVA)
|
||||||
|
{
|
||||||
|
AppendEvent("连续播放结束", "连续播放达到访问次数上限。");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var accessCompleted = _engine.StepOnce();
|
||||||
|
RefreshUI(accessCompleted);
|
||||||
|
|
||||||
|
if (accessCompleted)
|
||||||
|
{
|
||||||
|
var state = _engine.State;
|
||||||
|
AppendEvent(
|
||||||
|
BuildAccessCompactMessage(state),
|
||||||
|
$"访问#{state.CurrentRound} 虚拟地址VA={SimulationUIFormatter.FormatAddressHex(state.CurrentVirtualAddress, _engine.VaBits)} -> " +
|
||||||
|
$"物理地址PA={SimulationUIFormatter.FormatAddressHex(state.CurrentPhysicalAddress, _engine.VaBits)} " +
|
||||||
|
$"TLB命中={state.IsTlbHit} 页表命中={state.IsPageTableHit} 缺页={state.IsPageFault} 开销={state.CurrentCost}");
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return new WaitForSeconds(playIntervalSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
_playRoutine = null;
|
||||||
|
controlView?.SetPlaying(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshUI(bool accessCompleted)
|
||||||
|
{
|
||||||
|
if (_engine == null)
|
||||||
|
{
|
||||||
|
dashboardView?.ShowNotInitialized();
|
||||||
|
tablesView?.ShowNotInitialized();
|
||||||
|
traceView?.ShowNotInitialized();
|
||||||
|
flowAnimator?.ResetVisual();
|
||||||
|
processHeaderView?.RenderStep(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dashboardView?.Render(_engine);
|
||||||
|
tablesView?.Render(_engine);
|
||||||
|
traceView?.Render(_engine);
|
||||||
|
flowAnimator?.AnimateStep(_engine.State.CurrentStep, _engine.State.IsPageFault, accessCompleted);
|
||||||
|
processHeaderView?.RenderStep(_engine.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AppendStepLog(bool accessCompleted)
|
||||||
|
{
|
||||||
|
if (_engine == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = _engine.State;
|
||||||
|
if (accessCompleted)
|
||||||
|
{
|
||||||
|
AppendEvent(
|
||||||
|
$"访问#{state.CurrentRound} 完成({BuildResultFlags(state)})",
|
||||||
|
$"访问#{state.CurrentRound} 完成 | " +
|
||||||
|
$"TLB命中={state.IsTlbHit} 页表命中={state.IsPageTableHit} 缺页={state.IsPageFault} 开销={state.CurrentCost}\n" +
|
||||||
|
$"分支原因:{state.LastDecisionReason}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var stepZh = TranslationStepDisplay.ToChinese(state.CurrentStep);
|
||||||
|
AppendEvent($"步骤:{stepZh}", $"步骤 -> {stepZh}\n分支原因:{state.LastDecisionReason}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AppendEvent(string compact, string detail)
|
||||||
|
{
|
||||||
|
detailTimelineView?.Append(detail);
|
||||||
|
processHeaderView?.SetEvent(compact);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopPlayRoutine()
|
||||||
|
{
|
||||||
|
if (_playRoutine == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StopCoroutine(_playRoutine);
|
||||||
|
_playRoutine = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleStepClicked()
|
||||||
|
{
|
||||||
|
InitializeEngineIfNeeded();
|
||||||
|
if (_engine == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var accessCompleted = _engine.StepOnce();
|
||||||
|
RefreshUI(accessCompleted);
|
||||||
|
AppendStepLog(accessCompleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandlePlayClicked()
|
||||||
|
{
|
||||||
|
InitializeEngineIfNeeded();
|
||||||
|
if (_engine == null || _playRoutine != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_playRoutine = StartCoroutine(PlayRoutine());
|
||||||
|
controlView?.SetPlaying(true);
|
||||||
|
AppendEvent("开始连续播放", "已开始连续播放。");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleStepHotkey()
|
||||||
|
{
|
||||||
|
if (IsStepHotkeyBlocked())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleStepClicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandlePauseClicked()
|
||||||
|
{
|
||||||
|
StopPlayRoutine();
|
||||||
|
controlView?.SetPlaying(false);
|
||||||
|
AppendEvent("暂停播放", "已暂停连续播放。");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleResetClicked()
|
||||||
|
{
|
||||||
|
StopPlayRoutine();
|
||||||
|
if (_engine != null)
|
||||||
|
{
|
||||||
|
_engine.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
detailTimelineView?.Clear();
|
||||||
|
RefreshUI(accessCompleted: false);
|
||||||
|
controlView?.SetPlaying(false);
|
||||||
|
AppendEvent("已重置", "模拟已重置。");
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsStepHotkeyBlocked()
|
||||||
|
{
|
||||||
|
if (_playRoutine != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configInputView != null && configInputView.IsPanelVisible)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IsTypingInInputField();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsTypingInInputField()
|
||||||
|
{
|
||||||
|
var eventSystem = EventSystem.current;
|
||||||
|
if (eventSystem == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selected = eventSystem.currentSelectedGameObject;
|
||||||
|
if (selected == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return selected.GetComponent<TMP_InputField>() != null ||
|
||||||
|
selected.GetComponent<InputField>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildAccessCompactMessage(SimulationState state)
|
||||||
|
{
|
||||||
|
var flagZh = state.IsPageFault ? "缺页" : (state.IsTlbHit ? "TLB命中" : (state.IsPageTableHit ? "页表命中" : "未命中"));
|
||||||
|
return $"访问#{state.CurrentRound} {flagZh}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildResultFlags(SimulationState state)
|
||||||
|
{
|
||||||
|
if (state.IsPageFault)
|
||||||
|
{
|
||||||
|
return "缺页";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.IsTlbHit)
|
||||||
|
{
|
||||||
|
return "TLB命中";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.IsPageTableHit)
|
||||||
|
{
|
||||||
|
return "页表命中";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "未知";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SimulationConfig CloneConfig(SimulationConfig source)
|
||||||
|
{
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
return new SimulationConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SimulationConfig
|
||||||
|
{
|
||||||
|
machineBits = source.machineBits,
|
||||||
|
vaBits = source.vaBits,
|
||||||
|
pageSizeKB = source.pageSizeKB,
|
||||||
|
physicalMemoryMB = source.physicalMemoryMB,
|
||||||
|
tlbEntries = source.tlbEntries,
|
||||||
|
accessCount = source.accessCount,
|
||||||
|
pageFaultPenalty = source.pageFaultPenalty,
|
||||||
|
addressGenerationMode = source.addressGenerationMode,
|
||||||
|
arrayLengthBytes = source.arrayLengthBytes,
|
||||||
|
arrayElementBytes = source.arrayElementBytes,
|
||||||
|
arrayBaseAddress = source.arrayBaseAddress
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsSameConfig(SimulationConfig a, SimulationConfig b)
|
||||||
|
{
|
||||||
|
if (a == null || b == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.machineBits == b.machineBits &&
|
||||||
|
a.vaBits == b.vaBits &&
|
||||||
|
a.pageSizeKB == b.pageSizeKB &&
|
||||||
|
a.physicalMemoryMB == b.physicalMemoryMB &&
|
||||||
|
a.tlbEntries == b.tlbEntries &&
|
||||||
|
a.accessCount == b.accessCount &&
|
||||||
|
a.pageFaultPenalty == b.pageFaultPenalty &&
|
||||||
|
a.addressGenerationMode == b.addressGenerationMode &&
|
||||||
|
a.arrayLengthBytes == b.arrayLengthBytes &&
|
||||||
|
a.arrayElementBytes == b.arrayElementBytes &&
|
||||||
|
a.arrayBaseAddress == b.arrayBaseAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ac9c8cdc89fb6c14bbd38774897a7e26
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,324 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using VMdemo.Simulation;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public static class SimulationUIFormatter
|
||||||
|
{
|
||||||
|
private const string ColorVpn = "#4FC3F7";
|
||||||
|
private const string ColorL1 = "#FFB74D";
|
||||||
|
private const string ColorL2 = "#81C784";
|
||||||
|
private const string ColorOffset = "#B0BEC5";
|
||||||
|
|
||||||
|
public static string FormatStateSummary(
|
||||||
|
SimulationState state,
|
||||||
|
int machineBits,
|
||||||
|
int vaBits,
|
||||||
|
int pageSizeKB,
|
||||||
|
int physicalMemoryMB,
|
||||||
|
int tlbEntries)
|
||||||
|
{
|
||||||
|
var va = FormatAddressHex(state.CurrentVirtualAddress, vaBits);
|
||||||
|
var pa = FormatAddressHex(state.CurrentPhysicalAddress, vaBits);
|
||||||
|
var stepText = TranslationStepDisplay.ToChinese(state.CurrentStep);
|
||||||
|
return
|
||||||
|
$"系统规格:{machineBits}位机\n" +
|
||||||
|
$"虚拟地址有效位:{vaBits}位\n" +
|
||||||
|
$"页大小:{pageSizeKB}KB\n" +
|
||||||
|
$"物理内存:{physicalMemoryMB}MB\n" +
|
||||||
|
$"TLB:{tlbEntries}条全相联\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatStats(StatsCollector stats)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
$"总访问={stats.TotalAccess}\n" +
|
||||||
|
$"TLB命中率={stats.TlbHitRate:P2}\n" +
|
||||||
|
$"页表命中率={stats.PageTableHitRate:P2}\n" +
|
||||||
|
$"缺页次数={stats.PageFault}\n" +
|
||||||
|
$"平均开销={stats.AvgCost:F2}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatTlbTable(
|
||||||
|
IReadOnlyList<TlbEntry> entries,
|
||||||
|
int vpnBits,
|
||||||
|
int pfnBits)
|
||||||
|
{
|
||||||
|
if (entries == null || entries.Count == 0)
|
||||||
|
{
|
||||||
|
return "TLB:空";
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("TLB(最近使用 -> 最久未用)");
|
||||||
|
for (var i = 0; i < entries.Count; i++)
|
||||||
|
{
|
||||||
|
var entry = entries[i];
|
||||||
|
sb.Append("#").Append(i + 1)
|
||||||
|
.Append("VPN=").Append(FormatBitWidthHex(entry.Vpn, vpnBits))
|
||||||
|
.Append(" -> PFN=").Append(FormatBitWidthHex(entry.Pfn, pfnBits))
|
||||||
|
.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString().TrimEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatCurrentPageTableEntry(
|
||||||
|
SimulationState state,
|
||||||
|
TwoLevelPageTable pageTable,
|
||||||
|
EvictionInfo eviction)
|
||||||
|
{
|
||||||
|
if (state == null || pageTable == null)
|
||||||
|
{
|
||||||
|
return "页表:N/A";
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append("当前页表项:");
|
||||||
|
if (pageTable.TryGetEntry(state.CurrentAddressParts.L1Index, state.CurrentAddressParts.L2Index,
|
||||||
|
out var entry))
|
||||||
|
{
|
||||||
|
sb.Append("存在=").Append(entry.Present)
|
||||||
|
.Append(" 物理帧号PFN=").Append(FormatHex(entry.Pfn))
|
||||||
|
.Append(" 脏位=").Append(entry.Dirty);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append("(缺失)");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
if (eviction.HasEvicted)
|
||||||
|
{
|
||||||
|
sb.Append("最近淘汰:虚拟页号VPN=").Append(FormatHex(eviction.EvictedVpn))
|
||||||
|
.Append(" 物理帧号PFN=").Append(FormatHex(eviction.EvictedPfn));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append("最近淘汰:无");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatFifoQueue(IReadOnlyList<ulong> fifoOrder)
|
||||||
|
{
|
||||||
|
if (fifoOrder == null || fifoOrder.Count == 0)
|
||||||
|
{
|
||||||
|
return "FIFO:空";
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb = new StringBuilder("FIFO(最早进入 -> 最新进入):");
|
||||||
|
for (var i = 0; i < fifoOrder.Count; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
sb.Append(" -> ");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append(FormatHex(fifoOrder[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatAddressHex(ulong value, int vaBits)
|
||||||
|
{
|
||||||
|
return FormatBitWidthHex(value, vaBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatHex(ulong value)
|
||||||
|
{
|
||||||
|
return $"0x{value:X}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatBitWidthHex(ulong value, int bits)
|
||||||
|
{
|
||||||
|
var digits = bits switch
|
||||||
|
{
|
||||||
|
8 => 2,
|
||||||
|
16 => 4,
|
||||||
|
24 => 6,
|
||||||
|
32 => 8,
|
||||||
|
48 => 12,
|
||||||
|
64 => 16,
|
||||||
|
_ => bits > 0 ? (bits + 3) / 4 : 1
|
||||||
|
};
|
||||||
|
|
||||||
|
return $"0x{value.ToString($"X{digits}")}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ComputeBitsForCount(ulong count)
|
||||||
|
{
|
||||||
|
if (count <= 1UL)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxValue = count - 1UL;
|
||||||
|
var bits = 0;
|
||||||
|
while (maxValue > 0UL)
|
||||||
|
{
|
||||||
|
bits++;
|
||||||
|
maxValue >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatAddressSplitTrace(
|
||||||
|
SimulationState state,
|
||||||
|
int vaBits,
|
||||||
|
int offsetBits,
|
||||||
|
int l1Bits,
|
||||||
|
int l2Bits)
|
||||||
|
{
|
||||||
|
if (state == null)
|
||||||
|
{
|
||||||
|
return "地址拆分可视化:N/A";
|
||||||
|
}
|
||||||
|
|
||||||
|
var vpnBits = vaBits - offsetBits;
|
||||||
|
var vaHex = FormatAddressHex(state.CurrentVirtualAddress, vaBits);
|
||||||
|
var vaBin = FormatBinary(state.CurrentVirtualAddress, vaBits);
|
||||||
|
var vaBinColored = FormatVaBinaryWithFieldColors(state.CurrentVirtualAddress, vaBits, l1Bits, l2Bits, offsetBits);
|
||||||
|
var vpnBin = FormatBinary(state.CurrentAddressParts.Vpn, vpnBits);
|
||||||
|
var l1Bin = FormatBinary(state.CurrentAddressParts.L1Index, l1Bits);
|
||||||
|
var l2Bin = FormatBinary(state.CurrentAddressParts.L2Index, l2Bits);
|
||||||
|
var offBin = FormatBinary(state.CurrentAddressParts.Offset, offsetBits);
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("地址拆分可视化");
|
||||||
|
sb.AppendLine($"{vaHex})");
|
||||||
|
sb.AppendLine($"{vaBinColored}");
|
||||||
|
sb.AppendLine(
|
||||||
|
$"{WrapColor("VPN", ColorVpn)} = {WrapColor("L1+L2", ColorVpn)}," +
|
||||||
|
$"{WrapColor("L1", ColorL1)},{WrapColor("L2", ColorL2)},{WrapColor("Offset", ColorOffset)}");
|
||||||
|
sb.AppendLine($"VPN({vpnBits}) = L1({l1Bits}) + L2({l2Bits}) | Offset({offsetBits})");
|
||||||
|
sb.AppendLine($"VPN:{FormatBitWidthHex(state.CurrentAddressParts.Vpn, vpnBits)} ({WrapColor(vpnBin, ColorVpn)})");
|
||||||
|
sb.AppendLine($"L1 索引:{FormatBitWidthHex(state.CurrentAddressParts.L1Index, l1Bits)} ({WrapColor(l1Bin, ColorL1)})");
|
||||||
|
sb.AppendLine($"L2 索引:{FormatBitWidthHex(state.CurrentAddressParts.L2Index, l2Bits)} ({WrapColor(l2Bin, ColorL2)})");
|
||||||
|
sb.Append($"Offset:{FormatBitWidthHex(state.CurrentAddressParts.Offset, offsetBits)} ({WrapColor(offBin, ColorOffset)})");
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatPageTableWalkTrace(SimulationState state, TwoLevelPageTable pageTable)
|
||||||
|
{
|
||||||
|
if (state == null || pageTable == null)
|
||||||
|
{
|
||||||
|
return "页表访问路径:N/A";
|
||||||
|
}
|
||||||
|
|
||||||
|
var probe = pageTable.Probe(state.CurrentAddressParts.L1Index, state.CurrentAddressParts.L2Index);
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("多级页表查询可视化");
|
||||||
|
sb.AppendLine(
|
||||||
|
$"1) 先按 VPN 拆分:L1={state.CurrentAddressParts.L1Index}, L2={state.CurrentAddressParts.L2Index}");
|
||||||
|
switch (probe.Status)
|
||||||
|
{
|
||||||
|
case PageTableProbeStatus.MissingL1Table:
|
||||||
|
sb.Append("2) L1 未命中:对应二级页表不存在。");
|
||||||
|
break;
|
||||||
|
case PageTableProbeStatus.MissingL2Entry:
|
||||||
|
sb.Append("2) L1 命中,L2 未命中:页表项不存在。");
|
||||||
|
break;
|
||||||
|
case PageTableProbeStatus.NotPresentEntry:
|
||||||
|
sb.Append($"2) L1/L2 命中,但 present=false(PFN={FormatHex(probe.Entry.Pfn)})。");
|
||||||
|
break;
|
||||||
|
case PageTableProbeStatus.PresentEntry:
|
||||||
|
sb.Append($"2) L1/L2 命中,present=true,得到 PFN={FormatHex(probe.Entry.Pfn)}。");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatBinary(ulong value, int bits)
|
||||||
|
{
|
||||||
|
if (bits <= 0)
|
||||||
|
{
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb = new StringBuilder(bits + (bits / 4));
|
||||||
|
for (var i = bits - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var bit = (value >> i) & 1UL;
|
||||||
|
sb.Append(bit == 1UL ? '1' : '0');
|
||||||
|
if (i > 0 && i % 4 == 0)
|
||||||
|
{
|
||||||
|
sb.Append('_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatVaBinaryWithFieldColors(
|
||||||
|
ulong value,
|
||||||
|
int vaBits,
|
||||||
|
int l1Bits,
|
||||||
|
int l2Bits,
|
||||||
|
int offsetBits)
|
||||||
|
{
|
||||||
|
if (vaBits <= 0)
|
||||||
|
{
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb = new StringBuilder(vaBits * 10);
|
||||||
|
string currentColor = null;
|
||||||
|
|
||||||
|
for (var i = vaBits - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var bitColor = ResolveBitColor(i, l1Bits, l2Bits, offsetBits);
|
||||||
|
if (currentColor != bitColor)
|
||||||
|
{
|
||||||
|
if (currentColor != null)
|
||||||
|
{
|
||||||
|
sb.Append("</color>");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append("<color=").Append(bitColor).Append(">");
|
||||||
|
currentColor = bitColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bit = (value >> i) & 1UL;
|
||||||
|
sb.Append(bit == 1UL ? '1' : '0');
|
||||||
|
if (i > 0 && i % 4 == 0)
|
||||||
|
{
|
||||||
|
sb.Append('_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentColor != null)
|
||||||
|
{
|
||||||
|
sb.Append("</color>");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveBitColor(int bitIndex, int l1Bits, int l2Bits, int offsetBits)
|
||||||
|
{
|
||||||
|
var l1Start = offsetBits + l2Bits;
|
||||||
|
if (bitIndex >= l1Start)
|
||||||
|
{
|
||||||
|
return ColorL1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitIndex >= offsetBits)
|
||||||
|
{
|
||||||
|
return ColorL2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ColorOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string WrapColor(string text, string colorHex)
|
||||||
|
{
|
||||||
|
return $"<color={colorHex}>{text}</color>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d62c9fa502173a542a04294863667636
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DG.Tweening;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using VMdemo.Simulation;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public class StepFlowAnimator : MonoBehaviour
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class StepNodeView
|
||||||
|
{
|
||||||
|
public TranslationStep step;
|
||||||
|
public RectTransform target;
|
||||||
|
public CanvasGroup canvasGroup;
|
||||||
|
public Image background;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Header("Step Nodes")] [SerializeField]
|
||||||
|
private List<StepNodeView> stepNodes = new List<StepNodeView>();
|
||||||
|
|
||||||
|
[Header("Colors")] [SerializeField] private Color idleColor = new Color(0.18f, 0.22f, 0.28f, 1f);
|
||||||
|
[SerializeField] private Color activeColor = new Color(0.19f, 0.62f, 0.98f, 1f);
|
||||||
|
[SerializeField] private Color faultColor = new Color(0.97f, 0.31f, 0.27f, 1f);
|
||||||
|
|
||||||
|
[Header("Animation")] [SerializeField] private float highlightDuration = 0.2f;
|
||||||
|
[SerializeField] private float normalScale = 1f;
|
||||||
|
[SerializeField] private float activeScale = 1.08f;
|
||||||
|
[SerializeField] private float pulseScale = 1.04f;
|
||||||
|
[SerializeField] private RectTransform accessPulseTarget;
|
||||||
|
|
||||||
|
private readonly Dictionary<TranslationStep, StepNodeView> _nodeMap =
|
||||||
|
new Dictionary<TranslationStep, StepNodeView>();
|
||||||
|
|
||||||
|
private TranslationStep? _lastStep;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
BuildNodeMap();
|
||||||
|
ResetVisual();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetVisual()
|
||||||
|
{
|
||||||
|
DOTween.Kill(this);
|
||||||
|
_lastStep = null;
|
||||||
|
|
||||||
|
foreach (var node in stepNodes)
|
||||||
|
{
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.target != null)
|
||||||
|
{
|
||||||
|
node.target.localScale = Vector3.one * normalScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.canvasGroup != null)
|
||||||
|
{
|
||||||
|
node.canvasGroup.alpha = 0.72f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.background != null)
|
||||||
|
{
|
||||||
|
node.background.color = idleColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accessPulseTarget != null)
|
||||||
|
{
|
||||||
|
accessPulseTarget.localScale = Vector3.one;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AnimateStep(TranslationStep currentStep, bool isPageFault, bool accessCompleted)
|
||||||
|
{
|
||||||
|
BuildNodeMap();
|
||||||
|
if (_lastStep.HasValue && _nodeMap.TryGetValue(_lastStep.Value, out var lastNode))
|
||||||
|
{
|
||||||
|
AnimateToIdle(lastNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_nodeMap.TryGetValue(currentStep, out var currentNode))
|
||||||
|
{
|
||||||
|
AnimateToActive(currentNode, isPageFault && currentStep == TranslationStep.HandlePageFault);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accessCompleted)
|
||||||
|
{
|
||||||
|
AnimateAccessCompletedPulse();
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastStep = currentStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildNodeMap()
|
||||||
|
{
|
||||||
|
_nodeMap.Clear();
|
||||||
|
foreach (var node in stepNodes)
|
||||||
|
{
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_nodeMap.ContainsKey(node.step))
|
||||||
|
{
|
||||||
|
_nodeMap.Add(node.step, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AnimateToIdle(StepNodeView node)
|
||||||
|
{
|
||||||
|
if (node.target != null)
|
||||||
|
{
|
||||||
|
node.target.DOKill();
|
||||||
|
node.target.DOScale(normalScale, highlightDuration).SetEase(Ease.OutQuad).SetTarget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.canvasGroup != null)
|
||||||
|
{
|
||||||
|
node.canvasGroup.DOKill();
|
||||||
|
node.canvasGroup.DOFade(0.72f, highlightDuration).SetEase(Ease.OutQuad).SetTarget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.background != null)
|
||||||
|
{
|
||||||
|
node.background.DOKill();
|
||||||
|
node.background.DOColor(idleColor, highlightDuration).SetEase(Ease.OutQuad).SetTarget(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AnimateToActive(StepNodeView node, bool emphasizeFault)
|
||||||
|
{
|
||||||
|
if (node.target != null)
|
||||||
|
{
|
||||||
|
node.target.DOKill();
|
||||||
|
node.target.DOScale(activeScale, highlightDuration).SetEase(Ease.OutBack).SetTarget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.canvasGroup != null)
|
||||||
|
{
|
||||||
|
node.canvasGroup.DOKill();
|
||||||
|
node.canvasGroup.DOFade(1f, highlightDuration).SetEase(Ease.OutQuad).SetTarget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.background != null)
|
||||||
|
{
|
||||||
|
node.background.DOKill();
|
||||||
|
var targetColor = emphasizeFault ? faultColor : activeColor;
|
||||||
|
node.background.DOColor(targetColor, highlightDuration).SetEase(Ease.OutQuad).SetTarget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emphasizeFault && node.target != null)
|
||||||
|
{
|
||||||
|
node.target.DOPunchScale(new Vector3(0.07f, 0.07f, 0f), 0.28f, 6, 0.75f).SetTarget(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AnimateAccessCompletedPulse()
|
||||||
|
{
|
||||||
|
if (accessPulseTarget == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
accessPulseTarget.DOKill();
|
||||||
|
accessPulseTarget
|
||||||
|
.DOScale(pulseScale, 0.12f)
|
||||||
|
.SetEase(Ease.OutQuad)
|
||||||
|
.SetLoops(2, LoopType.Yoyo)
|
||||||
|
.SetTarget(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f36cd8ac00908594fb49c431d072c1bc
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
[RequireComponent(typeof(RectTransform))]
|
||||||
|
public class TimelineLogItemAutoSize : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private TMP_Text textComponent;
|
||||||
|
[SerializeField] private float horizontalPadding = 20f;
|
||||||
|
[SerializeField] private float verticalPadding = 12f;
|
||||||
|
[SerializeField] private bool clampToParentWidth = true;
|
||||||
|
[SerializeField] private float minWidth = 80f;
|
||||||
|
[SerializeField] private float minHeight = 30f;
|
||||||
|
|
||||||
|
public void RefreshLayout()
|
||||||
|
{
|
||||||
|
var text = textComponent != null ? textComponent : GetComponent<TMP_Text>();
|
||||||
|
var root = (RectTransform)transform;
|
||||||
|
if (text == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float maxWidth = float.PositiveInfinity;
|
||||||
|
if (clampToParentWidth && root.parent is RectTransform parentRect)
|
||||||
|
{
|
||||||
|
maxWidth = Mathf.Max(1f, parentRect.rect.width - horizontalPadding);
|
||||||
|
}
|
||||||
|
|
||||||
|
var preferred = text.GetPreferredValues(text.text, maxWidth, 0f);
|
||||||
|
var width = Mathf.Max(minWidth, preferred.x + horizontalPadding);
|
||||||
|
var height = Mathf.Max(minHeight, preferred.y + verticalPadding);
|
||||||
|
|
||||||
|
if (clampToParentWidth && root.parent is RectTransform p)
|
||||||
|
{
|
||||||
|
width = Mathf.Min(width, Mathf.Max(minWidth, p.rect.width));
|
||||||
|
}
|
||||||
|
|
||||||
|
root.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
|
||||||
|
root.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
|
||||||
|
|
||||||
|
var layoutElement = GetComponent<LayoutElement>();
|
||||||
|
if (layoutElement != null)
|
||||||
|
{
|
||||||
|
layoutElement.preferredWidth = width;
|
||||||
|
layoutElement.preferredHeight = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d594815f47f84f758ecf3e198de8d8de
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
using VMdemo.Simulation;
|
||||||
|
|
||||||
|
namespace VMdemo.UI
|
||||||
|
{
|
||||||
|
public static class TranslationStepDisplay
|
||||||
|
{
|
||||||
|
public static string ToChinese(TranslationStep step)
|
||||||
|
{
|
||||||
|
return step switch
|
||||||
|
{
|
||||||
|
TranslationStep.GenerateVA => "生成虚拟地址",
|
||||||
|
TranslationStep.SplitVA => "拆分虚拟地址",
|
||||||
|
TranslationStep.LookupTLB => "查询 TLB",
|
||||||
|
TranslationStep.LookupPageTable => "查询页表",
|
||||||
|
TranslationStep.HandlePageFault => "处理缺页",
|
||||||
|
TranslationStep.ComposePA => "合成物理地址",
|
||||||
|
TranslationStep.Finalize => "完成收尾",
|
||||||
|
_ => step.ToString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 61f58553676e41d68ef5818d93ba09dc
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -1,3 +1,17 @@
|
||||||
{
|
{
|
||||||
"name": "VMdemo"
|
"name": "VMdemo",
|
||||||
}
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||||
|
"GUID:b1a18c052caf77a44a8bbb8a5e4acd11"
|
||||||
|
],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ namespace VMdemo.Tests.EditMode
|
||||||
{
|
{
|
||||||
var config = new SimulationConfig
|
var config = new SimulationConfig
|
||||||
{
|
{
|
||||||
vaBits = 48,
|
vaBits = 24,
|
||||||
pageSizeKB = 4,
|
pageSizeKB = 4,
|
||||||
physicalMemoryMB = 64,
|
physicalMemoryMB = 64,
|
||||||
tlbEntries = 16,
|
tlbEntries = 16,
|
||||||
|
|
@ -26,7 +26,7 @@ namespace VMdemo.Tests.EditMode
|
||||||
Assert.That(derived.PageSizeBytes, Is.EqualTo(4096UL));
|
Assert.That(derived.PageSizeBytes, Is.EqualTo(4096UL));
|
||||||
Assert.That(derived.PhysicalMemoryBytes, Is.EqualTo(67108864UL));
|
Assert.That(derived.PhysicalMemoryBytes, Is.EqualTo(67108864UL));
|
||||||
Assert.That(derived.OffsetBits, Is.EqualTo(12));
|
Assert.That(derived.OffsetBits, Is.EqualTo(12));
|
||||||
Assert.That(derived.VpnBits, Is.EqualTo(36));
|
Assert.That(derived.VpnBits, Is.EqualTo(12));
|
||||||
Assert.That(derived.FrameCount, Is.EqualTo(16384UL));
|
Assert.That(derived.FrameCount, Is.EqualTo(16384UL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace VMdemo.Tests.EditMode
|
||||||
{
|
{
|
||||||
var config = new SimulationConfig
|
var config = new SimulationConfig
|
||||||
{
|
{
|
||||||
vaBits = 40,
|
vaBits = 12,
|
||||||
pageSizeKB = 4,
|
pageSizeKB = 4,
|
||||||
physicalMemoryMB = 64,
|
physicalMemoryMB = 64,
|
||||||
tlbEntries = 16,
|
tlbEntries = 16,
|
||||||
|
|
@ -54,7 +54,7 @@ namespace VMdemo.Tests.EditMode
|
||||||
{
|
{
|
||||||
var config = new SimulationConfig
|
var config = new SimulationConfig
|
||||||
{
|
{
|
||||||
vaBits = 32,
|
vaBits = 16,
|
||||||
pageSizeKB = 6,
|
pageSizeKB = 6,
|
||||||
physicalMemoryMB = 64,
|
physicalMemoryMB = 64,
|
||||||
tlbEntries = 16,
|
tlbEntries = 16,
|
||||||
|
|
@ -73,9 +73,9 @@ namespace VMdemo.Tests.EditMode
|
||||||
{
|
{
|
||||||
var config = new SimulationConfig
|
var config = new SimulationConfig
|
||||||
{
|
{
|
||||||
vaBits = 32,
|
vaBits = 8,
|
||||||
pageSizeKB = 4 * 1024 * 1024,
|
pageSizeKB = 1,
|
||||||
physicalMemoryMB = 8192,
|
physicalMemoryMB = 8,
|
||||||
tlbEntries = 16,
|
tlbEntries = 16,
|
||||||
accessCount = 10,
|
accessCount = 10,
|
||||||
pageFaultPenalty = 100
|
pageFaultPenalty = 100
|
||||||
|
|
@ -92,7 +92,7 @@ namespace VMdemo.Tests.EditMode
|
||||||
{
|
{
|
||||||
var config = new SimulationConfig
|
var config = new SimulationConfig
|
||||||
{
|
{
|
||||||
vaBits = 32,
|
vaBits = 16,
|
||||||
pageSizeKB = 2048,
|
pageSizeKB = 2048,
|
||||||
physicalMemoryMB = 1,
|
physicalMemoryMB = 1,
|
||||||
tlbEntries = 16,
|
tlbEntries = 16,
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ namespace VMdemo.Tests.EditMode
|
||||||
{
|
{
|
||||||
public class Step2AddressSplitTests
|
public class Step2AddressSplitTests
|
||||||
{
|
{
|
||||||
[TestCase(32)]
|
[TestCase(8)]
|
||||||
[TestCase(48)]
|
[TestCase(16)]
|
||||||
[TestCase(64)]
|
[TestCase(24)]
|
||||||
public void AddressGenerator_NextVirtualAddress_StaysWithinRange(int vaBits)
|
public void AddressGenerator_NextVirtualAddress_StaysWithinRange(int vaBits)
|
||||||
{
|
{
|
||||||
var generator = new AddressGenerator(vaBits, seed: 7);
|
var generator = new AddressGenerator(vaBits, seed: 7);
|
||||||
|
|
@ -23,8 +23,8 @@ namespace VMdemo.Tests.EditMode
|
||||||
[Test]
|
[Test]
|
||||||
public void AddressGenerator_SameSeed_GeneratesDeterministicSequence()
|
public void AddressGenerator_SameSeed_GeneratesDeterministicSequence()
|
||||||
{
|
{
|
||||||
var a = new AddressGenerator(48, seed: 99);
|
var a = new AddressGenerator(24, seed: 99);
|
||||||
var b = new AddressGenerator(48, seed: 99);
|
var b = new AddressGenerator(24, seed: 99);
|
||||||
|
|
||||||
for (var i = 0; i < 20; i++)
|
for (var i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -35,8 +35,8 @@ namespace VMdemo.Tests.EditMode
|
||||||
[Test]
|
[Test]
|
||||||
public void AddressGenerator_DifferentSeed_GeneratesDifferentSequence()
|
public void AddressGenerator_DifferentSeed_GeneratesDifferentSequence()
|
||||||
{
|
{
|
||||||
var a = new AddressGenerator(48, seed: 99);
|
var a = new AddressGenerator(24, seed: 99);
|
||||||
var b = new AddressGenerator(48, seed: 100);
|
var b = new AddressGenerator(24, seed: 100);
|
||||||
var hasDifference = false;
|
var hasDifference = false;
|
||||||
|
|
||||||
for (var i = 0; i < 20; i++)
|
for (var i = 0; i < 20; i++)
|
||||||
|
|
@ -51,9 +51,9 @@ namespace VMdemo.Tests.EditMode
|
||||||
Assert.IsTrue(hasDifference);
|
Assert.IsTrue(hasDifference);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(0x12345ABCUL, 32, 12, 0x12345UL, 0xABCUL, 0x48UL, 0x345UL)]
|
[TestCase(0xAFUL, 8, 4, 0xAUL, 0xFUL, 0x2UL, 0x2UL)]
|
||||||
[TestCase(0x0000ABCDEF123456UL, 48, 12, 0xABCDEF123UL, 0x456UL, 0x2AF37UL, 0x2F123UL)]
|
[TestCase(0xABCDUL, 16, 8, 0xABUL, 0xCDUL, 0xAUL, 0xBUL)]
|
||||||
[TestCase(0xFEDCBA9876543210UL, 64, 16, 0xFEDCBA987654UL, 0x3210UL, 0xFEDCBAUL, 0x987654UL)]
|
[TestCase(0x123456UL, 24, 8, 0x1234UL, 0x56UL, 0x12UL, 0x34UL)]
|
||||||
public void SplitVirtualAddress_SupportedVaBits_ReturnsExpectedParts(
|
public void SplitVirtualAddress_SupportedVaBits_ReturnsExpectedParts(
|
||||||
ulong va,
|
ulong va,
|
||||||
int vaBits,
|
int vaBits,
|
||||||
|
|
@ -75,19 +75,19 @@ namespace VMdemo.Tests.EditMode
|
||||||
[Test]
|
[Test]
|
||||||
public void SplitVirtualAddress_OddVpnBits_UsesCeilFloorBitSplit()
|
public void SplitVirtualAddress_OddVpnBits_UsesCeilFloorBitSplit()
|
||||||
{
|
{
|
||||||
const int vaBits = 32;
|
const int vaBits = 24;
|
||||||
const int offsetBits = 13;
|
const int offsetBits = 5;
|
||||||
const ulong va = 0xDEADBEEFUL;
|
const ulong va = 0xABCDEFUL;
|
||||||
|
|
||||||
var parts = AddressTranslatorUtils.SplitVirtualAddress(va, vaBits, offsetBits);
|
var parts = AddressTranslatorUtils.SplitVirtualAddress(va, vaBits, offsetBits);
|
||||||
AddressTranslatorUtils.GetPageTableBitLayout(vaBits - offsetBits, out var l1Bits, out var l2Bits);
|
AddressTranslatorUtils.GetPageTableBitLayout(vaBits - offsetBits, out var l1Bits, out var l2Bits);
|
||||||
|
|
||||||
Assert.That(l1Bits, Is.EqualTo(10));
|
Assert.That(l1Bits, Is.EqualTo(10));
|
||||||
Assert.That(l2Bits, Is.EqualTo(9));
|
Assert.That(l2Bits, Is.EqualTo(9));
|
||||||
Assert.That(parts.Vpn, Is.EqualTo(0x6F56DUL));
|
Assert.That(parts.Vpn, Is.EqualTo(0x55E6FUL));
|
||||||
Assert.That(parts.Offset, Is.EqualTo(0x1EEFUL));
|
Assert.That(parts.Offset, Is.EqualTo(0xFUL));
|
||||||
Assert.That(parts.L1Index, Is.EqualTo(0x37AUL));
|
Assert.That(parts.L1Index, Is.EqualTo(0x2AFUL));
|
||||||
Assert.That(parts.L2Index, Is.EqualTo(0x16DUL));
|
Assert.That(parts.L2Index, Is.EqualTo(0x6FUL));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
@ -107,7 +107,25 @@ namespace VMdemo.Tests.EditMode
|
||||||
public void SplitVirtualAddress_AddressOutOfRange_Throws()
|
public void SplitVirtualAddress_AddressOutOfRange_Throws()
|
||||||
{
|
{
|
||||||
Assert.Throws<System.ArgumentOutOfRangeException>(() =>
|
Assert.Throws<System.ArgumentOutOfRangeException>(() =>
|
||||||
AddressTranslatorUtils.SplitVirtualAddress(0x1_0000_0000UL, 32, 12));
|
AddressTranslatorUtils.SplitVirtualAddress(0x1_000000UL, 24, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AddressGenerator_SequentialArrayLoop_FollowsClassicForLoopOrderAndWraps()
|
||||||
|
{
|
||||||
|
var generator = new AddressGenerator(
|
||||||
|
vaBits: 16,
|
||||||
|
seed: 7,
|
||||||
|
mode: AddressGenerationMode.SequentialArrayLoop,
|
||||||
|
arrayLengthBytes: 16,
|
||||||
|
arrayElementBytes: 4,
|
||||||
|
arrayBaseAddress: 0x20);
|
||||||
|
|
||||||
|
Assert.That(generator.NextVirtualAddress(), Is.EqualTo(0x20UL));
|
||||||
|
Assert.That(generator.NextVirtualAddress(), Is.EqualTo(0x24UL));
|
||||||
|
Assert.That(generator.NextVirtualAddress(), Is.EqualTo(0x28UL));
|
||||||
|
Assert.That(generator.NextVirtualAddress(), Is.EqualTo(0x2CUL));
|
||||||
|
Assert.That(generator.NextVirtualAddress(), Is.EqualTo(0x20UL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,29 @@ namespace VMdemo.Tests.EditMode
|
||||||
Assert.IsFalse(entry.Present);
|
Assert.IsFalse(entry.Present);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TwoLevelPageTable_Probe_CanDistinguishLookupReasons()
|
||||||
|
{
|
||||||
|
var pageTable = new TwoLevelPageTable(3, 2);
|
||||||
|
|
||||||
|
var missingL1 = pageTable.Probe(1UL, 0UL);
|
||||||
|
Assert.That(missingL1.Status, Is.EqualTo(PageTableProbeStatus.MissingL1Table));
|
||||||
|
|
||||||
|
pageTable.SetPresent(1UL, 2UL, 7UL);
|
||||||
|
var missingL2 = pageTable.Probe(1UL, 3UL);
|
||||||
|
Assert.That(missingL2.Status, Is.EqualTo(PageTableProbeStatus.MissingL2Entry));
|
||||||
|
|
||||||
|
pageTable.MarkNotPresent(1UL, 2UL);
|
||||||
|
var notPresent = pageTable.Probe(1UL, 2UL);
|
||||||
|
Assert.That(notPresent.Status, Is.EqualTo(PageTableProbeStatus.NotPresentEntry));
|
||||||
|
Assert.IsTrue(notPresent.HasEntry);
|
||||||
|
|
||||||
|
pageTable.SetPresent(1UL, 2UL, 9UL);
|
||||||
|
var present = pageTable.Probe(1UL, 2UL);
|
||||||
|
Assert.That(present.Status, Is.EqualTo(PageTableProbeStatus.PresentEntry));
|
||||||
|
Assert.That(present.Entry.Pfn, Is.EqualTo(9UL));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void PhysicalMemoryManager_AllocateForVpn_EvictsInFifoOrder()
|
public void PhysicalMemoryManager_AllocateForVpn_EvictsInFifoOrder()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ namespace VMdemo.Tests.EditMode
|
||||||
{
|
{
|
||||||
var engine = CreateEngine(frameCountMb: 1, tlbEntries: 2, seed: 99);
|
var engine = CreateEngine(frameCountMb: 1, tlbEntries: 2, seed: 99);
|
||||||
const ulong va = 0x0000_89ABUL;
|
const ulong va = 0x0000_89ABUL;
|
||||||
var parts = AddressTranslatorUtils.SplitVirtualAddress(va, 32, engine.OffsetBits);
|
var parts = AddressTranslatorUtils.SplitVirtualAddress(va, engine.VaBits, engine.OffsetBits);
|
||||||
|
|
||||||
engine.PageTable.SetPresent(parts.L1Index, parts.L2Index, pfn: 3UL);
|
engine.PageTable.SetPresent(parts.L1Index, parts.L2Index, pfn: 3UL);
|
||||||
engine.SetNextVirtualAddress(va);
|
engine.SetNextVirtualAddress(va);
|
||||||
|
|
@ -109,7 +109,7 @@ namespace VMdemo.Tests.EditMode
|
||||||
{
|
{
|
||||||
var config = new SimulationConfig
|
var config = new SimulationConfig
|
||||||
{
|
{
|
||||||
vaBits = 32,
|
vaBits = 24,
|
||||||
pageSizeKB = 1024, // 1MB per page
|
pageSizeKB = 1024, // 1MB per page
|
||||||
physicalMemoryMB = 1, // 1 frame total
|
physicalMemoryMB = 1, // 1 frame total
|
||||||
tlbEntries = 4,
|
tlbEntries = 4,
|
||||||
|
|
@ -178,7 +178,7 @@ namespace VMdemo.Tests.EditMode
|
||||||
{
|
{
|
||||||
var config = new SimulationConfig
|
var config = new SimulationConfig
|
||||||
{
|
{
|
||||||
vaBits = 32,
|
vaBits = 24,
|
||||||
pageSizeKB = 4,
|
pageSizeKB = 4,
|
||||||
physicalMemoryMB = frameCountMb,
|
physicalMemoryMB = frameCountMb,
|
||||||
tlbEntries = tlbEntries,
|
tlbEntries = tlbEntries,
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ namespace VMdemo.Tests.EditMode
|
||||||
{
|
{
|
||||||
var config = new SimulationConfig
|
var config = new SimulationConfig
|
||||||
{
|
{
|
||||||
vaBits = 32,
|
vaBits = 24,
|
||||||
pageSizeKB = 4,
|
pageSizeKB = 4,
|
||||||
physicalMemoryMB = 1,
|
physicalMemoryMB = 1,
|
||||||
tlbEntries = 4,
|
tlbEntries = 4,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f54d1bd14bd3ca042bd867b519fee8cc
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8e7e8f5a82a3a134e91c54efd2274ea9
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1b8d251f9af63b746bf2f7ffe00ebb9b
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6ab70aee4d56447429c680537fbf93ed
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
Digitized data copyright (c) 2010 Google Corporation
|
||||||
|
with Reserved Font Arimo, Tinos and Cousine.
|
||||||
|
Copyright (c) 2012 Red Hat, Inc.
|
||||||
|
with Reserved Font Name Liberation.
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6e59c59b81ab47f9b6ec5781fa725d2c
|
||||||
|
timeCreated: 1484171296
|
||||||
|
licenseType: Pro
|
||||||
|
TextScriptImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,19 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e3265ab4bf004d28a9537516768c1c75
|
||||||
|
timeCreated: 1484171297
|
||||||
|
licenseType: Pro
|
||||||
|
TrueTypeFontImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
fontSize: 16
|
||||||
|
forceTextureCase: -2
|
||||||
|
characterSpacing: 1
|
||||||
|
characterPadding: 0
|
||||||
|
includeFontData: 1
|
||||||
|
use2xBehaviour: 0
|
||||||
|
fontNames: []
|
||||||
|
fallbackFontReferences: []
|
||||||
|
customCharacters:
|
||||||
|
fontRenderingMode: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 243e06394e614e5d99fab26083b707fa
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 731f1baa9d144a9897cb1d341c2092b8
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1442040525
|
||||||
|
licenseType: Pro
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!21 &2100000
|
||||||
|
Material:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: LiberationSans SDF - Drop Shadow
|
||||||
|
m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3}
|
||||||
|
m_ShaderKeywords: OUTLINE_ON UNDERLAY_ON
|
||||||
|
m_LightmapFlags: 5
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: -1
|
||||||
|
stringTagMap: {}
|
||||||
|
disabledShaderPasses: []
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs:
|
||||||
|
- _BumpMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _Cube:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _FaceTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MainTex:
|
||||||
|
m_Texture: {fileID: 28684132378477856, guid: 8f586378b4e144a9851e7b34d9b748ee,
|
||||||
|
type: 2}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _OutlineTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
m_Floats:
|
||||||
|
- _Ambient: 0.5
|
||||||
|
- _Bevel: 0.5
|
||||||
|
- _BevelClamp: 0
|
||||||
|
- _BevelOffset: 0
|
||||||
|
- _BevelRoundness: 0
|
||||||
|
- _BevelWidth: 0
|
||||||
|
- _BumpFace: 0
|
||||||
|
- _BumpOutline: 0
|
||||||
|
- _ColorMask: 15
|
||||||
|
- _Diffuse: 0.5
|
||||||
|
- _DiffusePower: 1
|
||||||
|
- _FaceDilate: 0.1
|
||||||
|
- _FaceUVSpeedX: 0
|
||||||
|
- _FaceUVSpeedY: 0
|
||||||
|
- _GlowInner: 0.05
|
||||||
|
- _GlowOffset: 0
|
||||||
|
- _GlowOuter: 0.05
|
||||||
|
- _GlowPower: 0.75
|
||||||
|
- _GradientScale: 10
|
||||||
|
- _LightAngle: 3.1416
|
||||||
|
- _MaskSoftnessX: 0
|
||||||
|
- _MaskSoftnessY: 0
|
||||||
|
- _OutlineSoftness: 0
|
||||||
|
- _OutlineUVSpeedX: 0
|
||||||
|
- _OutlineUVSpeedY: 0
|
||||||
|
- _OutlineWidth: 0.1
|
||||||
|
- _PerspectiveFilter: 0.875
|
||||||
|
- _Reflectivity: 10
|
||||||
|
- _ScaleRatioA: 0.9
|
||||||
|
- _ScaleRatioB: 0.73125
|
||||||
|
- _ScaleRatioC: 0.64125
|
||||||
|
- _ScaleX: 1
|
||||||
|
- _ScaleY: 1
|
||||||
|
- _ShaderFlags: 0
|
||||||
|
- _Sharpness: 0
|
||||||
|
- _SpecularPower: 2
|
||||||
|
- _Stencil: 0
|
||||||
|
- _StencilComp: 8
|
||||||
|
- _StencilOp: 0
|
||||||
|
- _StencilReadMask: 255
|
||||||
|
- _StencilWriteMask: 255
|
||||||
|
- _TextureHeight: 1024
|
||||||
|
- _TextureWidth: 1024
|
||||||
|
- _UnderlayDilate: 0
|
||||||
|
- _UnderlayOffsetX: 0.5
|
||||||
|
- _UnderlayOffsetY: -0.5
|
||||||
|
- _UnderlaySoftness: 0.05
|
||||||
|
- _VertexOffsetX: 0
|
||||||
|
- _VertexOffsetY: 0
|
||||||
|
- _WeightBold: 0.75
|
||||||
|
- _WeightNormal: 0
|
||||||
|
m_Colors:
|
||||||
|
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||||
|
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0}
|
||||||
|
- _FaceColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _GlowColor: {r: 0, g: 1, b: 0, a: 0.5}
|
||||||
|
- _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767}
|
||||||
|
- _OutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _SpecularColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e73a58f6e2794ae7b1b7e50b7fb811b0
|
||||||
|
timeCreated: 1484172806
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,343 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!21 &2180264
|
||||||
|
Material:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: LiberationSans SDF Material
|
||||||
|
m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3}
|
||||||
|
m_ShaderKeywords:
|
||||||
|
m_LightmapFlags: 1
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: -1
|
||||||
|
stringTagMap: {}
|
||||||
|
disabledShaderPasses: []
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs:
|
||||||
|
- _BumpMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _Cube:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _DetailAlbedoMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _DetailMask:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _DetailNormalMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _EmissionMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _FaceTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MainTex:
|
||||||
|
m_Texture: {fileID: 28268798066460806}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MetallicGlossMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _OcclusionMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _OutlineTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _ParallaxMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
m_Floats:
|
||||||
|
- _Ambient: 0.5
|
||||||
|
- _Bevel: 0.5
|
||||||
|
- _BevelClamp: 0
|
||||||
|
- _BevelOffset: 0
|
||||||
|
- _BevelRoundness: 0
|
||||||
|
- _BevelWidth: 0
|
||||||
|
- _BumpFace: 0
|
||||||
|
- _BumpOutline: 0
|
||||||
|
- _BumpScale: 1
|
||||||
|
- _ColorMask: 15
|
||||||
|
- _CullMode: 0
|
||||||
|
- _Cutoff: 0.5
|
||||||
|
- _DetailNormalMapScale: 1
|
||||||
|
- _Diffuse: 0.5
|
||||||
|
- _DstBlend: 0
|
||||||
|
- _FaceDilate: 0
|
||||||
|
- _FaceUVSpeedX: 0
|
||||||
|
- _FaceUVSpeedY: 0
|
||||||
|
- _GlossMapScale: 1
|
||||||
|
- _Glossiness: 0.5
|
||||||
|
- _GlossyReflections: 1
|
||||||
|
- _GlowInner: 0.05
|
||||||
|
- _GlowOffset: 0
|
||||||
|
- _GlowOuter: 0.05
|
||||||
|
- _GlowPower: 0.75
|
||||||
|
- _GradientScale: 10
|
||||||
|
- _LightAngle: 3.1416
|
||||||
|
- _MaskSoftnessX: 0
|
||||||
|
- _MaskSoftnessY: 0
|
||||||
|
- _Metallic: 0
|
||||||
|
- _Mode: 0
|
||||||
|
- _OcclusionStrength: 1
|
||||||
|
- _OutlineSoftness: 0
|
||||||
|
- _OutlineUVSpeedX: 0
|
||||||
|
- _OutlineUVSpeedY: 0
|
||||||
|
- _OutlineWidth: 0
|
||||||
|
- _Parallax: 0.02
|
||||||
|
- _PerspectiveFilter: 0.875
|
||||||
|
- _Reflectivity: 10
|
||||||
|
- _ScaleRatioA: 0.90909094
|
||||||
|
- _ScaleRatioB: 0.73125
|
||||||
|
- _ScaleRatioC: 0.7386364
|
||||||
|
- _ScaleX: 1
|
||||||
|
- _ScaleY: 1
|
||||||
|
- _ShaderFlags: 0
|
||||||
|
- _Sharpness: 0
|
||||||
|
- _SmoothnessTextureChannel: 0
|
||||||
|
- _SpecularHighlights: 1
|
||||||
|
- _SpecularPower: 2
|
||||||
|
- _SrcBlend: 1
|
||||||
|
- _Stencil: 0
|
||||||
|
- _StencilComp: 8
|
||||||
|
- _StencilOp: 0
|
||||||
|
- _StencilReadMask: 255
|
||||||
|
- _StencilWriteMask: 255
|
||||||
|
- _TextureHeight: 512
|
||||||
|
- _TextureWidth: 512
|
||||||
|
- _UVSec: 0
|
||||||
|
- _UnderlayDilate: 0
|
||||||
|
- _UnderlayOffsetX: 0
|
||||||
|
- _UnderlayOffsetY: 0
|
||||||
|
- _UnderlaySoftness: 0
|
||||||
|
- _VertexOffsetX: 0
|
||||||
|
- _VertexOffsetY: 0
|
||||||
|
- _WeightBold: 0.75
|
||||||
|
- _WeightNormal: 0
|
||||||
|
- _ZWrite: 1
|
||||||
|
m_Colors:
|
||||||
|
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||||
|
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0}
|
||||||
|
- _FaceColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _GlowColor: {r: 0, g: 1, b: 0, a: 0.5}
|
||||||
|
- _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767}
|
||||||
|
- _OutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _SpecularColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 71c1514a6bd24e1e882cebbe1904ce04, type: 3}
|
||||||
|
m_Name: LiberationSans SDF - Fallback
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
hashCode: -1699145518
|
||||||
|
material: {fileID: 2180264}
|
||||||
|
materialHashCode: 462855346
|
||||||
|
m_Version: 1.1.0
|
||||||
|
m_SourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75
|
||||||
|
m_SourceFontFile_EditorRef: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75,
|
||||||
|
type: 3}
|
||||||
|
m_SourceFontFile: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75, type: 3}
|
||||||
|
m_AtlasPopulationMode: 1
|
||||||
|
m_FaceInfo:
|
||||||
|
m_FamilyName: Liberation Sans
|
||||||
|
m_StyleName: Regular
|
||||||
|
m_PointSize: 86
|
||||||
|
m_Scale: 1
|
||||||
|
m_LineHeight: 98.8916
|
||||||
|
m_AscentLine: 77.853516
|
||||||
|
m_CapLine: 59
|
||||||
|
m_MeanLine: 45
|
||||||
|
m_Baseline: 0
|
||||||
|
m_DescentLine: -18.22461
|
||||||
|
m_SuperscriptOffset: 77.853516
|
||||||
|
m_SuperscriptSize: 0.5
|
||||||
|
m_SubscriptOffset: -18.22461
|
||||||
|
m_SubscriptSize: 0.5
|
||||||
|
m_UnderlineOffset: -12.261719
|
||||||
|
m_UnderlineThickness: 6.298828
|
||||||
|
m_StrikethroughOffset: 18
|
||||||
|
m_StrikethroughThickness: 6.298828
|
||||||
|
m_TabWidth: 24
|
||||||
|
m_GlyphTable: []
|
||||||
|
m_CharacterTable: []
|
||||||
|
m_AtlasTextures:
|
||||||
|
- {fileID: 28268798066460806}
|
||||||
|
m_AtlasTextureIndex: 0
|
||||||
|
m_IsMultiAtlasTexturesEnabled: 0
|
||||||
|
m_ClearDynamicDataOnBuild: 1
|
||||||
|
m_UsedGlyphRects: []
|
||||||
|
m_FreeGlyphRects:
|
||||||
|
- m_X: 0
|
||||||
|
m_Y: 0
|
||||||
|
m_Width: 511
|
||||||
|
m_Height: 511
|
||||||
|
m_fontInfo:
|
||||||
|
Name: Liberation Sans
|
||||||
|
PointSize: 86
|
||||||
|
Scale: 1
|
||||||
|
CharacterCount: 250
|
||||||
|
LineHeight: 98.90625
|
||||||
|
Baseline: 0
|
||||||
|
Ascender: 77.84375
|
||||||
|
CapHeight: 59.1875
|
||||||
|
Descender: -18.21875
|
||||||
|
CenterLine: 0
|
||||||
|
SuperscriptOffset: 77.84375
|
||||||
|
SubscriptOffset: -12.261719
|
||||||
|
SubSize: 0.5
|
||||||
|
Underline: -12.261719
|
||||||
|
UnderlineThickness: 6.298828
|
||||||
|
strikethrough: 23.675
|
||||||
|
strikethroughThickness: 0
|
||||||
|
TabWidth: 239.0625
|
||||||
|
Padding: 9
|
||||||
|
AtlasWidth: 1024
|
||||||
|
AtlasHeight: 1024
|
||||||
|
atlas: {fileID: 0}
|
||||||
|
m_AtlasWidth: 512
|
||||||
|
m_AtlasHeight: 512
|
||||||
|
m_AtlasPadding: 9
|
||||||
|
m_AtlasRenderMode: 4169
|
||||||
|
m_glyphInfoList: []
|
||||||
|
m_KerningTable:
|
||||||
|
kerningPairs: []
|
||||||
|
m_FontFeatureTable:
|
||||||
|
m_GlyphPairAdjustmentRecords: []
|
||||||
|
fallbackFontAssets: []
|
||||||
|
m_FallbackFontAssetTable: []
|
||||||
|
m_CreationSettings:
|
||||||
|
sourceFontFileName:
|
||||||
|
sourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75
|
||||||
|
pointSizeSamplingMode: 0
|
||||||
|
pointSize: 86
|
||||||
|
padding: 9
|
||||||
|
packingMode: 4
|
||||||
|
atlasWidth: 512
|
||||||
|
atlasHeight: 512
|
||||||
|
characterSetSelectionMode: 1
|
||||||
|
characterSequence: 32 - 126, 160 - 255, 8192 - 8303, 8364, 8482, 9633
|
||||||
|
referencedFontAssetGUID: 8f586378b4e144a9851e7b34d9b748ee
|
||||||
|
referencedTextAssetGUID:
|
||||||
|
fontStyle: 0
|
||||||
|
fontStyleModifier: 0
|
||||||
|
renderMode: 4169
|
||||||
|
includeFontFeatures: 1
|
||||||
|
m_FontWeightTable:
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
fontWeights:
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
normalStyle: 0
|
||||||
|
normalSpacingOffset: 0
|
||||||
|
boldStyle: 0.75
|
||||||
|
boldSpacing: 7
|
||||||
|
italicStyle: 35
|
||||||
|
tabSize: 10
|
||||||
|
--- !u!28 &28268798066460806
|
||||||
|
Texture2D:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: LiberationSans SDF Atlas
|
||||||
|
m_ImageContentsHash:
|
||||||
|
serializedVersion: 2
|
||||||
|
Hash: 00000000000000000000000000000000
|
||||||
|
m_ForcedFallbackFormat: 4
|
||||||
|
m_DownscaleFallback: 0
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Width: 0
|
||||||
|
m_Height: 0
|
||||||
|
m_CompleteImageSize: 0
|
||||||
|
m_TextureFormat: 1
|
||||||
|
m_MipCount: 1
|
||||||
|
m_IsReadable: 1
|
||||||
|
m_StreamingMipmaps: 0
|
||||||
|
m_StreamingMipmapsPriority: 0
|
||||||
|
m_AlphaIsTransparency: 0
|
||||||
|
m_ImageCount: 1
|
||||||
|
m_TextureDimension: 2
|
||||||
|
m_TextureSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_FilterMode: 1
|
||||||
|
m_Aniso: 1
|
||||||
|
m_MipBias: 0
|
||||||
|
m_WrapU: 0
|
||||||
|
m_WrapV: 0
|
||||||
|
m_WrapW: 0
|
||||||
|
m_LightmapFormat: 0
|
||||||
|
m_ColorSpace: 0
|
||||||
|
image data: 0
|
||||||
|
_typelessdata:
|
||||||
|
m_StreamData:
|
||||||
|
offset: 0
|
||||||
|
size: 0
|
||||||
|
path:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2e498d1c8094910479dc3e1b768306a4
|
||||||
|
timeCreated: 1484171803
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!21 &2100000
|
||||||
|
Material:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: LiberationSans SDF - Outline
|
||||||
|
m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3}
|
||||||
|
m_ShaderKeywords: OUTLINE_ON
|
||||||
|
m_LightmapFlags: 5
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: -1
|
||||||
|
stringTagMap: {}
|
||||||
|
disabledShaderPasses: []
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs:
|
||||||
|
- _BumpMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _Cube:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _FaceTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MainTex:
|
||||||
|
m_Texture: {fileID: 28684132378477856, guid: 8f586378b4e144a9851e7b34d9b748ee,
|
||||||
|
type: 2}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _OutlineTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
m_Floats:
|
||||||
|
- _Ambient: 0.5
|
||||||
|
- _Bevel: 0.5
|
||||||
|
- _BevelClamp: 0
|
||||||
|
- _BevelOffset: 0
|
||||||
|
- _BevelRoundness: 0
|
||||||
|
- _BevelWidth: 0
|
||||||
|
- _BumpFace: 0
|
||||||
|
- _BumpOutline: 0
|
||||||
|
- _ColorMask: 15
|
||||||
|
- _Diffuse: 0.5
|
||||||
|
- _FaceDilate: 0.1
|
||||||
|
- _FaceUVSpeedX: 0
|
||||||
|
- _FaceUVSpeedY: 0
|
||||||
|
- _GlowInner: 0.05
|
||||||
|
- _GlowOffset: 0
|
||||||
|
- _GlowOuter: 0.05
|
||||||
|
- _GlowPower: 0.75
|
||||||
|
- _GradientScale: 10
|
||||||
|
- _LightAngle: 3.1416
|
||||||
|
- _MaskSoftnessX: 0
|
||||||
|
- _MaskSoftnessY: 0
|
||||||
|
- _OutlineSoftness: 0
|
||||||
|
- _OutlineUVSpeedX: 0
|
||||||
|
- _OutlineUVSpeedY: 0
|
||||||
|
- _OutlineWidth: 0.1
|
||||||
|
- _PerspectiveFilter: 0.875
|
||||||
|
- _Reflectivity: 10
|
||||||
|
- _ScaleRatioA: 0.9
|
||||||
|
- _ScaleRatioB: 0.73125
|
||||||
|
- _ScaleRatioC: 0.64125
|
||||||
|
- _ScaleX: 1
|
||||||
|
- _ScaleY: 1
|
||||||
|
- _ShaderFlags: 0
|
||||||
|
- _Sharpness: 0
|
||||||
|
- _SpecularPower: 2
|
||||||
|
- _Stencil: 0
|
||||||
|
- _StencilComp: 8
|
||||||
|
- _StencilOp: 0
|
||||||
|
- _StencilReadMask: 255
|
||||||
|
- _StencilWriteMask: 255
|
||||||
|
- _TextureHeight: 1024
|
||||||
|
- _TextureWidth: 1024
|
||||||
|
- _UnderlayDilate: 0
|
||||||
|
- _UnderlayOffsetX: 0
|
||||||
|
- _UnderlayOffsetY: 0
|
||||||
|
- _UnderlaySoftness: 0
|
||||||
|
- _VertexOffsetX: 0
|
||||||
|
- _VertexOffsetY: 0
|
||||||
|
- _WeightBold: 0.75
|
||||||
|
- _WeightNormal: 0
|
||||||
|
m_Colors:
|
||||||
|
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||||
|
- _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0}
|
||||||
|
- _FaceColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _GlowColor: {r: 0, g: 1, b: 0, a: 0.5}
|
||||||
|
- _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767}
|
||||||
|
- _OutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _SpecularColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 79459efec17a4d00a321bdcc27bbc385
|
||||||
|
timeCreated: 1484172856
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8f586378b4e144a9851e7b34d9b748ee
|
||||||
|
timeCreated: 1484171803
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
)]}〕〉》」』】〙〗〟’”⦆»ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻‐゠–〜?!‼⁇⁈⁉・、%,.:;。!?]):;=}¢°"†‡℃〆%,.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fade42e8bc714b018fac513c043d323b
|
||||||
|
timeCreated: 1425440388
|
||||||
|
licenseType: Store
|
||||||
|
TextScriptImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
([{〔〈《「『【〘〖〝‘“⦅«$—…‥〳〴〵\[({£¥"々〇$¥₩ #
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d82c1b31c7e74239bff1220585707d2b
|
||||||
|
timeCreated: 1425440388
|
||||||
|
licenseType: Store
|
||||||
|
TextScriptImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 512a49d95c0c4332bdd98131869c23c9
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1441876896
|
||||||
|
licenseType: Pro
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,659 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!21 &2103686
|
||||||
|
Material:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: TextMeshPro/Sprite
|
||||||
|
m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3}
|
||||||
|
m_ShaderKeywords: UNITY_UI_CLIP_RECT
|
||||||
|
m_LightmapFlags: 5
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: -1
|
||||||
|
stringTagMap: {}
|
||||||
|
disabledShaderPasses: []
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs:
|
||||||
|
- _MainTex:
|
||||||
|
m_Texture: {fileID: 2800000, guid: dffef66376be4fa480fb02b19edbe903, type: 3}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
m_Floats:
|
||||||
|
- _ColorMask: 15
|
||||||
|
- _CullMode: 0
|
||||||
|
- _Stencil: 0
|
||||||
|
- _StencilComp: 8
|
||||||
|
- _StencilOp: 0
|
||||||
|
- _StencilReadMask: 255
|
||||||
|
- _StencilWriteMask: 255
|
||||||
|
- _UseUIAlphaClip: 0
|
||||||
|
m_Colors:
|
||||||
|
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||||
|
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 84a92b25f83d49b9bc132d206b370281, type: 3}
|
||||||
|
m_Name: EmojiOne
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
hashCode: -1836805472
|
||||||
|
material: {fileID: 2103686}
|
||||||
|
materialHashCode: 0
|
||||||
|
m_Version: 1.1.0
|
||||||
|
m_FaceInfo:
|
||||||
|
m_FamilyName:
|
||||||
|
m_StyleName:
|
||||||
|
m_PointSize: 0
|
||||||
|
m_Scale: 0
|
||||||
|
m_LineHeight: 0
|
||||||
|
m_AscentLine: 0
|
||||||
|
m_CapLine: 0
|
||||||
|
m_MeanLine: 0
|
||||||
|
m_Baseline: 0
|
||||||
|
m_DescentLine: 0
|
||||||
|
m_SuperscriptOffset: 0
|
||||||
|
m_SuperscriptSize: 0
|
||||||
|
m_SubscriptOffset: 0
|
||||||
|
m_SubscriptSize: 0
|
||||||
|
m_UnderlineOffset: 0
|
||||||
|
m_UnderlineThickness: 0
|
||||||
|
m_StrikethroughOffset: 0
|
||||||
|
m_StrikethroughThickness: 0
|
||||||
|
m_TabWidth: 0
|
||||||
|
spriteSheet: {fileID: 2800000, guid: dffef66376be4fa480fb02b19edbe903, type: 3}
|
||||||
|
m_SpriteCharacterTable:
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128522
|
||||||
|
m_GlyphIndex: 0
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: Smiling face with smiling eyes
|
||||||
|
m_HashCode: -1318250903
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128523
|
||||||
|
m_GlyphIndex: 1
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f60b
|
||||||
|
m_HashCode: 57188339
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128525
|
||||||
|
m_GlyphIndex: 2
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f60d
|
||||||
|
m_HashCode: 57188341
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128526
|
||||||
|
m_GlyphIndex: 3
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f60e
|
||||||
|
m_HashCode: 57188340
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128512
|
||||||
|
m_GlyphIndex: 4
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: Grinning face
|
||||||
|
m_HashCode: -95541379
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128513
|
||||||
|
m_GlyphIndex: 5
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f601
|
||||||
|
m_HashCode: 57188256
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128514
|
||||||
|
m_GlyphIndex: 6
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: Face with tears of joy
|
||||||
|
m_HashCode: 239522663
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128515
|
||||||
|
m_GlyphIndex: 7
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f603
|
||||||
|
m_HashCode: 57188258
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128516
|
||||||
|
m_GlyphIndex: 8
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f604
|
||||||
|
m_HashCode: 57188261
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128517
|
||||||
|
m_GlyphIndex: 9
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f605
|
||||||
|
m_HashCode: 57188260
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128518
|
||||||
|
m_GlyphIndex: 10
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f606
|
||||||
|
m_HashCode: 57188263
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128521
|
||||||
|
m_GlyphIndex: 11
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f609
|
||||||
|
m_HashCode: 57188264
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 0
|
||||||
|
m_GlyphIndex: 12
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: .notdef
|
||||||
|
m_HashCode: -600915428
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 129315
|
||||||
|
m_GlyphIndex: 13
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f923
|
||||||
|
m_HashCode: 57200239
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 9786
|
||||||
|
m_GlyphIndex: 14
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 263a
|
||||||
|
m_HashCode: 1748406
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 9785
|
||||||
|
m_GlyphIndex: 15
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 2639
|
||||||
|
m_HashCode: 1748462
|
||||||
|
m_SpriteGlyphTable:
|
||||||
|
- m_Index: 0
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 0
|
||||||
|
m_Y: 384
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 1
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 128
|
||||||
|
m_Y: 384
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 2
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 256
|
||||||
|
m_Y: 384
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 3
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 384
|
||||||
|
m_Y: 384
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 4
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 0
|
||||||
|
m_Y: 256
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 5
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 128
|
||||||
|
m_Y: 256
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 6
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 256
|
||||||
|
m_Y: 256
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 7
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 384
|
||||||
|
m_Y: 256
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 8
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 0
|
||||||
|
m_Y: 128
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 9
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 128
|
||||||
|
m_Y: 128
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 10
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 256
|
||||||
|
m_Y: 128
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 11
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 384
|
||||||
|
m_Y: 128
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 12
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 0
|
||||||
|
m_Y: 0
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 13
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 128
|
||||||
|
m_Y: 0
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 14
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 256
|
||||||
|
m_Y: 0
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 15
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 384
|
||||||
|
m_Y: 0
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
spriteInfoList:
|
||||||
|
- id: 0
|
||||||
|
x: 0
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: Smiling face with smiling eyes
|
||||||
|
hashCode: -1318250903
|
||||||
|
unicode: 128522
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 1
|
||||||
|
x: 128
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f60b
|
||||||
|
hashCode: 57188339
|
||||||
|
unicode: 128523
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 2
|
||||||
|
x: 256
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f60d
|
||||||
|
hashCode: 57188341
|
||||||
|
unicode: 128525
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 3
|
||||||
|
x: 384
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f60e
|
||||||
|
hashCode: 57188340
|
||||||
|
unicode: 128526
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 4
|
||||||
|
x: 0
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: Grinning face
|
||||||
|
hashCode: -95541379
|
||||||
|
unicode: 128512
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 5
|
||||||
|
x: 128
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f601
|
||||||
|
hashCode: 57188256
|
||||||
|
unicode: 128513
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 6
|
||||||
|
x: 256
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: Face with tears of joy
|
||||||
|
hashCode: 239522663
|
||||||
|
unicode: 128514
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 7
|
||||||
|
x: 384
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f603
|
||||||
|
hashCode: 57188258
|
||||||
|
unicode: 128515
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 8
|
||||||
|
x: 0
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f604
|
||||||
|
hashCode: 57188261
|
||||||
|
unicode: 128516
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 9
|
||||||
|
x: 128
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f605
|
||||||
|
hashCode: 57188260
|
||||||
|
unicode: 128517
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 10
|
||||||
|
x: 256
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f606
|
||||||
|
hashCode: 57188263
|
||||||
|
unicode: 128518
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 11
|
||||||
|
x: 384
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f609
|
||||||
|
hashCode: 57188264
|
||||||
|
unicode: 128521
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 12
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f618
|
||||||
|
hashCode: 57188168
|
||||||
|
unicode: 128536
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 13
|
||||||
|
x: 128
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f923
|
||||||
|
hashCode: 57200239
|
||||||
|
unicode: 129315
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 14
|
||||||
|
x: 256
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 263a
|
||||||
|
hashCode: 1748406
|
||||||
|
unicode: 9786
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 15
|
||||||
|
x: 384
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 2639
|
||||||
|
hashCode: 1748462
|
||||||
|
unicode: 9785
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
fallbackSpriteAssets: []
|
||||||
|
--- !u!21 &1369835458
|
||||||
|
Material:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: TextMeshPro/Sprite
|
||||||
|
m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3}
|
||||||
|
m_ShaderKeywords:
|
||||||
|
m_LightmapFlags: 5
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: -1
|
||||||
|
stringTagMap: {}
|
||||||
|
disabledShaderPasses: []
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs: []
|
||||||
|
m_Floats: []
|
||||||
|
m_Colors: []
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c41005c129ba4d66911b75229fd70b45
|
||||||
|
timeCreated: 1480316912
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4aecb92fff08436c8303b10eab8da368
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1441876950
|
||||||
|
licenseType: Pro
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: ab2114bdc8544297b417dfefe9f1e410, type: 3}
|
||||||
|
m_Name: Default Style Sheet
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_StyleList:
|
||||||
|
- m_Name: H1
|
||||||
|
m_HashCode: 2425
|
||||||
|
m_OpeningDefinition: <size=2em><b><#40ff80>*
|
||||||
|
m_ClosingDefinition: '*</size></b></color>'
|
||||||
|
m_OpeningTagArray: 3c00000073000000690000007a000000650000003d00000032000000650000006d0000003e0000003c000000620000003e0000003c000000230000003400000030000000660000006600000038000000300000003e0000002a000000
|
||||||
|
m_ClosingTagArray: 2a0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000
|
||||||
|
- m_Name: Quote
|
||||||
|
m_HashCode: 92254330
|
||||||
|
m_OpeningDefinition: <i><size=75%><margin=10%>
|
||||||
|
m_ClosingDefinition: </i></size></width></margin>
|
||||||
|
m_OpeningTagArray: 3c000000690000003e0000003c00000073000000690000007a000000650000003d0000003700000035000000250000003e0000003c0000006d000000610000007200000067000000690000006e0000003d0000003100000030000000250000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f000000690000003e0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f00000077000000690000006400000074000000680000003e0000003c0000002f0000006d000000610000007200000067000000690000006e0000003e000000
|
||||||
|
- m_Name: Link
|
||||||
|
m_HashCode: 2687968
|
||||||
|
m_OpeningDefinition: <u><#40a0ff><link="ID_01">
|
||||||
|
m_ClosingDefinition: </u></color></link>
|
||||||
|
m_OpeningTagArray: 3c000000750000003e0000003c000000230000003400000030000000610000003000000066000000660000003e0000003c0000006c000000690000006e0000006b0000003d0000002200000049000000440000005f0000003000000031000000220000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f000000750000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f0000006c000000690000006e0000006b0000003e000000
|
||||||
|
- m_Name: Title
|
||||||
|
m_HashCode: 98732960
|
||||||
|
m_OpeningDefinition: <size=125%><b><align=center>
|
||||||
|
m_ClosingDefinition: </size></b></align>
|
||||||
|
m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000003200000035000000250000003e0000003c000000620000003e0000003c000000610000006c00000069000000670000006e0000003d00000063000000650000006e0000007400000065000000720000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000610000006c00000069000000670000006e0000003e000000
|
||||||
|
- m_Name: H2
|
||||||
|
m_HashCode: 2426
|
||||||
|
m_OpeningDefinition: <size=1.5em><b><#4080FF>
|
||||||
|
m_ClosingDefinition: </size></b></color>
|
||||||
|
m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000002e00000035000000650000006d0000003e0000003c000000620000003e0000003c000000230000003400000030000000380000003000000046000000460000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000
|
||||||
|
- m_Name: H3
|
||||||
|
m_HashCode: 2427
|
||||||
|
m_OpeningDefinition: <size=1.17em><b><#FF8040>
|
||||||
|
m_ClosingDefinition: </size></b></color>
|
||||||
|
m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000002e0000003100000037000000650000006d0000003e0000003c000000620000003e0000003c000000230000004600000046000000380000003000000034000000300000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000
|
||||||
|
- m_Name: C1
|
||||||
|
m_HashCode: 2194
|
||||||
|
m_OpeningDefinition: <color=#ffff40>
|
||||||
|
m_ClosingDefinition: </color>
|
||||||
|
m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000006600000066000000660000006600000034000000300000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e000000
|
||||||
|
- m_Name: C2
|
||||||
|
m_HashCode: 2193
|
||||||
|
m_OpeningDefinition: <color=#ff40FF><size=125%>
|
||||||
|
m_ClosingDefinition: </color></size>
|
||||||
|
m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000006600000066000000340000003000000046000000460000003e0000003c00000073000000690000007a000000650000003d000000310000003200000035000000250000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f00000073000000690000007a000000650000003e000000
|
||||||
|
- m_Name: C3
|
||||||
|
m_HashCode: 2192
|
||||||
|
m_OpeningDefinition: <color=#80A0FF><b>
|
||||||
|
m_ClosingDefinition: </color></b>
|
||||||
|
m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000003800000030000000410000003000000046000000460000003e0000003c000000620000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f000000620000003e000000
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f952c082cb03451daed3ee968ac6c63e
|
||||||
|
timeCreated: 1432805430
|
||||||
|
licenseType: Store
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 2705215ac5b84b70bacc50632be6e391, type: 3}
|
||||||
|
m_Name: TMP Settings
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_enableWordWrapping: 1
|
||||||
|
m_enableKerning: 1
|
||||||
|
m_enableExtraPadding: 0
|
||||||
|
m_enableTintAllSprites: 0
|
||||||
|
m_enableParseEscapeCharacters: 1
|
||||||
|
m_EnableRaycastTarget: 1
|
||||||
|
m_GetFontFeaturesAtRuntime: 1
|
||||||
|
m_missingGlyphCharacter: 0
|
||||||
|
m_warningsDisabled: 0
|
||||||
|
m_defaultFontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||||
|
m_defaultFontAssetPath: Fonts & Materials/
|
||||||
|
m_defaultFontSize: 36
|
||||||
|
m_defaultAutoSizeMinRatio: 0.5
|
||||||
|
m_defaultAutoSizeMaxRatio: 2
|
||||||
|
m_defaultTextMeshProTextContainerSize: {x: 20, y: 5}
|
||||||
|
m_defaultTextMeshProUITextContainerSize: {x: 200, y: 50}
|
||||||
|
m_autoSizeTextContainer: 0
|
||||||
|
m_fallbackFontAssets: []
|
||||||
|
m_matchMaterialPreset: 1
|
||||||
|
m_defaultSpriteAsset: {fileID: 11400000, guid: c41005c129ba4d66911b75229fd70b45,
|
||||||
|
type: 2}
|
||||||
|
m_defaultSpriteAssetPath: Sprite Assets/
|
||||||
|
m_enableEmojiSupport: 1
|
||||||
|
m_MissingCharacterSpriteUnicode: 0
|
||||||
|
m_defaultColorGradientPresetsPath: Color Gradient Presets/
|
||||||
|
m_defaultStyleSheet: {fileID: 11400000, guid: f952c082cb03451daed3ee968ac6c63e,
|
||||||
|
type: 2}
|
||||||
|
m_StyleSheetsResourcePath:
|
||||||
|
m_leadingCharacters: {fileID: 4900000, guid: d82c1b31c7e74239bff1220585707d2b, type: 3}
|
||||||
|
m_followingCharacters: {fileID: 4900000, guid: fade42e8bc714b018fac513c043d323b,
|
||||||
|
type: 3}
|
||||||
|
m_UseModernHangulLineBreakingRules: 0
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3f5b5dff67a942289a9defa416b206f3
|
||||||
|
timeCreated: 1436653997
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e9f693669af91aa45ad615fc681ed29f
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
Shader "TextMeshPro/Bitmap Custom Atlas" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_FaceTex ("Font Texture", 2D) = "white" {}
|
||||||
|
[HDR]_FaceColor ("Text Color", Color) = (1,1,1,1)
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_Padding ("Padding", float) = 0
|
||||||
|
|
||||||
|
_StencilComp("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil("Stencil ID", Float) = 0
|
||||||
|
_StencilOp("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode("Cull Mode", Float) = 0
|
||||||
|
_ColorMask("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader{
|
||||||
|
|
||||||
|
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref[_Stencil]
|
||||||
|
Comp[_StencilComp]
|
||||||
|
Pass[_StencilOp]
|
||||||
|
ReadMask[_StencilReadMask]
|
||||||
|
WriteMask[_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Lighting Off
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
ZWrite Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
Blend SrcAlpha OneMinusSrcAlpha
|
||||||
|
ColorMask[_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex vert
|
||||||
|
#pragma fragment frag
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
|
||||||
|
struct appdata_t {
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct v2f {
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
float4 mask : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform sampler2D _MainTex;
|
||||||
|
uniform sampler2D _FaceTex;
|
||||||
|
uniform float4 _FaceTex_ST;
|
||||||
|
uniform fixed4 _FaceColor;
|
||||||
|
|
||||||
|
uniform float _VertexOffsetX;
|
||||||
|
uniform float _VertexOffsetY;
|
||||||
|
uniform float4 _ClipRect;
|
||||||
|
uniform float _MaskSoftnessX;
|
||||||
|
uniform float _MaskSoftnessY;
|
||||||
|
|
||||||
|
float2 UnpackUV(float uv)
|
||||||
|
{
|
||||||
|
float2 output;
|
||||||
|
output.x = floor(uv / 4096);
|
||||||
|
output.y = uv - 4096 * output.x;
|
||||||
|
|
||||||
|
return output * 0.001953125;
|
||||||
|
}
|
||||||
|
|
||||||
|
v2f vert (appdata_t v)
|
||||||
|
{
|
||||||
|
float4 vert = v.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
vert.xy += (vert.w * 0.5) / _ScreenParams.xy;
|
||||||
|
|
||||||
|
float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert));
|
||||||
|
|
||||||
|
fixed4 faceColor = v.color;
|
||||||
|
faceColor *= _FaceColor;
|
||||||
|
|
||||||
|
v2f OUT;
|
||||||
|
OUT.vertex = vPosition;
|
||||||
|
OUT.color = faceColor;
|
||||||
|
OUT.texcoord0 = v.texcoord0;
|
||||||
|
OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(v.texcoord1), _FaceTex);
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1]));
|
||||||
|
|
||||||
|
// Clamp _ClipRect to 16bit.
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
|
||||||
|
return OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed4 frag (v2f IN) : SV_Target
|
||||||
|
{
|
||||||
|
fixed4 color = tex2D(_MainTex, IN.texcoord0) * tex2D(_FaceTex, IN.texcoord1) * IN.color;
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
|
||||||
|
color *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(color.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 48bb5f55d8670e349b6e614913f9d910
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
Shader "TextMeshPro/Mobile/Bitmap" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
[HDR]_Color ("Text Color", Color) = (1,1,1,1)
|
||||||
|
_DiffusePower ("Diffuse Power", Range(1.0,4.0)) = 1.0
|
||||||
|
|
||||||
|
_VertexOffsetX("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY("Vertex OffsetY", float) = 0
|
||||||
|
_MaskSoftnessX("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
|
||||||
|
_StencilComp("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil("Stencil ID", Float) = 0
|
||||||
|
_StencilOp("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode("Cull Mode", Float) = 0
|
||||||
|
_ColorMask("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
|
||||||
|
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref[_Stencil]
|
||||||
|
Comp[_StencilComp]
|
||||||
|
Pass[_StencilOp]
|
||||||
|
ReadMask[_StencilReadMask]
|
||||||
|
WriteMask[_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Lighting Off
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
ZWrite Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
Blend SrcAlpha OneMinusSrcAlpha
|
||||||
|
ColorMask[_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex vert
|
||||||
|
#pragma fragment frag
|
||||||
|
#pragma fragmentoption ARB_precision_hint_fastest
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
|
||||||
|
struct appdata_t {
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct v2f {
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float4 mask : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
sampler2D _MainTex;
|
||||||
|
fixed4 _Color;
|
||||||
|
float _DiffusePower;
|
||||||
|
|
||||||
|
uniform float _VertexOffsetX;
|
||||||
|
uniform float _VertexOffsetY;
|
||||||
|
uniform float4 _ClipRect;
|
||||||
|
uniform float _MaskSoftnessX;
|
||||||
|
uniform float _MaskSoftnessY;
|
||||||
|
|
||||||
|
v2f vert (appdata_t v)
|
||||||
|
{
|
||||||
|
v2f OUT;
|
||||||
|
float4 vert = v.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
vert.xy += (vert.w * 0.5) / _ScreenParams.xy;
|
||||||
|
|
||||||
|
OUT.vertex = UnityPixelSnap(UnityObjectToClipPos(vert));
|
||||||
|
OUT.color = v.color;
|
||||||
|
OUT.color *= _Color;
|
||||||
|
OUT.color.rgb *= _DiffusePower;
|
||||||
|
OUT.texcoord0 = v.texcoord0;
|
||||||
|
|
||||||
|
float2 pixelSize = OUT.vertex.w;
|
||||||
|
//pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1]));
|
||||||
|
|
||||||
|
// Clamp _ClipRect to 16bit.
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
|
||||||
|
return OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed4 frag (v2f IN) : COLOR
|
||||||
|
{
|
||||||
|
fixed4 color = fixed4(IN.color.rgb, IN.color.a * tex2D(_MainTex, IN.texcoord0).a);
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
|
||||||
|
color *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(color.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
|
||||||
|
Lighting Off Cull Off ZTest Always ZWrite Off Fog { Mode Off }
|
||||||
|
Blend SrcAlpha OneMinusSrcAlpha
|
||||||
|
BindChannels {
|
||||||
|
Bind "Color", color
|
||||||
|
Bind "Vertex", vertex
|
||||||
|
Bind "TexCoord", texcoord0
|
||||||
|
}
|
||||||
|
Pass {
|
||||||
|
SetTexture [_MainTex] {
|
||||||
|
constantColor [_Color] combine constant * primary, constant * texture
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1e3b057af24249748ff873be7fafee47
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
Shader "TextMeshPro/Bitmap" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_FaceTex ("Font Texture", 2D) = "white" {}
|
||||||
|
[HDR]_FaceColor ("Text Color", Color) = (1,1,1,1)
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
|
||||||
|
_StencilComp("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil("Stencil ID", Float) = 0
|
||||||
|
_StencilOp("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode("Cull Mode", Float) = 0
|
||||||
|
_ColorMask("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader{
|
||||||
|
|
||||||
|
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref[_Stencil]
|
||||||
|
Comp[_StencilComp]
|
||||||
|
Pass[_StencilOp]
|
||||||
|
ReadMask[_StencilReadMask]
|
||||||
|
WriteMask[_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Lighting Off
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
ZWrite Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
Blend SrcAlpha OneMinusSrcAlpha
|
||||||
|
ColorMask[_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex vert
|
||||||
|
#pragma fragment frag
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
|
||||||
|
struct appdata_t {
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct v2f {
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
float4 mask : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform sampler2D _MainTex;
|
||||||
|
uniform sampler2D _FaceTex;
|
||||||
|
uniform float4 _FaceTex_ST;
|
||||||
|
uniform fixed4 _FaceColor;
|
||||||
|
|
||||||
|
uniform float _VertexOffsetX;
|
||||||
|
uniform float _VertexOffsetY;
|
||||||
|
uniform float4 _ClipRect;
|
||||||
|
uniform float _MaskSoftnessX;
|
||||||
|
uniform float _MaskSoftnessY;
|
||||||
|
|
||||||
|
float2 UnpackUV(float uv)
|
||||||
|
{
|
||||||
|
float2 output;
|
||||||
|
output.x = floor(uv / 4096);
|
||||||
|
output.y = uv - 4096 * output.x;
|
||||||
|
|
||||||
|
return output * 0.001953125;
|
||||||
|
}
|
||||||
|
|
||||||
|
v2f vert (appdata_t v)
|
||||||
|
{
|
||||||
|
float4 vert = v.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
vert.xy += (vert.w * 0.5) / _ScreenParams.xy;
|
||||||
|
|
||||||
|
float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert));
|
||||||
|
|
||||||
|
fixed4 faceColor = v.color;
|
||||||
|
faceColor *= _FaceColor;
|
||||||
|
|
||||||
|
v2f OUT;
|
||||||
|
OUT.vertex = vPosition;
|
||||||
|
OUT.color = faceColor;
|
||||||
|
OUT.texcoord0 = v.texcoord0;
|
||||||
|
OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(v.texcoord1), _FaceTex);
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1]));
|
||||||
|
|
||||||
|
// Clamp _ClipRect to 16bit.
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
|
||||||
|
return OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed4 frag (v2f IN) : SV_Target
|
||||||
|
{
|
||||||
|
fixed4 color = tex2D(_MainTex, IN.texcoord0);
|
||||||
|
color = fixed4 (tex2D(_FaceTex, IN.texcoord1).rgb * IN.color.rgb, IN.color.a * color.a);
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
|
||||||
|
color *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(color.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 128e987d567d4e2c824d754223b3f3b0
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,317 @@
|
||||||
|
Shader "TextMeshPro/Distance Field Overlay" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_FaceTex ("Face Texture", 2D) = "white" {}
|
||||||
|
_FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineTex ("Outline Texture", 2D) = "white" {}
|
||||||
|
_OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0, 1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_Bevel ("Bevel", Range(0,1)) = 0.5
|
||||||
|
_BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0
|
||||||
|
_BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0
|
||||||
|
_BevelClamp ("Bevel Clamp", Range(0,1)) = 0
|
||||||
|
_BevelRoundness ("Bevel Roundness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416
|
||||||
|
[HDR]_SpecularColor ("Specular", Color) = (1,1,1,1)
|
||||||
|
_SpecularPower ("Specular", Range(0,4)) = 2.0
|
||||||
|
_Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10
|
||||||
|
_Diffuse ("Diffuse", Range(0,1)) = 0.5
|
||||||
|
_Ambient ("Ambient", Range(1,0)) = 0.5
|
||||||
|
|
||||||
|
_BumpMap ("Normal map", 2D) = "bump" {}
|
||||||
|
_BumpOutline ("Bump Outline", Range(0,1)) = 0
|
||||||
|
_BumpFace ("Bump Face", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1)
|
||||||
|
_ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1)
|
||||||
|
_Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ }
|
||||||
|
_EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5)
|
||||||
|
_GlowOffset ("Offset", Range(-1,1)) = 0
|
||||||
|
_GlowInner ("Inner", Range(0,1)) = 0.05
|
||||||
|
_GlowOuter ("Outer", Range(0,1)) = 0.05
|
||||||
|
_GlowPower ("Falloff", Range(1, 0)) = 0.75
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = 0.5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5.0
|
||||||
|
_ScaleX ("Scale X", float) = 1.0
|
||||||
|
_ScaleY ("Scale Y", float) = 1.0
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767)
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue"="Overlay"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest Always
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma target 3.0
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ BEVEL_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
#pragma shader_feature __ GLOW_ON
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
#include "TMPro.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
float4 position : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 atlas : TEXCOORD0; // Atlas
|
||||||
|
float4 param : TEXCOORD1; // alphaClip, scale, bias, weight
|
||||||
|
float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw)
|
||||||
|
float3 viewDir : TEXCOORD3;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float4 texcoord2 : TEXCOORD4; // u,v, scale, bias
|
||||||
|
fixed4 underlayColor : COLOR1;
|
||||||
|
#endif
|
||||||
|
float4 textures : TEXCOORD5;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used by Unity internally to handle Texture Tiling and Offset.
|
||||||
|
float4 _FaceTex_ST;
|
||||||
|
float4 _OutlineTex_ST;
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
pixel_t output;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(pixel_t, output);
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
UNITY_TRANSFER_INSTANCE_ID(input,output);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||||
|
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.position;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
|
scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1);
|
||||||
|
if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
float bias =(.5 - weight) + (.5 / scale);
|
||||||
|
|
||||||
|
float alphaClip = (1.0 - _OutlineWidth*_ScaleRatioA - _OutlineSoftness*_ScaleRatioA);
|
||||||
|
|
||||||
|
#if GLOW_ON
|
||||||
|
alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float4 underlayColor = _UnderlayColor;
|
||||||
|
underlayColor.rgb *= underlayColor.a;
|
||||||
|
|
||||||
|
float bScale = scale;
|
||||||
|
bScale /= 1 + ((_UnderlaySoftness*_ScaleRatioC) * bScale);
|
||||||
|
float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale);
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 bOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||||
|
|
||||||
|
// Support for texture tiling and offset
|
||||||
|
float2 textureUV = UnpackUV(input.texcoord1.x);
|
||||||
|
float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex);
|
||||||
|
float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex);
|
||||||
|
|
||||||
|
|
||||||
|
output.position = vPosition;
|
||||||
|
output.color = input.color;
|
||||||
|
output.atlas = input.texcoord0;
|
||||||
|
output.param = float4(alphaClip, scale, bias, weight);
|
||||||
|
output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz);
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
output.texcoord2 = float4(input.texcoord0 + bOffset, bScale, bBias);
|
||||||
|
output.underlayColor = underlayColor;
|
||||||
|
#endif
|
||||||
|
output.textures = float4(faceUV, outlineUV);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
|
||||||
|
float c = tex2D(_MainTex, input.atlas).a;
|
||||||
|
|
||||||
|
#ifndef UNDERLAY_ON
|
||||||
|
clip(c - input.param.x);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float scale = input.param.y;
|
||||||
|
float bias = input.param.z;
|
||||||
|
float weight = input.param.w;
|
||||||
|
float sd = (bias - c) * scale;
|
||||||
|
|
||||||
|
float outline = (_OutlineWidth * _ScaleRatioA) * scale;
|
||||||
|
float softness = (_OutlineSoftness * _ScaleRatioA) * scale;
|
||||||
|
|
||||||
|
half4 faceColor = _FaceColor;
|
||||||
|
half4 outlineColor = _OutlineColor;
|
||||||
|
|
||||||
|
faceColor.rgb *= input.color.rgb;
|
||||||
|
|
||||||
|
faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y);
|
||||||
|
outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y);
|
||||||
|
|
||||||
|
faceColor = GetColor(sd, faceColor, outlineColor, outline, softness);
|
||||||
|
|
||||||
|
#if BEVEL_ON
|
||||||
|
float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0);
|
||||||
|
float3 n = GetSurfaceNormal(input.atlas, weight, dxy);
|
||||||
|
|
||||||
|
float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz;
|
||||||
|
bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5));
|
||||||
|
n = normalize(n- bump);
|
||||||
|
|
||||||
|
float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0));
|
||||||
|
|
||||||
|
float3 col = GetSpecular(n, light);
|
||||||
|
faceColor.rgb += col*faceColor.a;
|
||||||
|
faceColor.rgb *= 1-(dot(n, light)*_Diffuse);
|
||||||
|
faceColor.rgb *= lerp(_Ambient, 1, n.z*n.z);
|
||||||
|
|
||||||
|
fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n));
|
||||||
|
faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z;
|
||||||
|
faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z;
|
||||||
|
faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GLOW_ON
|
||||||
|
float4 glowColor = GetGlowColor(sd, scale);
|
||||||
|
faceColor.rgb += glowColor.rgb * glowColor.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
||||||
|
faceColor *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(faceColor.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return faceColor * input.color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Fallback "TextMeshPro/Mobile/Distance Field"
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dd89cf5b9246416f84610a006f916af7
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,310 @@
|
||||||
|
Shader "TextMeshPro/Distance Field SSD" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_FaceTex ("Face Texture", 2D) = "white" {}
|
||||||
|
_FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineTex ("Outline Texture", 2D) = "white" {}
|
||||||
|
_OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0, 1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_Bevel ("Bevel", Range(0,1)) = 0.5
|
||||||
|
_BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0
|
||||||
|
_BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0
|
||||||
|
_BevelClamp ("Bevel Clamp", Range(0,1)) = 0
|
||||||
|
_BevelRoundness ("Bevel Roundness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416
|
||||||
|
[HDR]_SpecularColor ("Specular", Color) = (1,1,1,1)
|
||||||
|
_SpecularPower ("Specular", Range(0,4)) = 2.0
|
||||||
|
_Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10
|
||||||
|
_Diffuse ("Diffuse", Range(0,1)) = 0.5
|
||||||
|
_Ambient ("Ambient", Range(1,0)) = 0.5
|
||||||
|
|
||||||
|
_BumpMap ("Normal map", 2D) = "bump" {}
|
||||||
|
_BumpOutline ("Bump Outline", Range(0,1)) = 0
|
||||||
|
_BumpFace ("Bump Face", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1)
|
||||||
|
_ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1)
|
||||||
|
_Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ }
|
||||||
|
_EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5)
|
||||||
|
_GlowOffset ("Offset", Range(-1,1)) = 0
|
||||||
|
_GlowInner ("Inner", Range(0,1)) = 0.05
|
||||||
|
_GlowOuter ("Outer", Range(0,1)) = 0.05
|
||||||
|
_GlowPower ("Falloff", Range(1, 0)) = 0.75
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = 0.5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5.0
|
||||||
|
_ScaleX ("Scale X", float) = 1.0
|
||||||
|
_ScaleY ("Scale Y", float) = 1.0
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767)
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue" = "Transparent"
|
||||||
|
"IgnoreProjector" = "True"
|
||||||
|
"RenderType" = "Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref[_Stencil]
|
||||||
|
Comp[_StencilComp]
|
||||||
|
Pass[_StencilOp]
|
||||||
|
ReadMask[_StencilReadMask]
|
||||||
|
WriteMask[_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull[_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest[unity_GUIZTestMode]
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask[_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma target 3.0
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ BEVEL_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
#pragma shader_feature __ GLOW_ON
|
||||||
|
#pragma shader_feature __ FORCE_LINEAR
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
#include "TMPro.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
float4 position : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
float4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
float4 color : COLOR;
|
||||||
|
float2 atlas : TEXCOORD0;
|
||||||
|
float weight : TEXCOORD1;
|
||||||
|
float2 mask : TEXCOORD2; // Position in object space(xy)
|
||||||
|
float3 viewDir : TEXCOORD3;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float2 texcoord2 : TEXCOORD4;
|
||||||
|
float4 underlayColor : COLOR1;
|
||||||
|
#endif
|
||||||
|
float4 textures : TEXCOORD5;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used by Unity internally to handle Texture Tiling and Offset.
|
||||||
|
float4 _FaceTex_ST;
|
||||||
|
float4 _OutlineTex_ST;
|
||||||
|
|
||||||
|
float4 SRGBToLinear(float4 rgba) {
|
||||||
|
return float4(lerp(rgba.rgb / 12.92f, pow((rgba.rgb + 0.055f) / 1.055f, 2.4f), step(0.04045f, rgba.rgb)), rgba.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
pixel_t output;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(pixel_t, output);
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
UNITY_TRANSFER_INSTANCE_ID(input,output);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||||
|
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.position;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float4 underlayColor = _UnderlayColor;
|
||||||
|
underlayColor.rgb *= underlayColor.a;
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 bOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
|
||||||
|
// Support for texture tiling and offset
|
||||||
|
float2 textureUV = UnpackUV(input.texcoord1.x);
|
||||||
|
float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex);
|
||||||
|
float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex);
|
||||||
|
|
||||||
|
float4 color = input.color;
|
||||||
|
#if (FORCE_LINEAR && !UNITY_COLORSPACE_GAMMA)
|
||||||
|
color = SRGBToLinear(input.color);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
output.position = vPosition;
|
||||||
|
output.color = color;
|
||||||
|
output.atlas = input.texcoord0;
|
||||||
|
output.weight = weight;
|
||||||
|
output.mask = half2(vert.xy * 2 - clampedRect.xy - clampedRect.zw);
|
||||||
|
output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz);
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
output.texcoord2 = input.texcoord0 + bOffset;
|
||||||
|
output.underlayColor = underlayColor;
|
||||||
|
#endif
|
||||||
|
output.textures = float4(faceUV, outlineUV);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
|
||||||
|
float c = tex2D(_MainTex, input.atlas).a;
|
||||||
|
|
||||||
|
float2 pixelSize = float2(ddx(input.atlas.y), ddy(input.atlas.y));
|
||||||
|
pixelSize *= _TextureWidth * .75;
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize)) * _GradientScale * (_Sharpness + 1);
|
||||||
|
|
||||||
|
float weight = input.weight;
|
||||||
|
float bias = (.5 - weight) + (.5 / scale);
|
||||||
|
float sd = (bias - c) * scale;
|
||||||
|
|
||||||
|
float outline = (_OutlineWidth * _ScaleRatioA) * scale;
|
||||||
|
float softness = (_OutlineSoftness * _ScaleRatioA) * scale;
|
||||||
|
|
||||||
|
half4 faceColor = _FaceColor;
|
||||||
|
half4 outlineColor = _OutlineColor;
|
||||||
|
|
||||||
|
faceColor.rgb *= input.color.rgb;
|
||||||
|
|
||||||
|
faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y);
|
||||||
|
outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y);
|
||||||
|
|
||||||
|
faceColor = GetColor(sd, faceColor, outlineColor, outline, softness);
|
||||||
|
|
||||||
|
#if BEVEL_ON
|
||||||
|
float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0);
|
||||||
|
float3 n = GetSurfaceNormal(input.atlas, weight, dxy);
|
||||||
|
|
||||||
|
float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz;
|
||||||
|
bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5));
|
||||||
|
n = normalize(n - bump);
|
||||||
|
|
||||||
|
float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0));
|
||||||
|
|
||||||
|
float3 col = GetSpecular(n, light);
|
||||||
|
faceColor.rgb += col * faceColor.a;
|
||||||
|
faceColor.rgb *= 1 - (dot(n, light) * _Diffuse);
|
||||||
|
faceColor.rgb *= lerp(_Ambient, 1, n.z * n.z);
|
||||||
|
|
||||||
|
fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n));
|
||||||
|
faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float bScale = scale;
|
||||||
|
bScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * bScale);
|
||||||
|
float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
float d = tex2D(_MainTex, input.texcoord2.xy).a * bScale;
|
||||||
|
faceColor += input.underlayColor * saturate(d - bBias) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
float d = tex2D(_MainTex, input.texcoord2.xy).a * bScale;
|
||||||
|
faceColor += input.underlayColor * (1 - saturate(d - bBias)) * saturate(1 - sd) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GLOW_ON
|
||||||
|
float4 glowColor = GetGlowColor(sd, scale);
|
||||||
|
faceColor.rgb += glowColor.rgb * glowColor.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
float2 maskZW = 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + (1 / scale));
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * maskZW);
|
||||||
|
faceColor *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(faceColor.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return faceColor * input.color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Fallback "TextMeshPro/Mobile/Distance Field"
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 14eb328de4b8eb245bb7cea29e4ac00b
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,247 @@
|
||||||
|
// Simplified SDF shader:
|
||||||
|
// - No Shading Option (bevel / bump / env map)
|
||||||
|
// - No Glow Option
|
||||||
|
// - Softness is applied on both side of the outline
|
||||||
|
|
||||||
|
Shader "TextMeshPro/Mobile/Distance Field - Masking" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0,1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = .5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5
|
||||||
|
_ScaleX ("Scale X", float) = 1
|
||||||
|
_ScaleY ("Scale Y", float) = 1
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
_MaskTex ("Mask Texture", 2D) = "white" {}
|
||||||
|
_MaskInverse ("Inverse", float) = 0
|
||||||
|
_MaskEdgeColor ("Edge Color", Color) = (1,1,1,1)
|
||||||
|
_MaskEdgeSoftness ("Edge Softness", Range(0, 1)) = 0.01
|
||||||
|
_MaskWipeControl ("Wipe Position", Range(0, 1)) = 0.5
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue"="Transparent"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ OUTLINE_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 faceColor : COLOR;
|
||||||
|
fixed4 outlineColor : COLOR1;
|
||||||
|
float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV
|
||||||
|
half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w)
|
||||||
|
half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw)
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved
|
||||||
|
half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
float _MaskWipeControl;
|
||||||
|
float _MaskEdgeSoftness;
|
||||||
|
fixed4 _MaskEdgeColor;
|
||||||
|
bool _MaskInverse;
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||||
|
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
|
scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1);
|
||||||
|
if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
float layerScale = scale;
|
||||||
|
|
||||||
|
scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale);
|
||||||
|
float bias = (0.5 - weight) * scale - 0.5;
|
||||||
|
float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale;
|
||||||
|
|
||||||
|
float opacity = input.color.a;
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
opacity = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor;
|
||||||
|
faceColor.rgb *= faceColor.a;
|
||||||
|
|
||||||
|
fixed4 outlineColor = _OutlineColor;
|
||||||
|
outlineColor.a *= opacity;
|
||||||
|
outlineColor.rgb *= outlineColor.a;
|
||||||
|
outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2))));
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
|
||||||
|
layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale);
|
||||||
|
float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale);
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 layerOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||||
|
|
||||||
|
// Structure for pixel shader
|
||||||
|
pixel_t output = {
|
||||||
|
vPosition,
|
||||||
|
faceColor,
|
||||||
|
outlineColor,
|
||||||
|
float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y),
|
||||||
|
half4(scale, bias - outline, bias + outline, bias),
|
||||||
|
half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)),
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
float4(input.texcoord0 + layerOffset, input.color.a, 0),
|
||||||
|
half2(layerScale, layerBias),
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PIXEL SHADER
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x;
|
||||||
|
half4 c = input.faceColor * saturate(d - input.param.w);
|
||||||
|
|
||||||
|
#ifdef OUTLINE_ON
|
||||||
|
c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z));
|
||||||
|
c *= saturate(d - input.param.y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
half sd = saturate(d - input.param.z);
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
//#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
||||||
|
c *= m.x * m.y;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
float a = abs(_MaskInverse - tex2D(_MaskTex, input.texcoord0.zw).a);
|
||||||
|
float t = a + (1 - _MaskWipeControl) * _MaskEdgeSoftness - _MaskWipeControl;
|
||||||
|
a = saturate(t / _MaskEdgeSoftness);
|
||||||
|
c.rgb = lerp(_MaskEdgeColor.rgb*c.a, c.rgb, a);
|
||||||
|
c *= a;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
c *= input.texcoord1.z;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(c.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bc1ede39bf3643ee8e493720e4259791
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,240 @@
|
||||||
|
// Simplified SDF shader:
|
||||||
|
// - No Shading Option (bevel / bump / env map)
|
||||||
|
// - No Glow Option
|
||||||
|
// - Softness is applied on both side of the outline
|
||||||
|
|
||||||
|
Shader "TextMeshPro/Mobile/Distance Field Overlay" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0,1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = .5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5
|
||||||
|
_ScaleX ("Scale X", float) = 1
|
||||||
|
_ScaleY ("Scale Y", float) = 1
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue"="Overlay"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest Always
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ OUTLINE_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 faceColor : COLOR;
|
||||||
|
fixed4 outlineColor : COLOR1;
|
||||||
|
float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV
|
||||||
|
half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w)
|
||||||
|
half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw)
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved
|
||||||
|
half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
pixel_t output;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(pixel_t, output);
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
UNITY_TRANSFER_INSTANCE_ID(input, output);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||||
|
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||||
|
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
|
scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1);
|
||||||
|
if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
float layerScale = scale;
|
||||||
|
|
||||||
|
scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale);
|
||||||
|
float bias = (0.5 - weight) * scale - 0.5;
|
||||||
|
float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale;
|
||||||
|
|
||||||
|
float opacity = input.color.a;
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
opacity = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor;
|
||||||
|
faceColor.rgb *= faceColor.a;
|
||||||
|
|
||||||
|
fixed4 outlineColor = _OutlineColor;
|
||||||
|
outlineColor.a *= opacity;
|
||||||
|
outlineColor.rgb *= outlineColor.a;
|
||||||
|
outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2))));
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale);
|
||||||
|
float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale);
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 layerOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||||
|
|
||||||
|
// Populate structure for pixel shader
|
||||||
|
output.vertex = vPosition;
|
||||||
|
output.faceColor = faceColor;
|
||||||
|
output.outlineColor = outlineColor;
|
||||||
|
output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y);
|
||||||
|
output.param = half4(scale, bias - outline, bias + outline, bias);
|
||||||
|
output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0);
|
||||||
|
output.underlayParam = half2(layerScale, layerBias);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PIXEL SHADER
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
|
||||||
|
half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x;
|
||||||
|
half4 c = input.faceColor * saturate(d - input.param.w);
|
||||||
|
|
||||||
|
#ifdef OUTLINE_ON
|
||||||
|
c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z));
|
||||||
|
c *= saturate(d - input.param.y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
half sd = saturate(d - input.param.z);
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
||||||
|
c *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
c *= input.texcoord1.z;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(c.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a02a7d8c237544f1962732b55a9aebf1
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Simplified SDF shader:
|
||||||
|
// - No Shading Option (bevel / bump / env map)
|
||||||
|
// - No Glow Option
|
||||||
|
// - Softness is applied on both side of the outline
|
||||||
|
|
||||||
|
Shader "TextMeshPro/Mobile/Distance Field SSD" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0,1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = .5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5
|
||||||
|
_ScaleX ("Scale X", float) = 1
|
||||||
|
_ScaleY ("Scale Y", float) = 1
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
_MaskTex ("Mask Texture", 2D) = "white" {}
|
||||||
|
_MaskInverse ("Inverse", float) = 0
|
||||||
|
_MaskEdgeColor ("Edge Color", Color) = (1,1,1,1)
|
||||||
|
_MaskEdgeSoftness ("Edge Softness", Range(0, 1)) = 0.01
|
||||||
|
_MaskWipeControl ("Wipe Position", Range(0, 1)) = 0.5
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags {
|
||||||
|
"Queue"="Transparent"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ OUTLINE_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
|
||||||
|
#include "TMPro_Mobile.cginc"
|
||||||
|
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c8d12adcee749c344b8117cf7c7eb912
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,240 @@
|
||||||
|
// Simplified SDF shader:
|
||||||
|
// - No Shading Option (bevel / bump / env map)
|
||||||
|
// - No Glow Option
|
||||||
|
// - Softness is applied on both side of the outline
|
||||||
|
|
||||||
|
Shader "TextMeshPro/Mobile/Distance Field" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0,1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = .5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5
|
||||||
|
_ScaleX ("Scale X", float) = 1
|
||||||
|
_ScaleY ("Scale Y", float) = 1
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue"="Transparent"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ OUTLINE_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 faceColor : COLOR;
|
||||||
|
fixed4 outlineColor : COLOR1;
|
||||||
|
float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV
|
||||||
|
half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w)
|
||||||
|
half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw)
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved
|
||||||
|
half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
pixel_t output;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(pixel_t, output);
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
UNITY_TRANSFER_INSTANCE_ID(input, output);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||||
|
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||||
|
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
|
scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1);
|
||||||
|
if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
float layerScale = scale;
|
||||||
|
|
||||||
|
scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale);
|
||||||
|
float bias = (0.5 - weight) * scale - 0.5;
|
||||||
|
float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale;
|
||||||
|
|
||||||
|
float opacity = input.color.a;
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
opacity = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor;
|
||||||
|
faceColor.rgb *= faceColor.a;
|
||||||
|
|
||||||
|
fixed4 outlineColor = _OutlineColor;
|
||||||
|
outlineColor.a *= opacity;
|
||||||
|
outlineColor.rgb *= outlineColor.a;
|
||||||
|
outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2))));
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale);
|
||||||
|
float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale);
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 layerOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||||
|
|
||||||
|
// Populate structure for pixel shader
|
||||||
|
output.vertex = vPosition;
|
||||||
|
output.faceColor = faceColor;
|
||||||
|
output.outlineColor = outlineColor;
|
||||||
|
output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y);
|
||||||
|
output.param = half4(scale, bias - outline, bias + outline, bias);
|
||||||
|
output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0);
|
||||||
|
output.underlayParam = half2(layerScale, layerBias);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PIXEL SHADER
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
|
||||||
|
half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x;
|
||||||
|
half4 c = input.faceColor * saturate(d - input.param.w);
|
||||||
|
|
||||||
|
#ifdef OUTLINE_ON
|
||||||
|
c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z));
|
||||||
|
c *= saturate(d - input.param.y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
half sd = saturate(d - input.param.z);
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
||||||
|
c *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
c *= input.texcoord1.z;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(c.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue