finish(maybe...)

This commit is contained in:
SepComet 2026-04-14 21:30:38 +08:00
parent 785e92ec8b
commit 2c61ef07ff
172 changed files with 202485 additions and 68 deletions

167907
Assets/MainTMPFont.asset Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6d323088abea7f842969756cfc4a7c85
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,3 @@
{
"name": "DOTween.Modules"
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b1a18c052caf77a44a8bbb8a5e4acd11
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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: []

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a87e3a74be955cd489afbc0a2017918c
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ef8d46c253ef36e4ab74f4106405ecbf
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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

13616
Assets/Scenes/Main.unity Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 85bc7cc748291a344ba0188b5c2c378b
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
namespace VMdemo.Core
{
public enum AddressGenerationMode
{
RandomUniform = 0,
SequentialArrayLoop = 1
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7d91aaaf0f71455ba5f1707f02b3f7b7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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))
{ {

View File

@ -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;

View File

@ -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;
}
} }
} }

View File

@ -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;
} }
} }
} }

View File

@ -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);
}
} }
} }

View File

@ -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);

View File

@ -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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 93f3af00cf194cf4bf98f5df86f86ffc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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());
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 40ec73de0f6f4717a043fc64ff3c3b13
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9b68de53ac3e4c49a27b25bf5f91821b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 58e1bc0dfbbf46b7b64e6d6d74fd5f24
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 71f3b95f31a74ef98ffd50e2f6435c20
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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, "TLBN/A");
SetText(pageTableText, "页表N/A");
SetText(fifoText, "FIFON/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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68f3ab1453614176a0f66589d29a55dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c65bcc42d5bf440ca80a93cc5a2f1fc1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5f6f28922eb241649a4d14b8b6cc6bf7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac9c8cdc89fb6c14bbd38774897a7e26
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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=falsePFN={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>";
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d62c9fa502173a542a04294863667636
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f36cd8ac00908594fb49c431d072c1bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d594815f47f84f758ecf3e198de8d8de
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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()
};
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61f58553676e41d68ef5818d93ba09dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
}

View File

@ -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,

View File

@ -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));
} }
} }
} }

View File

@ -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()
{ {

View File

@ -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,

View File

@ -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,

8
Assets/TextMesh Pro.meta Normal file
View File

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

View File

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

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1b8d251f9af63b746bf2f7ffe00ebb9b
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -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.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6e59c59b81ab47f9b6ec5781fa725d2c
timeCreated: 1484171296
licenseType: Pro
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -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:

View File

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

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 731f1baa9d144a9897cb1d341c2092b8
folderAsset: yes
timeCreated: 1442040525
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e73a58f6e2794ae7b1b7e50b7fb811b0
timeCreated: 1484172806
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2e498d1c8094910479dc3e1b768306a4
timeCreated: 1484171803
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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}

View File

@ -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

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8f586378b4e144a9851e7b34d9b748ee
timeCreated: 1484171803
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1 @@
)]}〕〉》」』】〙〗〟’”⦆»ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻‐゠–〜?!‼⁇⁈⁉・、%,.:;。!?]):;=}¢°"†‡℃〆%,.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fade42e8bc714b018fac513c043d323b
timeCreated: 1425440388
licenseType: Store
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1 @@
([{〔〈《「『【〘〖〝‘“⦅«$—…‥〳〴〵\{£¥"々〇$¥₩ #

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d82c1b31c7e74239bff1220585707d2b
timeCreated: 1425440388
licenseType: Store
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 512a49d95c0c4332bdd98131869c23c9
folderAsset: yes
timeCreated: 1441876896
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c41005c129ba4d66911b75229fd70b45
timeCreated: 1480316912
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 4aecb92fff08436c8303b10eab8da368
folderAsset: yes
timeCreated: 1441876950
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f952c082cb03451daed3ee968ac6c63e
timeCreated: 1432805430
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3f5b5dff67a942289a9defa416b206f3
timeCreated: 1436653997
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -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"
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 48bb5f55d8670e349b6e614913f9d910
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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"
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 1e3b057af24249748ff873be7fafee47
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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"
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 128e987d567d4e2c824d754223b3f3b0
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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"
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: dd89cf5b9246416f84610a006f916af7
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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"
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 14eb328de4b8eb245bb7cea29e4ac00b
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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"
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: bc1ede39bf3643ee8e493720e4259791
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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"
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a02a7d8c237544f1962732b55a9aebf1
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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"
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: c8d12adcee749c344b8117cf7c7eb912
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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