diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..79069b1 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: gorialis +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/assets/sample.jpg b/.github/assets/sample.jpg new file mode 100644 index 0000000..70b5052 Binary files /dev/null and b/.github/assets/sample.jpg differ diff --git a/.github/assets/set_instance_1.png b/.github/assets/set_instance_1.png new file mode 100644 index 0000000..d143ce8 Binary files /dev/null and b/.github/assets/set_instance_1.png differ diff --git a/.github/assets/set_instance_2.png b/.github/assets/set_instance_2.png new file mode 100644 index 0000000..48cc811 Binary files /dev/null and b/.github/assets/set_instance_2.png differ diff --git a/.github/assets/udon-qr.svg b/.github/assets/udon-qr.svg new file mode 100644 index 0000000..65226f1 --- /dev/null +++ b/.github/assets/udon-qr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Assets/UdonQR.meta b/Assets/UdonQR.meta new file mode 100644 index 0000000..8bfa504 --- /dev/null +++ b/Assets/UdonQR.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: adfa73af47cad984db0be1362099410b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UdonQR/Prefabs.meta b/Assets/UdonQR/Prefabs.meta new file mode 100644 index 0000000..b6c2d9c --- /dev/null +++ b/Assets/UdonQR/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 409ef9c359182874aaba03d58c542699 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UdonQR/Prefabs/QRCanvas.prefab b/Assets/UdonQR/Prefabs/QRCanvas.prefab new file mode 100644 index 0000000..2268828 --- /dev/null +++ b/Assets/UdonQR/Prefabs/QRCanvas.prefab @@ -0,0 +1,204 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4846963176756753657 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4846963176756753602} + - component: {fileID: 4846963176756753661} + - component: {fileID: 4846963176756753660} + - component: {fileID: 4846963176756753663} + - component: {fileID: 4846963176756753662} + m_Layer: 0 + m_Name: QRCanvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4846963176756753602 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4846963176756753657} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.0025, y: 0.0025, z: 0.0025} + m_Children: + - {fileID: 4846963176943915906} + m_Father: {fileID: 0} + m_RootOrder: 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: 500, y: 500} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!223 &4846963176756753661 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4846963176756753657} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 2 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!114 &4846963176756753660 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4846963176756753657} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &4846963176756753663 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4846963176756753657} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &4846963176756753662 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4846963176756753657} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 45115577ef41a5b4ca741ed302693907, type: 3} + m_Name: + m_EditorClassIdentifier: + interactTextPlacement: {fileID: 0} + interactText: Use + interactTextGO: {fileID: 0} + proximity: 2 + SynchronizePosition: 0 + AllowCollisionOwnershipTransfer: 0 + serializedProgramAsset: {fileID: 11400000, guid: 38340f97df821b7448d6251a0ae8bc1c, + type: 2} + programSource: {fileID: 11400000, guid: e54052152dd448647b48087a5cc71c13, type: 2} + serializedPublicVariablesBytesString: Ai8AAAAAATIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAFQAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAAAAAAYBAAAAAAAAACcBBAAAAHQAeQBwAGUAAWgAAABTAHkAcwB0AGUAbQAuAEMAbwBsAGwAZQBjAHQAaQBvAG4AcwAuAEcAZQBuAGUAcgBpAGMALgBMAGkAcwB0AGAAMQBbAFsAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBJAG4AdABlAHIAZgBhAGMAZQBzAC4ASQBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AXQBdACwAIABtAHMAYwBvAHIAbABpAGIAAQEJAAAAVgBhAHIAaQBhAGIAbABlAHMALwEAAAABaAAAAFMAeQBzAHQAZQBtAC4AQwBvAGwAbABlAGMAdABpAG8AbgBzAC4ARwBlAG4AZQByAGkAYwAuAEwAaQBzAHQAYAAxAFsAWwBWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAEkAbgB0AGUAcgBmAGEAYwBlAHMALgBJAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgBdAF0ALAAgAG0AcwBjAG8AcgBsAGkAYgABAAAABgMAAAAAAAAAAi8CAAAAAVYAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAVQBuAGkAdAB5AEUAbgBnAGkAbgBlAC4AVQBJAC4AVABlAHgAdAAsACAAVQBuAGkAdAB5AEUAbgBnAGkAbgBlAC4AVQBJAF0AXQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAgAAAAYCAAAAAAAAACcBBAAAAHQAeQBwAGUAARcAAABTAHkAcwB0AGUAbQAuAFMAdAByAGkAbgBnACwAIABtAHMAYwBvAHIAbABpAGIAJwEKAAAAUwB5AG0AYgBvAGwATgBhAG0AZQABDQAAAF8AYwBhAG4AdgBhAHMAVABhAHIAZwBlAHQAJwEEAAAAdAB5AHAAZQABIwAAAFUAbgBpAHQAeQBFAG4AZwBpAG4AZQAuAFUASQAuAFQAZQB4AHQALAAgAFUAbgBpAHQAeQBFAG4AZwBpAG4AZQAuAFUASQALAQUAAABWAGEAbAB1AGUAAAAAAAcFAi8DAAAAAUkAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAUwB5AHMAdABlAG0ALgBJAG4AdAAzADIALAAgAG0AcwBjAG8AcgBsAGkAYgBdAF0ALAAgAFYAUgBDAC4AVQBkAG8AbgAuAEMAbwBtAG0AbwBuAAMAAAAGAgAAAAAAAAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAHQAcgBpAG4AZwAsACAAbQBzAGMAbwByAGwAaQBiACcBCgAAAFMAeQBtAGIAbwBsAE4AYQBtAGUAAQ8AAABlAHIAcgBvAHIAQwBvAHIAcgBlAGMAdABpAG8AbgAnAQQAAAB0AHkAcABlAAEWAAAAUwB5AHMAdABlAG0ALgBJAG4AdAAzADIALAAgAG0AcwBjAG8AcgBsAGkAYgAXAQUAAABWAGEAbAB1AGUAAAAAAAcFAjADAAAABAAAAAYCAAAAAAAAACcBBAAAAHQAeQBwAGUAARcAAABTAHkAcwB0AGUAbQAuAFMAdAByAGkAbgBnACwAIABtAHMAYwBvAHIAbABpAGIAJwEKAAAAUwB5AG0AYgBvAGwATgBhAG0AZQABCwAAAG0AYQBzAGsAUABhAHQAdABlAHIAbgAnAQQAAAB0AHkAcABlAAEWAAAAUwB5AHMAdABlAG0ALgBJAG4AdAAzADIALAAgAG0AcwBjAG8AcgBsAGkAYgAXAQUAAABWAGEAbAB1AGUAAQAAAAcFBwUHBQ== + publicVariablesUnityEngineObjects: + - {fileID: 4846963176943915907} + publicVariablesSerializationDataFormat: 0 +--- !u!1 &4846963176943915965 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4846963176943915906} + - component: {fileID: 4846963176943915904} + - component: {fileID: 4846963176943915907} + m_Layer: 0 + m_Name: QRText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4846963176943915906 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4846963176943915965} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 0.6, z: 1} + m_Children: [] + m_Father: {fileID: 4846963176756753602} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 500, y: 768} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4846963176943915904 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4846963176943915965} + m_CullTransparentMesh: 0 +--- !u!114 &4846963176943915907 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4846963176943915965} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 50 + m_FontStyle: 0 + m_BestFit: 1 + m_MinSize: 0 + m_MaxSize: 200 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2588\u2588\u2591\u2591\u2591\u2588\u2588\u2588\u2588\u2588\u2588\u2588\r\n\u2588\u2591\u2591\u2591\u2591\u2591\u2588\u2591\u2591\u2588\u2591\u2591\u2591\u2591\u2588\u2591\u2591\u2591\u2591\u2591\u2588\r\n\u2588\u2591\u2588\u2588\u2588\u2591\u2588\u2591\u2588\u2588\u2588\u2588\u2591\u2591\u2588\u2591\u2588\u2588\u2588\u2591\u2588\r\n\u2588\u2591\u2588\u2588\u2588\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2591\u2591\u2588\u2591\u2588\u2588\u2588\u2591\u2588\r\n\u2588\u2591\u2588\u2588\u2588\u2591\u2588\u2591\u2588\u2591\u2588\u2588\u2588\u2591\u2588\u2591\u2588\u2588\u2588\u2591\u2588\r\n\u2588\u2591\u2591\u2591\u2591\u2591\u2588\u2591\u2588\u2591\u2591\u2591\u2588\u2591\u2588\u2591\u2591\u2591\u2591\u2591\u2588\r\n\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2588\u2588\u2588\u2588\u2588\u2588\u2588\r\n\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2588\u2591\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\r\n\u2588\u2591\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2588\u2588\u2591\u2588\u2591\u2588\u2588\u2588\u2588\u2588\u2591\u2591\r\n\u2588\u2591\u2591\u2588\u2591\u2588\u2591\u2588\u2588\u2591\u2591\u2591\u2588\u2591\u2591\u2588\u2591\u2591\u2588\u2591\u2588\r\n\u2588\u2588\u2588\u2591\u2588\u2591\u2588\u2591\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2591\u2588\u2588\u2588\u2588\u2591\r\n\u2591\u2591\u2591\u2591\u2588\u2588\u2591\u2591\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2588\u2588\u2588\u2588\u2588\u2588\r\n\u2591\u2588\u2588\u2591\u2588\u2588\u2588\u2591\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2591\u2588\u2591\u2591\u2591\u2591\r\n\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2588\u2591\u2588\u2591\r\n\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2588\u2591\u2591\u2588\u2591\u2588\u2588\u2591\u2588\u2588\u2588\u2591\r\n\u2588\u2591\u2591\u2591\u2591\u2591\u2588\u2591\u2588\u2591\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2588\u2588\u2591\u2588\r\n\u2588\u2591\u2588\u2588\u2588\u2591\u2588\u2591\u2588\u2588\u2588\u2591\u2588\u2591\u2591\u2591\u2591\u2588\u2591\u2588\u2591\r\n\u2588\u2591\u2588\u2588\u2588\u2591\u2588\u2591\u2588\u2588\u2591\u2591\u2588\u2591\u2591\u2588\u2588\u2591\u2588\u2591\u2591\r\n\u2588\u2591\u2588\u2588\u2588\u2591\u2588\u2591\u2588\u2591\u2591\u2588\u2591\u2588\u2591\u2591\u2591\u2591\u2588\u2591\u2591\r\n\u2588\u2591\u2591\u2591\u2591\u2591\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2588\u2591\u2588\u2588\u2591\u2591\r\n\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2588\u2588\u2591\u2588\u2591\u2588\u2591\u2591\u2588\u2591\u2591\u2588\u2591" diff --git a/Assets/UdonQR/Prefabs/QRCanvas.prefab.meta b/Assets/UdonQR/Prefabs/QRCanvas.prefab.meta new file mode 100644 index 0000000..fba559a --- /dev/null +++ b/Assets/UdonQR/Prefabs/QRCanvas.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4c1a52ec92ec82a46aa257080dde8865 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UdonQR/Prefabs/UdonQR.prefab b/Assets/UdonQR/Prefabs/UdonQR.prefab new file mode 100644 index 0000000..dc89b1d --- /dev/null +++ b/Assets/UdonQR/Prefabs/UdonQR.prefab @@ -0,0 +1,57 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &9018801747113834372 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9018801747113834374} + - component: {fileID: 9018801747113834373} + m_Layer: 0 + m_Name: UdonQR + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &9018801747113834374 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9018801747113834372} + 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_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &9018801747113834373 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9018801747113834372} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 45115577ef41a5b4ca741ed302693907, type: 3} + m_Name: + m_EditorClassIdentifier: + interactTextPlacement: {fileID: 0} + interactText: Use + interactTextGO: {fileID: 0} + proximity: 2 + SynchronizePosition: 0 + AllowCollisionOwnershipTransfer: 0 + serializedProgramAsset: {fileID: 11400000, guid: c630def4bff0c964b90f859edf60ba10, + type: 2} + programSource: {fileID: 11400000, guid: 720399303af7da743a56c91b0728f8e1, type: 2} + serializedPublicVariablesBytesString: Ai8AAAAAATIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAFQAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAAAAAAYBAAAAAAAAACcBBAAAAHQAeQBwAGUAAWgAAABTAHkAcwB0AGUAbQAuAEMAbwBsAGwAZQBjAHQAaQBvAG4AcwAuAEcAZQBuAGUAcgBpAGMALgBMAGkAcwB0AGAAMQBbAFsAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBJAG4AdABlAHIAZgBhAGMAZQBzAC4ASQBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AXQBdACwAIABtAHMAYwBvAHIAbABpAGIAAQEJAAAAVgBhAHIAaQBhAGIAbABlAHMALwEAAAABaAAAAFMAeQBzAHQAZQBtAC4AQwBvAGwAbABlAGMAdABpAG8AbgBzAC4ARwBlAG4AZQByAGkAYwAuAEwAaQBzAHQAYAAxAFsAWwBWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAEkAbgB0AGUAcgBmAGEAYwBlAHMALgBJAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgBdAF0ALAAgAG0AcwBjAG8AcgBsAGkAYgABAAAABgQAAAAAAAAAAi8CAAAAAUkAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAUwB5AHMAdABlAG0ALgBJAG4AdAAzADIALAAgAG0AcwBjAG8AcgBsAGkAYgBdAF0ALAAgAFYAUgBDAC4AVQBkAG8AbgAuAEMAbwBtAG0AbwBuAAIAAAAGAgAAAAAAAAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAHQAcgBpAG4AZwAsACAAbQBzAGMAbwByAGwAaQBiACcBCgAAAFMAeQBtAGIAbwBsAE4AYQBtAGUAARIAAABFAFIAUgBPAFIAXwBDAE8AUgBSAEUAQwBUAEkATwBOAF8ATAAnAQQAAAB0AHkAcABlAAEWAAAAUwB5AHMAdABlAG0ALgBJAG4AdAAzADIALAAgAG0AcwBjAG8AcgBsAGkAYgAXAQUAAABWAGEAbAB1AGUAAQAAAAcFAjACAAAAAwAAAAYCAAAAAAAAACcBBAAAAHQAeQBwAGUAARcAAABTAHkAcwB0AGUAbQAuAFMAdAByAGkAbgBnACwAIABtAHMAYwBvAHIAbABpAGIAJwEKAAAAUwB5AG0AYgBvAGwATgBhAG0AZQABEgAAAEUAUgBSAE8AUgBfAEMATwBSAFIARQBDAFQASQBPAE4AXwBNACcBBAAAAHQAeQBwAGUAARYAAABTAHkAcwB0AGUAbQAuAEkAbgB0ADMAMgAsACAAbQBzAGMAbwByAGwAaQBiABcBBQAAAFYAYQBsAHUAZQAAAAAABwUCMAIAAAAEAAAABgIAAAAAAAAAJwEEAAAAdAB5AHAAZQABFwAAAFMAeQBzAHQAZQBtAC4AUwB0AHIAaQBuAGcALAAgAG0AcwBjAG8AcgBsAGkAYgAnAQoAAABTAHkAbQBiAG8AbABOAGEAbQBlAAESAAAARQBSAFIATwBSAF8AQwBPAFIAUgBFAEMAVABJAE8ATgBfAFEAJwEEAAAAdAB5AHAAZQABFgAAAFMAeQBzAHQAZQBtAC4ASQBuAHQAMwAyACwAIABtAHMAYwBvAHIAbABpAGIAFwEFAAAAVgBhAGwAdQBlAAMAAAAHBQIwAgAAAAUAAAAGAgAAAAAAAAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAHQAcgBpAG4AZwAsACAAbQBzAGMAbwByAGwAaQBiACcBCgAAAFMAeQBtAGIAbwBsAE4AYQBtAGUAARIAAABFAFIAUgBPAFIAXwBDAE8AUgBSAEUAQwBUAEkATwBOAF8ASAAnAQQAAAB0AHkAcABlAAEWAAAAUwB5AHMAdABlAG0ALgBJAG4AdAAzADIALAAgAG0AcwBjAG8AcgBsAGkAYgAXAQUAAABWAGEAbAB1AGUAAgAAAAcFBwUHBQ== + publicVariablesUnityEngineObjects: [] + publicVariablesSerializationDataFormat: 0 diff --git a/Assets/UdonQR/Prefabs/UdonQR.prefab.meta b/Assets/UdonQR/Prefabs/UdonQR.prefab.meta new file mode 100644 index 0000000..b89fbda --- /dev/null +++ b/Assets/UdonQR/Prefabs/UdonQR.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 75f1573ff93ddba4e92fa6f25374ce03 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UdonQR/Udon.meta b/Assets/UdonQR/Udon.meta new file mode 100644 index 0000000..44ac592 --- /dev/null +++ b/Assets/UdonQR/Udon.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 15bda6835b9e22445adfee6838cb3701 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UdonQR/Udon/UdonQR.asset b/Assets/UdonQR/Udon/UdonQR.asset new file mode 100644 index 0000000..ad4b2e6 --- /dev/null +++ b/Assets/UdonQR/Udon/UdonQR.asset @@ -0,0 +1,1164 @@ +%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: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3} + m_Name: UdonQR + m_EditorClassIdentifier: + serializedUdonProgramAsset: {fileID: 11400000, guid: c630def4bff0c964b90f859edf60ba10, + type: 2} + udonAssembly: + assemblyError: + sourceCsScript: {fileID: 11500000, guid: 12bea67aa39620741af205f1260869a4, type: 3} + behaviourIDHeapVarName: __refl_const_intnl_udonTypeID + compileErrors: [] + hasInteractEvent: 0 + serializationData: + SerializedFormat: 2 + SerializedBytes: + ReferencedUnityObjects: [] + SerializedBytesString: + Prefab: {fileID: 0} + PrefabModificationsReferencedUnityObjects: [] + PrefabModifications: [] + SerializationNodes: + - Name: fieldDefinitions + Entry: 7 + Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition, + UdonSharp.Editor]], mscorlib + - Name: comparer + Entry: 7 + Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String, + mscorlib]], mscorlib + - Name: + Entry: 8 + Data: + - Name: + Entry: 12 + Data: 19 + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: ERROR_CORRECTION_L + - Name: $v + Entry: 7 + Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 3|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 7 + Data: 4|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Int32, mscorlib + - Name: + Entry: 8 + Data: + - Name: declarationType + Entry: 3 + Data: 257 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: ERROR_CORRECTION_L + - Name: symbolUniqueName + Entry: 1 + Data: ERROR_CORRECTION_L + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 5|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: ERROR_CORRECTION_M + - Name: $v + Entry: 7 + Data: 6|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 7|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 4 + - Name: declarationType + Entry: 3 + Data: 257 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: ERROR_CORRECTION_M + - Name: symbolUniqueName + Entry: 1 + Data: ERROR_CORRECTION_M + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 8|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: ERROR_CORRECTION_Q + - Name: $v + Entry: 7 + Data: 9|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 10|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 4 + - Name: declarationType + Entry: 3 + Data: 257 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: ERROR_CORRECTION_Q + - Name: symbolUniqueName + Entry: 1 + Data: ERROR_CORRECTION_Q + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 11|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: ERROR_CORRECTION_H + - Name: $v + Entry: 7 + Data: 12|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 13|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 4 + - Name: declarationType + Entry: 3 + Data: 257 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: ERROR_CORRECTION_H + - Name: symbolUniqueName + Entry: 1 + Data: ERROR_CORRECTION_H + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 14|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: MODE_NUMBER + - Name: $v + Entry: 7 + Data: 15|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 16|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 4 + - Name: declarationType + Entry: 3 + Data: 257 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: MODE_NUMBER + - Name: symbolUniqueName + Entry: 1 + Data: MODE_NUMBER + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 17|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: MODE_ALPHANUMERIC + - Name: $v + Entry: 7 + Data: 18|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 19|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 4 + - Name: declarationType + Entry: 3 + Data: 257 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: MODE_ALPHANUMERIC + - Name: symbolUniqueName + Entry: 1 + Data: MODE_ALPHANUMERIC + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 20|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: MODE_BYTES + - Name: $v + Entry: 7 + Data: 21|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 22|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 4 + - Name: declarationType + Entry: 3 + Data: 257 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: MODE_BYTES + - Name: symbolUniqueName + Entry: 1 + Data: MODE_BYTES + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 23|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: MODE_KANJI + - Name: $v + Entry: 7 + Data: 24|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 25|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 4 + - Name: declarationType + Entry: 3 + Data: 257 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: MODE_KANJI + - Name: symbolUniqueName + Entry: 1 + Data: MODE_KANJI + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 26|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: ADJUST_PATTERN_POSITIONS + - Name: $v + Entry: 7 + Data: 27|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 28|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 7 + Data: 29|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Int32[][], mscorlib + - Name: + Entry: 8 + Data: + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemObjectArray + - Name: symbolOriginalName + Entry: 1 + Data: ADJUST_PATTERN_POSITIONS + - Name: symbolUniqueName + Entry: 1 + Data: ADJUST_PATTERN_POSITIONS + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 30|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: RS_BLOCKS + - Name: $v + Entry: 7 + Data: 31|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 32|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 29 + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemObjectArray + - Name: symbolOriginalName + Entry: 1 + Data: RS_BLOCKS + - Name: symbolUniqueName + Entry: 1 + Data: RS_BLOCKS + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 33|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: RS_POLYNOMIAL_LUT_KEYS + - Name: $v + Entry: 7 + Data: 34|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 35|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 7 + Data: 36|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Byte[], mscorlib + - Name: + Entry: 8 + Data: + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemByteArray + - Name: symbolOriginalName + Entry: 1 + Data: RS_POLYNOMIAL_LUT_KEYS + - Name: symbolUniqueName + Entry: 1 + Data: RS_POLYNOMIAL_LUT_KEYS + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 37|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: RS_POLYNOMIAL_LUT_VALUES + - Name: $v + Entry: 7 + Data: 38|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 39|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 7 + Data: 40|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Byte[][], mscorlib + - Name: + Entry: 8 + Data: + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemObjectArray + - Name: symbolOriginalName + Entry: 1 + Data: RS_POLYNOMIAL_LUT_VALUES + - Name: symbolUniqueName + Entry: 1 + Data: RS_POLYNOMIAL_LUT_VALUES + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 41|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: BIT_LIMIT_TABLE + - Name: $v + Entry: 7 + Data: 42|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 43|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 29 + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemObjectArray + - Name: symbolOriginalName + Entry: 1 + Data: BIT_LIMIT_TABLE + - Name: symbolUniqueName + Entry: 1 + Data: BIT_LIMIT_TABLE + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 44|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: BCH_G15 + - Name: $v + Entry: 7 + Data: 45|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 46|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 4 + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: BCH_G15 + - Name: symbolUniqueName + Entry: 1 + Data: BCH_G15 + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 47|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: BCH_G18 + - Name: $v + Entry: 7 + Data: 48|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 49|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 4 + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: BCH_G18 + - Name: symbolUniqueName + Entry: 1 + Data: BCH_G18 + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 50|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: BCH_G15_MASK + - Name: $v + Entry: 7 + Data: 51|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 52|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 4 + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: BCH_G15_MASK + - Name: symbolUniqueName + Entry: 1 + Data: BCH_G15_MASK + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 53|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: ALPHANUMERIC_LUT + - Name: $v + Entry: 7 + Data: 54|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 55|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 7 + Data: 56|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.String, mscorlib + - Name: + Entry: 8 + Data: + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemString + - Name: symbolOriginalName + Entry: 1 + Data: ALPHANUMERIC_LUT + - Name: symbolUniqueName + Entry: 1 + Data: ALPHANUMERIC_LUT + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 57|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: EXPONENT_TABLE + - Name: $v + Entry: 7 + Data: 58|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 59|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 36 + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemByteArray + - Name: symbolOriginalName + Entry: 1 + Data: EXPONENT_TABLE + - Name: symbolUniqueName + Entry: 1 + Data: EXPONENT_TABLE + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 60|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: LOGARITHM_TABLE + - Name: $v + Entry: 7 + Data: 61|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 62|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 36 + - Name: declarationType + Entry: 3 + Data: 258 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemByteArray + - Name: symbolOriginalName + Entry: 1 + Data: LOGARITHM_TABLE + - Name: symbolUniqueName + Entry: 1 + Data: LOGARITHM_TABLE + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 63|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: diff --git a/Assets/UdonQR/Udon/UdonQR.asset.meta b/Assets/UdonQR/Udon/UdonQR.asset.meta new file mode 100644 index 0000000..9c2b6c7 --- /dev/null +++ b/Assets/UdonQR/Udon/UdonQR.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 720399303af7da743a56c91b0728f8e1 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UdonQR/Udon/UdonQRCanvasSetter.asset b/Assets/UdonQR/Udon/UdonQRCanvasSetter.asset new file mode 100644 index 0000000..3f41f86 --- /dev/null +++ b/Assets/UdonQR/Udon/UdonQRCanvasSetter.asset @@ -0,0 +1,298 @@ +%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: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3} + m_Name: UdonQRCanvasSetter + m_EditorClassIdentifier: + serializedUdonProgramAsset: {fileID: 11400000, guid: 38340f97df821b7448d6251a0ae8bc1c, + type: 2} + udonAssembly: + assemblyError: + sourceCsScript: {fileID: 11500000, guid: c32b0eecbf0b1b5418acf2f2662c03a7, type: 3} + behaviourIDHeapVarName: __refl_const_intnl_udonTypeID + compileErrors: [] + hasInteractEvent: 0 + serializationData: + SerializedFormat: 2 + SerializedBytes: + ReferencedUnityObjects: + - {fileID: 11500000, guid: 12bea67aa39620741af205f1260869a4, type: 3} + SerializedBytesString: + Prefab: {fileID: 0} + PrefabModificationsReferencedUnityObjects: [] + PrefabModifications: [] + SerializationNodes: + - Name: fieldDefinitions + Entry: 7 + Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition, + UdonSharp.Editor]], mscorlib + - Name: comparer + Entry: 7 + Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String, + mscorlib]], mscorlib + - Name: + Entry: 8 + Data: + - Name: + Entry: 12 + Data: 4 + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: _qrLibrary + - Name: $v + Entry: 7 + Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 3|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 7 + Data: 4|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: UdonQR, Assembly-CSharp + - Name: + Entry: 8 + Data: + - Name: declarationType + Entry: 3 + Data: 1 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: VRCUdonUdonBehaviour + - Name: symbolOriginalName + Entry: 1 + Data: _qrLibrary + - Name: symbolUniqueName + Entry: 1 + Data: _qrLibrary + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 5|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 10 + Data: 0 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: _canvasTarget + - Name: $v + Entry: 7 + Data: 6|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 7|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 7 + Data: 8|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: UnityEngine.UI.Text, UnityEngine.UI + - Name: + Entry: 8 + Data: + - Name: declarationType + Entry: 3 + Data: 1 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: UnityEngineUIText + - Name: symbolOriginalName + Entry: 1 + Data: _canvasTarget + - Name: symbolUniqueName + Entry: 1 + Data: _canvasTarget + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 9|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: errorCorrection + - Name: $v + Entry: 7 + Data: 10|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 11|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 7 + Data: 12|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Int32, mscorlib + - Name: + Entry: 8 + Data: + - Name: declarationType + Entry: 3 + Data: 1 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: errorCorrection + - Name: symbolUniqueName + Entry: 1 + Data: errorCorrection + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 13|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: maskPattern + - Name: $v + Entry: 7 + Data: 14|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: fieldSymbol + Entry: 7 + Data: 15|UdonSharp.Compiler.SymbolDefinition, UdonSharp.Editor + - Name: internalType + Entry: 9 + Data: 12 + - Name: declarationType + Entry: 3 + Data: 1 + - Name: syncMode + Entry: 3 + Data: 0 + - Name: symbolResolvedTypeName + Entry: 1 + Data: SystemInt32 + - Name: symbolOriginalName + Entry: 1 + Data: maskPattern + - Name: symbolUniqueName + Entry: 1 + Data: maskPattern + - Name: symbolDefaultValue + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: fieldAttributes + Entry: 7 + Data: 16|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: userBehaviourSource + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: diff --git a/Assets/UdonQR/Udon/UdonQRCanvasSetter.asset.meta b/Assets/UdonQR/Udon/UdonQRCanvasSetter.asset.meta new file mode 100644 index 0000000..e1beae4 --- /dev/null +++ b/Assets/UdonQR/Udon/UdonQRCanvasSetter.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e54052152dd448647b48087a5cc71c13 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UdonQR/UdonSharp.meta b/Assets/UdonQR/UdonSharp.meta new file mode 100644 index 0000000..859f028 --- /dev/null +++ b/Assets/UdonQR/UdonSharp.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 46bc2d058e1516846ac448b841533b67 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UdonQR/UdonSharp/UdonQR.cs b/Assets/UdonQR/UdonSharp/UdonQR.cs new file mode 100644 index 0000000..8c0ef04 --- /dev/null +++ b/Assets/UdonQR/UdonSharp/UdonQR.cs @@ -0,0 +1,875 @@ +// -*- coding: utf-8 -*- +/* +MIT License + +Copyright (c) 2021 Devon (Gorialis) R + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.UI; +using UdonSharp; +using VRC.SDKBase; +using VRC.Udon; + +#if !COMPILER_UDONSHARP && UNITY_EDITOR +using UnityEditor; +using UdonSharpEditor; +#endif + +public class UdonQR : UdonSharpBehaviour +{ + // Udon does not support UTF-8 or expose System.Text.Encoding so we must implement this ourselves + private short[] ToUTF8(char[] characters) + { + short[] buffer = new short[characters.Length * 4]; + + int writeIndex = 0; + for (int i = 0; i < characters.Length; i++) + { + uint character = characters[i]; + + if (character < 0x80) + { + buffer[writeIndex++] = (short)character; + } else if (character < 0x800) + { + buffer[writeIndex++] = (short)(0b11000000 | ((character >> 6) & 0b11111)); + buffer[writeIndex++] = (short)(0b10000000 | (character & 0b111111)); + } else if (character < 0x10000) + { + buffer[writeIndex++] = (short)(0b11100000 | ((character >> 12) & 0b1111)); + buffer[writeIndex++] = (short)(0b10000000 | ((character >> 6) & 0b111111)); + buffer[writeIndex++] = (short)(0b10000000 | (character & 0b111111)); + } else + { + buffer[writeIndex++] = (short)(0b11110000 | ((character >> 18) & 0b111)); + buffer[writeIndex++] = (short)(0b10000000 | ((character >> 12) & 0b111111)); + buffer[writeIndex++] = (short)(0b10000000 | ((character >> 6) & 0b111111)); + buffer[writeIndex++] = (short)(0b10000000 | (character & 0b111111)); + } + } + + // We do this to truncate off the end of the array + // This would be a lot easier with Array.Resize, but Udon once again does not allow access to it. + short[] output = new short[writeIndex]; + + for (int i = 0; i < writeIndex; i++) + output[i] = buffer[i]; + + return output; + } + + public readonly int ERROR_CORRECTION_L = 1; + public readonly int ERROR_CORRECTION_M = 0; + public readonly int ERROR_CORRECTION_Q = 3; + public readonly int ERROR_CORRECTION_H = 2; + + public const int MODE_NUMBER = 1 << 0; + public const int MODE_ALPHANUMERIC = 1 << 1; + public const int MODE_BYTES = 1 << 2; + public const int MODE_KANJI = 1 << 3; + + + private readonly int[][] ADJUST_PATTERN_POSITIONS = { + new int[] {}, + new int[] {6, 18}, + new int[] {6, 22}, + new int[] {6, 26}, + new int[] {6, 30}, + new int[] {6, 34}, + new int[] {6, 22, 38}, + new int[] {6, 24, 42}, + new int[] {6, 26, 46}, + new int[] {6, 28, 50}, + new int[] {6, 30, 54}, + new int[] {6, 32, 58}, + new int[] {6, 34, 62}, + new int[] {6, 26, 46, 66}, + new int[] {6, 26, 48, 70}, + new int[] {6, 26, 50, 74}, + new int[] {6, 30, 54, 78}, + new int[] {6, 30, 56, 82}, + new int[] {6, 30, 58, 86}, + new int[] {6, 34, 62, 90}, + new int[] {6, 28, 50, 72, 94}, + new int[] {6, 26, 50, 74, 98}, + new int[] {6, 30, 54, 78, 102}, + new int[] {6, 28, 54, 80, 106}, + new int[] {6, 32, 58, 84, 110}, + new int[] {6, 30, 58, 86, 114}, + new int[] {6, 34, 62, 90, 118}, + new int[] {6, 26, 50, 74, 98, 122}, + new int[] {6, 30, 54, 78, 102, 126}, + new int[] {6, 26, 52, 78, 104, 130}, + new int[] {6, 30, 56, 82, 108, 134}, + new int[] {6, 34, 60, 86, 112, 138}, + new int[] {6, 30, 58, 86, 114, 142}, + new int[] {6, 34, 62, 90, 118, 146}, + new int[] {6, 30, 54, 78, 102, 126, 150}, + new int[] {6, 24, 50, 76, 102, 128, 154}, + new int[] {6, 28, 54, 80, 106, 132, 158}, + new int[] {6, 32, 58, 84, 110, 136, 162}, + new int[] {6, 26, 54, 82, 110, 138, 166}, + new int[] {6, 30, 58, 86, 114, 142, 170}, + }; + + private readonly int[][] RS_BLOCKS = { + // Version 1 + /* M */ new int[] {1, 26, 16}, /* L */ new int[] {1, 26, 19}, /* H */ new int[] {1, 26, 9}, /* Q */ new int[] {1, 26, 13}, + // Version 2 + /* M */ new int[] {1, 44, 28}, /* L */ new int[] {1, 44, 34}, /* H */ new int[] {1, 44, 16}, /* Q */ new int[] {1, 44, 22}, + // Version 3 + /* M */ new int[] {1, 70, 44}, /* L */ new int[] {1, 70, 55}, /* H */ new int[] {2, 35, 13}, /* Q */ new int[] {2, 35, 17}, + // Version 4 + /* M */ new int[] {2, 50, 32}, /* L */ new int[] {1, 100, 80}, /* H */ new int[] {4, 25, 9}, /* Q */ new int[] {2, 50, 24}, + // Version 5 + /* M */ new int[] {2, 67, 43}, /* L */ new int[] {1, 134, 108}, /* H */ new int[] {2, 33, 11, 2, 34, 12}, /* Q */ new int[] {2, 33, 15, 2, 34, 16}, + // Version 6 + /* M */ new int[] {4, 43, 27}, /* L */ new int[] {2, 86, 68}, /* H */ new int[] {4, 43, 15}, /* Q */ new int[] {4, 43, 19}, + // Version 7 + /* M */ new int[] {4, 49, 31}, /* L */ new int[] {2, 98, 78}, /* H */ new int[] {4, 39, 13, 1, 40, 14}, /* Q */ new int[] {2, 32, 14, 4, 33, 15}, + // Version 8 + /* M */ new int[] {2, 60, 38, 2, 61, 39}, /* L */ new int[] {2, 121, 97}, /* H */ new int[] {4, 40, 14, 2, 41, 15}, /* Q */ new int[] {4, 40, 18, 2, 41, 19}, + // Version 9 + /* M */ new int[] {3, 58, 36, 2, 59, 37}, /* L */ new int[] {2, 146, 116}, /* H */ new int[] {4, 36, 12, 4, 37, 13}, /* Q */ new int[] {4, 36, 16, 4, 37, 17}, + // Version 10 + /* M */ new int[] {4, 69, 43, 1, 70, 44}, /* L */ new int[] {2, 86, 68, 2, 87, 69}, /* H */ new int[] {6, 43, 15, 2, 44, 16}, /* Q */ new int[] {6, 43, 19, 2, 44, 20}, + // Version 11 + /* M */ new int[] {1, 80, 50, 4, 81, 51}, /* L */ new int[] {4, 101, 81}, /* H */ new int[] {3, 36, 12, 8, 37, 13}, /* Q */ new int[] {4, 50, 22, 4, 51, 23}, + // Version 12 + /* M */ new int[] {6, 58, 36, 2, 59, 37}, /* L */ new int[] {2, 116, 92, 2, 117, 93}, /* H */ new int[] {7, 42, 14, 4, 43, 15}, /* Q */ new int[] {4, 46, 20, 6, 47, 21}, + // Version 13 + /* M */ new int[] {8, 59, 37, 1, 60, 38}, /* L */ new int[] {4, 133, 107}, /* H */ new int[] {12, 33, 11, 4, 34, 12}, /* Q */ new int[] {8, 44, 20, 4, 45, 21}, + // Version 14 + /* M */ new int[] {4, 64, 40, 5, 65, 41}, /* L */ new int[] {3, 145, 115, 1, 146, 116}, /* H */ new int[] {11, 36, 12, 5, 37, 13}, /* Q */ new int[] {11, 36, 16, 5, 37, 17}, + // Version 15 + /* M */ new int[] {5, 65, 41, 5, 66, 42}, /* L */ new int[] {5, 109, 87, 1, 110, 88}, /* H */ new int[] {11, 36, 12, 7, 37, 13}, /* Q */ new int[] {5, 54, 24, 7, 55, 25}, + // Version 16 + /* M */ new int[] {7, 73, 45, 3, 74, 46}, /* L */ new int[] {5, 122, 98, 1, 123, 99}, /* H */ new int[] {3, 45, 15, 13, 46, 16}, /* Q */ new int[] {15, 43, 19, 2, 44, 20}, + // Version 17 + /* M */ new int[] {10, 74, 46, 1, 75, 47}, /* L */ new int[] {1, 135, 107, 5, 136, 108}, /* H */ new int[] {2, 42, 14, 17, 43, 15}, /* Q */ new int[] {1, 50, 22, 15, 51, 23}, + // Version 18 + /* M */ new int[] {9, 69, 43, 4, 70, 44}, /* L */ new int[] {5, 150, 120, 1, 151, 121}, /* H */ new int[] {2, 42, 14, 19, 43, 15}, /* Q */ new int[] {17, 50, 22, 1, 51, 23}, + // Version 19 + /* M */ new int[] {3, 70, 44, 11, 71, 45}, /* L */ new int[] {3, 141, 113, 4, 142, 114}, /* H */ new int[] {9, 39, 13, 16, 40, 14}, /* Q */ new int[] {17, 47, 21, 4, 48, 22}, + // Version 20 + /* M */ new int[] {3, 67, 41, 13, 68, 42}, /* L */ new int[] {3, 135, 107, 5, 136, 108}, /* H */ new int[] {15, 43, 15, 10, 44, 16}, /* Q */ new int[] {15, 54, 24, 5, 55, 25}, + // Version 21 + /* M */ new int[] {17, 68, 42}, /* L */ new int[] {4, 144, 116, 4, 145, 117}, /* H */ new int[] {19, 46, 16, 6, 47, 17}, /* Q */ new int[] {17, 50, 22, 6, 51, 23}, + // Version 22 + /* M */ new int[] {17, 74, 46}, /* L */ new int[] {2, 139, 111, 7, 140, 112}, /* H */ new int[] {34, 37, 13}, /* Q */ new int[] {7, 54, 24, 16, 55, 25}, + // Version 23 + /* M */ new int[] {4, 75, 47, 14, 76, 48}, /* L */ new int[] {4, 151, 121, 5, 152, 122}, /* H */ new int[] {16, 45, 15, 14, 46, 16}, /* Q */ new int[] {11, 54, 24, 14, 55, 25}, + // Version 24 + /* M */ new int[] {6, 73, 45, 14, 74, 46}, /* L */ new int[] {6, 147, 117, 4, 148, 118}, /* H */ new int[] {30, 46, 16, 2, 47, 17}, /* Q */ new int[] {11, 54, 24, 16, 55, 25}, + // Version 25 + /* M */ new int[] {8, 75, 47, 13, 76, 48}, /* L */ new int[] {8, 132, 106, 4, 133, 107}, /* H */ new int[] {22, 45, 15, 13, 46, 16}, /* Q */ new int[] {7, 54, 24, 22, 55, 25}, + // Version 26 + /* M */ new int[] {19, 74, 46, 4, 75, 47}, /* L */ new int[] {10, 142, 114, 2, 143, 115}, /* H */ new int[] {33, 46, 16, 4, 47, 17}, /* Q */ new int[] {28, 50, 22, 6, 51, 23}, + // Version 27 + /* M */ new int[] {22, 73, 45, 3, 74, 46}, /* L */ new int[] {8, 152, 122, 4, 153, 123}, /* H */ new int[] {12, 45, 15, 28, 46, 16}, /* Q */ new int[] {8, 53, 23, 26, 54, 24}, + // Version 28 + /* M */ new int[] {3, 73, 45, 23, 74, 46}, /* L */ new int[] {3, 147, 117, 10, 148, 118}, /* H */ new int[] {11, 45, 15, 31, 46, 16}, /* Q */ new int[] {4, 54, 24, 31, 55, 25}, + // Version 29 + /* M */ new int[] {21, 73, 45, 7, 74, 46}, /* L */ new int[] {7, 146, 116, 7, 147, 117}, /* H */ new int[] {19, 45, 15, 26, 46, 16}, /* Q */ new int[] {1, 53, 23, 37, 54, 24}, + // Version 30 + /* M */ new int[] {19, 75, 47, 10, 76, 48}, /* L */ new int[] {5, 145, 115, 10, 146, 116}, /* H */ new int[] {23, 45, 15, 25, 46, 16}, /* Q */ new int[] {15, 54, 24, 25, 55, 25}, + // Version 31 + /* M */ new int[] {2, 74, 46, 29, 75, 47}, /* L */ new int[] {13, 145, 115, 3, 146, 116}, /* H */ new int[] {23, 45, 15, 28, 46, 16}, /* Q */ new int[] {42, 54, 24, 1, 55, 25}, + // Version 32 + /* M */ new int[] {10, 74, 46, 23, 75, 47}, /* L */ new int[] {17, 145, 115}, /* H */ new int[] {19, 45, 15, 35, 46, 16}, /* Q */ new int[] {10, 54, 24, 35, 55, 25}, + // Version 33 + /* M */ new int[] {14, 74, 46, 21, 75, 47}, /* L */ new int[] {17, 145, 115, 1, 146, 116}, /* H */ new int[] {11, 45, 15, 46, 46, 16}, /* Q */ new int[] {29, 54, 24, 19, 55, 25}, + // Version 34 + /* M */ new int[] {14, 74, 46, 23, 75, 47}, /* L */ new int[] {13, 145, 115, 6, 146, 116}, /* H */ new int[] {59, 46, 16, 1, 47, 17}, /* Q */ new int[] {44, 54, 24, 7, 55, 25}, + // Version 35 + /* M */ new int[] {12, 75, 47, 26, 76, 48}, /* L */ new int[] {12, 151, 121, 7, 152, 122}, /* H */ new int[] {22, 45, 15, 41, 46, 16}, /* Q */ new int[] {39, 54, 24, 14, 55, 25}, + // Version 36 + /* M */ new int[] {6, 75, 47, 34, 76, 48}, /* L */ new int[] {6, 151, 121, 14, 152, 122}, /* H */ new int[] {2, 45, 15, 64, 46, 16}, /* Q */ new int[] {46, 54, 24, 10, 55, 25}, + // Version 37 + /* M */ new int[] {29, 74, 46, 14, 75, 47}, /* L */ new int[] {17, 152, 122, 4, 153, 123}, /* H */ new int[] {24, 45, 15, 46, 46, 16}, /* Q */ new int[] {49, 54, 24, 10, 55, 25}, + // Version 38 + /* M */ new int[] {13, 74, 46, 32, 75, 47}, /* L */ new int[] {4, 152, 122, 18, 153, 123}, /* H */ new int[] {42, 45, 15, 32, 46, 16}, /* Q */ new int[] {48, 54, 24, 14, 55, 25}, + // Version 39 + /* M */ new int[] {40, 75, 47, 7, 76, 48}, /* L */ new int[] {20, 147, 117, 4, 148, 118}, /* H */ new int[] {10, 45, 15, 67, 46, 16}, /* Q */ new int[] {43, 54, 24, 22, 55, 25}, + // Version 40 + /* M */ new int[] {18, 75, 47, 31, 76, 48}, /* L */ new int[] {19, 148, 118, 6, 149, 119}, /* H */ new int[] {20, 45, 15, 61, 46, 1}, /* Q */ new int[] {34, 54, 24, 34, 55, 25}, + }; + + + private readonly byte[] RS_POLYNOMIAL_LUT_KEYS = { + 7, 10, 13, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30 + }; + private readonly byte[][] RS_POLYNOMIAL_LUT_VALUES = { + new byte[] {1, 127, 122, 154, 164, 11, 68, 117}, + new byte[] {1, 216, 194, 159, 111, 199, 94, 95, 113, 157, 193}, + new byte[] {1, 137, 73, 227, 17, 177, 17, 52, 13, 46, 43, 83, 132, 120}, + new byte[] {1, 29, 196, 111, 163, 112, 74, 10, 105, 105, 139, 132, 151, 32, 134, 26}, + new byte[] {1, 59, 13, 104, 189, 68, 209, 30, 8, 163, 65, 41, 229, 98, 50, 36, 59}, + new byte[] {1, 119, 66, 83, 120, 119, 22, 197, 83, 249, 41, 143, 134, 85, 53, 125, 99, 79}, + new byte[] {1, 239, 251, 183, 113, 149, 175, 199, 215, 240, 220, 73, 82, 173, 75, 32, 67, 217, 146}, + new byte[] {1, 152, 185, 240, 5, 111, 99, 6, 220, 112, 150, 69, 36, 187, 22, 228, 198, 121, 121, 165, 174}, + new byte[] {1, 89, 179, 131, 176, 182, 244, 19, 189, 69, 40, 28, 137, 29, 123, 67, 253, 86, 218, 230, 26, 145, 245}, + new byte[] {1, 122, 118, 169, 70, 178, 237, 216, 102, 115, 150, 229, 73, 130, 72,61, 43, 206, 1, 237, 247, 127, 217, 144, 117}, + new byte[] {1, 246, 51, 183, 4, 136, 98, 199, 152, 77, 56, 206, 24, 145, 40, 209, 117, 233, 42, 135, 68, 70, 144, 146, 77, 43, 94}, + new byte[] {1, 252, 9, 28, 13, 18, 251, 208, 150, 103, 174, 100, 41, 167, 12, 247, 56, 117, 119, 233, 127, 181, 100, 121, 147, 176, 74, 58, 197}, + new byte[] {1, 212, 246, 77, 73, 195, 192, 75, 98, 5, 70, 103, 177, 22, 217, 138, 51, 181, 246, 72, 25, 18, 46, 228, 74, 216, 195, 11, 106, 130, 150}, + }; + + private readonly int[][] BIT_LIMIT_TABLE = { + new int[] {0, 128, 224, 352, 512, 688, 864, 992, 1232, 1456, 1728, 2032, 2320, 2672, 2920, 3320, 3624, 4056, 4504, 5016, 5352, 5712, 6256, 6880, 7312, 8000, 8496, 9024, 9544, 10136, 10984, 11640, 12328, 13048, 13800, 14496, 15312, 15936, 16816, 17728, 18672}, + new int[] {0, 152, 272, 440, 640, 864, 1088, 1248, 1552, 1856, 2192, 2592, 2960, 3424, 3688, 4184, 4712, 5176, 5768, 6360, 6888, 7456, 8048, 8752, 9392, 10208, 10960, 11744, 12248, 13048, 13880, 14744, 15640, 16568, 17528, 18448, 19472, 20528, 21616, 22496, 23648}, + new int[] {0, 72, 128, 208, 288, 368, 480, 528, 688, 800, 976, 1120, 1264, 1440, 1576, 1784, 2024, 2264, 2504, 2728, 3080, 3248, 3536, 3712, 4112, 4304, 4768, 5024, 5288, 5608, 5960, 6344, 6760, 7208, 7688, 7888, 8432, 8768, 9136, 9776, 10208}, + new int[] {0, 104, 176, 272, 384, 496, 608, 704, 880, 1056, 1232, 1440, 1648, 1952, 2088, 2360, 2600, 2936, 3176, 3560, 3880, 4096, 4544, 4912, 5312, 5744, 6032, 6464, 6968, 7288, 7880, 8264, 8920, 9368, 9848, 10288, 10832, 11408, 12016, 12656, 13328}, + }; + + private const int BCH_G15 = ( + (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0) + ); + + private const int BCH_G18 = ( + (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0) + ); + + private const int BCH_G15_MASK = ( + (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1) + ); + + private const string ALPHANUMERIC_LUT = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'"; + + // Populated in Start + private readonly byte[] EXPONENT_TABLE = { + 1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76, 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96, 192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119, 238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161, 95, 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187, 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, 175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, 206, 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, 151, 51, 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, 168, 77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191, 99, 198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227, 219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87, 174, 65, 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, 81, 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, 18, 36, 72, 144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125, 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, 1 + }; + private readonly byte[] LOGARITHM_TABLE = { + 0, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 100, 224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113, 5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18, 130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, 120, 77, 228, 114, 166, 6, 191, 139, 98, 102, 221, 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148, 206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, 182, 163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61, 202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115, 243, 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24, 227, 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149, 188, 207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211, 171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31, 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, 111, 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90, 203, 89, 95, 176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230, 231, 173, 232, 116, 214, 244, 234, 168, 80, 88, 175 + }; + + public string Create(string input, int error_correction = 0, int mask_pattern = 1, string fill_character= "\u2588", string clear_character="\u2591") + { + // First, figure out what kind of encoding mode we want to use + bool only_numeric = true; + bool only_alphanumeric = true; + + for (int i = 0; i < input.Length; i++) { + char c = input[i]; + + if (c < 48 || c > 57) + only_numeric = false; + if (ALPHANUMERIC_LUT.IndexOf(c) == -1) + only_alphanumeric = false; + + // If we know that we can't use a smaller encoding, there is no reason to continue, + // because it won't change our minds about what encoding to use. + if (!only_numeric && !only_alphanumeric) + break; + } + + int encoding_mode; + short[] input_data; + int input_stride; + int input_stride_end; + + if (only_numeric) { + int numeric_buffer_size = (input.Length / 3) + ((input.Length % 3 == 0) ? 0 : 1); + input_data = new short[numeric_buffer_size]; + + // Main buffer is 10 bits + input_stride = 10; + // End will be shorter if not all digits are used + switch (input.Length % 3) { + case 0: + default: + input_stride_end = 10; + break; + case 1: + input_stride_end = 4; + break; + case 2: + input_stride_end = 7; + break; + } + + for (int i = 0; i < numeric_buffer_size; i++) { + string substring = input.Substring(i * 3, Mathf.Min(3, input.Length - (i * 3))); + input_data[i] = Int16.Parse(substring); + } + + encoding_mode = MODE_NUMBER; + } else if (only_alphanumeric) { + int alphanumeric_buffer_size = (input.Length / 2) + ((input.Length % 2 == 0) ? 0 : 1); + input_data = new short[alphanumeric_buffer_size]; + + // Main buffer is 11 bits + input_stride = 11; + // Only 6 bits are used if the final chunk is not a pair of 2 + input_stride_end = (input.Length % 2 == 0) ? 11 : 6; + + for (int i = 0; i < alphanumeric_buffer_size; i++) { + string substring = input.Substring(i * 2, Mathf.Min(2, input.Length - (i * 2))); + + if (substring.Length == 2) { + input_data[i] = (short)((ALPHANUMERIC_LUT.IndexOf(substring[0]) * 45) + ALPHANUMERIC_LUT.IndexOf(substring[1])); + } else { + input_data[i] = (short)ALPHANUMERIC_LUT.IndexOf(substring[0]); + } + } + + encoding_mode = MODE_ALPHANUMERIC; + } else { + input_data = ToUTF8(input.ToCharArray()); + // Always 8 bits + input_stride = 8; + input_stride_end = 8; + + encoding_mode = MODE_BYTES; + } + + // Calculate best version based on whether the data fits + int version; + for (version = 1; version < 41; version++) + { + int ephem_mode_size; + switch (encoding_mode) + { + case MODE_NUMBER: + ephem_mode_size = (version < 10) ? 10 : (version < 27) ? 12 : 14; + break; + case MODE_ALPHANUMERIC: + ephem_mode_size = (version < 10) ? 9 : (version < 27) ? 11 : 13; + break; + case MODE_BYTES: + default: + ephem_mode_size = (version < 10) ? 8 : (version < 27) ? 16 : 16; + break; + case MODE_KANJI: + ephem_mode_size = (version < 10) ? 8 : (version < 27) ? 10 : 12; + break; + } + + int needed_bits = 4 + ephem_mode_size + ((input_data.Length - 1) * input_stride) + input_stride_end; + int[] bit_limits = BIT_LIMIT_TABLE[error_correction]; + + int bisector; + for (bisector = version; bisector < bit_limits.Length; bisector++) + if (bit_limits[bisector] >= needed_bits) + break; + + if (bisector == version) + break; + } + + int module_count = version * 4 + 17; + // 0 for unset, 1 for fill, 2 for intentionally clear + byte[] modules = new byte[module_count * module_count]; + + // Set position patterns + int edge_probe_position = module_count - 7; + + for (int y = 0; y < 9; y++) { + for (int x = 0; x < 9; x++) { + byte filled = (x >= 1 && x <= 7 && y >= 1 && y <= 7 && (x == 1 || x == 7 || y == 1 || y == 7 || (x >= 3 && x <= 5 && y >= 3 && y <= 5))) ? (byte)1 : (byte)2; + if (x >= 1 && y >= 1) + modules[(module_count * (y - 1)) + (x - 1)] = filled; + if (x <= 7 && y >= 1) + modules[(module_count * (y - 1)) + edge_probe_position + (x - 1)] = filled; + if (x >= 1 && y <= 7) + modules[(module_count * (edge_probe_position + (y - 1))) + (x - 1)] = filled; + } + } + + // Set up adjust patterns + int[] adjust_patterns = ADJUST_PATTERN_POSITIONS[version - 1]; + + for (int y_index = 0; y_index < adjust_patterns.Length; y_index++) { + int y_position = adjust_patterns[y_index]; + for (int x_index = 0; x_index < adjust_patterns.Length; x_index++) { + int x_position = adjust_patterns[x_index]; + + if (modules[(module_count * y_position) + x_position] != 0) continue; + + // Unrolled for optimization + modules[(module_count * (y_position - 2)) + x_position - 2] = 1; + modules[(module_count * (y_position - 2)) + x_position - 1] = 1; + modules[(module_count * (y_position - 2)) + x_position + 0] = 1; + modules[(module_count * (y_position - 2)) + x_position + 1] = 1; + modules[(module_count * (y_position - 2)) + x_position + 2] = 1; + + modules[(module_count * (y_position - 1)) + x_position - 2] = 1; + modules[(module_count * (y_position - 1)) + x_position - 1] = 2; + modules[(module_count * (y_position - 1)) + x_position + 0] = 2; + modules[(module_count * (y_position - 1)) + x_position + 1] = 2; + modules[(module_count * (y_position - 1)) + x_position + 2] = 1; + + modules[(module_count * (y_position + 0)) + x_position - 2] = 1; + modules[(module_count * (y_position + 0)) + x_position - 1] = 2; + modules[(module_count * (y_position + 0)) + x_position + 0] = 1; + modules[(module_count * (y_position + 0)) + x_position + 1] = 2; + modules[(module_count * (y_position + 0)) + x_position + 2] = 1; + + modules[(module_count * (y_position + 1)) + x_position - 2] = 1; + modules[(module_count * (y_position + 1)) + x_position - 1] = 2; + modules[(module_count * (y_position + 1)) + x_position + 0] = 2; + modules[(module_count * (y_position + 1)) + x_position + 1] = 2; + modules[(module_count * (y_position + 1)) + x_position + 2] = 1; + + modules[(module_count * (y_position + 2)) + x_position - 2] = 1; + modules[(module_count * (y_position + 2)) + x_position - 1] = 1; + modules[(module_count * (y_position + 2)) + x_position + 0] = 1; + modules[(module_count * (y_position + 2)) + x_position + 1] = 1; + modules[(module_count * (y_position + 2)) + x_position + 2] = 1; + } + } + + // Set up timing pattern + for (int i = 8; i < module_count - 8; i++) { + if (modules[(module_count * i) + 6] == 0) + modules[(module_count * i) + 6] = (i % 2 == 0) ? (byte)1 : (byte)2; + if (modules[(module_count * 6) + i] == 0) + modules[(module_count * 6) + i] = (i % 2 == 0) ? (byte)1 : (byte)2; + } + + // Set up type info + int bch_type_info = (error_correction << 3) | mask_pattern; + int bch_type_info_d = bch_type_info << 10; + + int bch_type_digit_d = bch_type_info_d == 0 ? 0 : Mathf.FloorToInt(Mathf.Log(bch_type_info_d, 2.0f) + 1.0f); + + while (bch_type_digit_d - 11 >= 0) { + bch_type_info_d ^= (BCH_G15 << (bch_type_digit_d - 11)); + bch_type_digit_d = bch_type_info_d == 0 ? 0 : Mathf.FloorToInt(Mathf.Log(bch_type_info_d, 2.0f) + 1.0f); + } + + bch_type_info = ((bch_type_info << 10) | bch_type_info_d) ^ BCH_G15_MASK; + + for (int i = 0; i < 15; i++) { + byte match = ((bch_type_info >> i) & 1) == 1 ? (byte)1 : (byte)2; + + // Vertical type info + if (i < 6) + modules[(module_count * i) + 8] = match; + else if (i < 8) + modules[(module_count * (i + 1)) + 8] = match; + else + modules[(module_count * (module_count - 15 + i)) + 8] = match; + + // Horizontal type info + if (i < 8) + modules[(module_count * 8) + module_count - i - 1] = match; + else if (i < 9) + modules[(module_count * 8) + 15 - i] = match; + else + modules[(module_count * 8) + 15 - i - 1] = match; + } + + modules[(module_count * (module_count - 8)) + 8] = 1; + + if (version >= 7) { + // Set up type number + int bch_type_number = version << 12; + + bch_type_digit_d = bch_type_number == 0 ? 0 : Mathf.FloorToInt(Mathf.Log(bch_type_number, 2.0f) + 1.0f); + + while (bch_type_digit_d - 13 >= 0) + { + bch_type_number ^= (BCH_G18 << (bch_type_digit_d - 13)); + bch_type_digit_d = bch_type_number == 0 ? 0 : Mathf.FloorToInt(Mathf.Log(bch_type_number, 2.0f) + 1.0f); + } + + bch_type_number = (version << 12) | bch_type_number; + + for (int i = 0; i < 18; i++) + { + byte match = ((bch_type_number >> i) & 1) == 1 ? (byte)1 : (byte)2; + + modules[(module_count * (i / 3)) + i % 3 + module_count - 8 - 3] = match; + modules[(module_count * (i % 3 + module_count - 8 - 3)) + (i / 3)] = match; + } + } + + // Generate data cache + byte[] singleton_data_cache = new byte[input_data.Length + 1024]; + int data_cache_bit_length = 4; + + // Write data mode + singleton_data_cache[0] = (byte)(encoding_mode << 4); + + int mode_size; + + switch (encoding_mode) { + case MODE_NUMBER: + mode_size = (version < 10) ? 10 : (version < 27) ? 12 : 14; + break; + case MODE_ALPHANUMERIC: + mode_size = (version < 10) ? 9 : (version < 27) ? 11 : 13; + break; + case MODE_BYTES: + default: + mode_size = (version < 10) ? 8 : (version < 27) ? 16 : 16; + break; + case MODE_KANJI: + mode_size = (version < 10) ? 8 : (version < 27) ? 10 : 12; + break; + } + + // Write data length + int write_size = mode_size; + int source = (encoding_mode == MODE_BYTES) ? input_data.Length : input.Length; + + // write loop + for (int write_index = 0; write_index < write_size; write_index++) { + if (((source >> (write_size - write_index - 1)) & 1) == 1) + singleton_data_cache[data_cache_bit_length / 8] |= (byte)(0x80 >> (data_cache_bit_length % 8)); + data_cache_bit_length++; + } + + // Write actual data + for (int i = 0; i < input_data.Length; i++) { + write_size = (i == input_data.Length - 1) ? input_stride_end : input_stride; + source = input_data[i]; + + // write loop + for (int write_index = 0; write_index < write_size; write_index++) { + if (((source >> (write_size - write_index - 1)) & 1) == 1) + singleton_data_cache[data_cache_bit_length / 8] |= (byte)(0x80 >> (data_cache_bit_length % 8)); + data_cache_bit_length++; + } + } + + // Calculate RS blocks + int[] rs_block = RS_BLOCKS[(version - 1) * 4 + error_correction]; + + int[] rs_total_counts = new int[6 * 67]; + int[] rs_data_counts = new int[6 * 67]; + int rs_block_count = 0; + int bit_limit = 0; + int total_code_count = 0; + + for (int i = 0; i < rs_block.Length; i += 3) { + int count = rs_block[i]; + int total_count = rs_block[i + 1]; + int data_count = rs_block[i + 2]; + + for (int j = 0; j < count; j++, rs_block_count++) { + rs_total_counts[rs_block_count] = total_count; + rs_data_counts[rs_block_count] = data_count; + total_code_count += total_count; + bit_limit += data_count * 8; + } + } + + data_cache_bit_length += Mathf.Min(bit_limit - data_cache_bit_length, 4); + + // Delimit into words + if (data_cache_bit_length % 8 != 0) + data_cache_bit_length += (8 - (data_cache_bit_length % 8)); + + // Pad the remaining space + int bytes_to_fill = (bit_limit - data_cache_bit_length) / 8; + for (int i = 0; i < bytes_to_fill; i++) { + singleton_data_cache[data_cache_bit_length / 8] = (i % 2 == 0) ? (byte)0xEC : (byte)0x11; + data_cache_bit_length += 8; + } + + // Create bytes with RS blocks + int dc_offset = 0; + int max_dc_count = 0; + int max_ec_count = 0; + byte[][] dcdata = new byte[rs_block_count][]; + byte[][] ecdata = new byte[rs_block_count][]; + + for (int r = 0; r < rs_block_count; r++) { + int dc_count = rs_data_counts[r]; + int ec_count = rs_total_counts[r] - dc_count; + + max_dc_count = Mathf.Max(max_dc_count, dc_count); + max_ec_count = Mathf.Max(max_ec_count, ec_count); + + dcdata[r] = new byte[dc_count]; + + for (int i = 0; i < dc_count; i++) + dcdata[r][i] = (byte)(0xFF & singleton_data_cache[i + dc_offset]); + + dc_offset += dc_count; + + // Error correction polynomial + + // I wish Udon supported Dictionary + bool found = false; + byte[] rs_polynomial = new byte[1]; + rs_polynomial[0] = 1; + + for (int i = 0; i < RS_POLYNOMIAL_LUT_KEYS.Length; i++) { + if (ec_count == RS_POLYNOMIAL_LUT_KEYS[i]) { + found = true; + rs_polynomial = new byte[RS_POLYNOMIAL_LUT_VALUES[i].Length]; + RS_POLYNOMIAL_LUT_VALUES[i].CopyTo(rs_polynomial, 0); + break; + } + } + + if (!found) { + for (int i = 0; i < ec_count; i++) { + byte[] second = new byte[2]; + second[0] = 1; + second[1] = EXPONENT_TABLE[i]; + + byte[] new_rs_polynomial = new byte[rs_polynomial.Length + second.Length - 1]; + + for (int a = 0; a < rs_polynomial.Length; a++) { + for (int b = 0; b < second.Length; b++) { + new_rs_polynomial[a + b] ^= EXPONENT_TABLE[(LOGARITHM_TABLE[rs_polynomial[a]] + LOGARITHM_TABLE[second[b]]) % 255]; + } + } + + rs_polynomial = new_rs_polynomial; + // Trim + int rs_trim_offset = 0; + for (; rs_trim_offset < rs_polynomial.Length; rs_trim_offset++) + if (rs_polynomial[rs_trim_offset] != 0) + break; + + if (rs_trim_offset > 0) { + new_rs_polynomial = new byte[rs_polynomial.Length - rs_trim_offset]; + + for (int j = rs_trim_offset; j < rs_polynomial.Length; j++) + new_rs_polynomial[j - rs_trim_offset] = rs_polynomial[j]; + + rs_polynomial = new_rs_polynomial; + } + } + } + + byte[] raw_polynomial = new byte[dcdata[r].Length + rs_polynomial.Length - 1]; + dcdata[r].CopyTo(raw_polynomial, 0); + + // Trim + byte[] new_raw_polynomial; + int offset = 0; + for (; offset < raw_polynomial.Length; offset++) + if (raw_polynomial[offset] != 0) + break; + + if (offset > 0) { + new_raw_polynomial = new byte[raw_polynomial.Length - offset]; + + for (int j = offset; j < raw_polynomial.Length; j++) + new_raw_polynomial[j - offset] = raw_polynomial[j]; + + raw_polynomial = new_raw_polynomial; + } + + byte[] modulo_polynomial; + + // Uh oh + byte[] left_side = new byte[raw_polynomial.Length]; + raw_polynomial.CopyTo(left_side, 0); + byte[] right_side = new byte[rs_polynomial.Length]; + rs_polynomial.CopyTo(right_side, 0); + + while (true) { + if (left_side.Length - right_side.Length < 0) { + modulo_polynomial = left_side; + break; + } + + int ratio = LOGARITHM_TABLE[left_side[0]] - LOGARITHM_TABLE[right_side[0]]; + byte[] output_polynomial = new byte[left_side.Length]; + + for (int i = 0; i < right_side.Length; i++) + output_polynomial[i] = (byte)(left_side[i] ^ EXPONENT_TABLE[(LOGARITHM_TABLE[right_side[i]] + ratio) % 255]); + + for (int i = right_side.Length; i < left_side.Length; i++) + output_polynomial[i] = left_side[i]; + + // Trim + byte[] new_left_polynomial; + offset = 0; + for (; offset < output_polynomial.Length; offset++) + if (output_polynomial[offset] != 0) + break; + + if (offset > 0) { + new_left_polynomial = new byte[output_polynomial.Length - offset]; + + for (int j = offset; j < output_polynomial.Length; j++) + new_left_polynomial[j - offset] = output_polynomial[j]; + + output_polynomial = new_left_polynomial; + } + + left_side = output_polynomial; + } + + ecdata[r] = new byte[rs_polynomial.Length - 1]; + + for (int i = 0; i < rs_polynomial.Length - 1; i++) { + int mod_index = i + modulo_polynomial.Length - ecdata[r].Length; + + ecdata[r][i] = (byte)(mod_index >= 0 ? modulo_polynomial[mod_index] : 0); + } + + } + + byte[] data_cache = new byte[total_code_count]; + int data_cache_index = 0; + + for (int i = 0; i < max_dc_count; i++) { + for (int r = 0; r < rs_block_count; r++) { + if (i < dcdata[r].Length) { + data_cache[data_cache_index] = dcdata[r][i]; + data_cache_index++; + } + } + } + + for (int i = 0; i < max_ec_count; i++) { + for (int r = 0; r < rs_block_count; r++) { + if (i < ecdata[r].Length) { + data_cache[data_cache_index] = ecdata[r][i]; + data_cache_index++; + } + } + } + + // Map data + + int inc = -1; + int row = module_count - 1; + int bitIndex = 7; + int byteIndex = 0; + + for (int col = module_count - 1; col > 0; col -= 2) { + if (col <= 6) col--; + + while (true) { + for (int c = 0; c < 2; c++) { + if (modules[(module_count * row) + col - c] == 0) { + bool dark = false; + + if (byteIndex < data_cache.Length) + dark = (((data_cache[byteIndex] >> bitIndex) & 1) == 1); + + switch (mask_pattern) { + case 0: + dark = ((row + (col - c)) % 2 == 0) ? !dark : dark; + break; + case 1: + dark = (row % 2 == 0) ? !dark : dark; + break; + case 2: + dark = ((col - c) % 3 == 0) ? !dark : dark; + break; + case 3: + dark = ((row + (col - c)) % 3 == 0) ? !dark : dark; + break; + case 4: + dark = (((row / 2) + ((col - c) / 3)) % 2 == 0) ? !dark : dark; + break; + case 5: + dark = ((row * (col - c)) % 2 + (row * (col - c)) % 3 == 0) ? !dark : dark; + break; + case 6: + dark = (((row * (col - c)) % 2 + (row * (col - c)) % 3) % 2 == 0) ? !dark : dark; + break; + case 7: + dark = (((row * (col - c)) % 3 + (row + (col - c)) % 2) % 2 == 0) ? !dark : dark; + break; + } + + modules[(module_count * row) + col - c] = dark ? (byte)1 : (byte)2; + bitIndex -= 1; + + if (bitIndex == -1) { + byteIndex += 1; + bitIndex = 7; + } + } + } + + row += inc; + + if (row < 0 || module_count <= row) { + row -= inc; + inc = -inc; + break; + } + } + } + + // Convert modules to text + string output = ""; + + for (int y = 0; y < module_count; ++y) { + for (int x = 0; x < module_count; ++x) + output += (modules[(y * module_count) + x] == 1) ? fill_character : clear_character; + output += "\n"; + } + + return output; + } + + void Start() + { + + } +} + +#if !COMPILER_UDONSHARP && UNITY_EDITOR + +[CustomEditor(typeof(UdonQR))] +public class UdonQREditor : Editor +{ + private string inputString = ""; + + private Text text; + + public override void OnInspectorGUI() + { + // Draws the default convert to UdonBehaviour button, program asset field, sync settings, etc. + if (UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(target)) return; + + UdonQR inspectorBehaviour = (UdonQR)target; + + if (!EditorApplication.isPlaying) + EditorGUILayout.HelpBox("Enter play mode to run tests", MessageType.Info); + + EditorGUI.BeginDisabledGroup(!EditorApplication.isPlaying); + + EditorGUILayout.LabelField("Input for QR"); + inputString = EditorGUILayout.TextArea(inputString); + + text = (Text)EditorGUILayout.ObjectField(text, typeof(Text), true); + + if (GUILayout.Button("Show QR")) + { + string output = inspectorBehaviour.Create(inputString); + EditorUtility.DisplayDialog("Results", output, "OK"); + text.text = output; + } + + EditorGUI.EndDisabledGroup(); + } +} +#endif diff --git a/Assets/UdonQR/UdonSharp/UdonQR.cs.meta b/Assets/UdonQR/UdonSharp/UdonQR.cs.meta new file mode 100644 index 0000000..a63320f --- /dev/null +++ b/Assets/UdonQR/UdonSharp/UdonQR.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12bea67aa39620741af205f1260869a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UdonQR/UdonSharp/UdonQRCanvasSetter.cs b/Assets/UdonQR/UdonSharp/UdonQRCanvasSetter.cs new file mode 100644 index 0000000..c374cf7 --- /dev/null +++ b/Assets/UdonQR/UdonSharp/UdonQRCanvasSetter.cs @@ -0,0 +1,78 @@ + +using UdonSharp; +using UnityEngine; +using UnityEngine.UI; +using VRC.SDKBase; +using VRC.Udon; +using System; + +#if !COMPILER_UDONSHARP && UNITY_EDITOR +using UnityEditor; +using UdonSharpEditor; +#endif + +public class UdonQRCanvasSetter : UdonSharpBehaviour +{ + public UdonQR _qrLibrary; + public Text _canvasTarget; + public int errorCorrection = 0; + public int maskPattern = 1; + + public void Set(string text) + { + _canvasTarget.text = _qrLibrary.Create(text, errorCorrection, maskPattern, "\u2588", "\u2591"); + } + + void Start() + { + + } +} + +#if !COMPILER_UDONSHARP && UNITY_EDITOR + +[CustomEditor(typeof(UdonQRCanvasSetter))] +public class UdonQRCanvasSetterEditor : Editor +{ + private string inputString = ""; + + public override void OnInspectorGUI() + { + // Draws the default convert to UdonBehaviour button, program asset field, sync settings, etc. + if (UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(target)) return; + + UdonQRCanvasSetter inspectorBehaviour = (UdonQRCanvasSetter)target; + + EditorGUILayout.LabelField("UdonQR library object:"); + inspectorBehaviour._qrLibrary = (UdonQR)EditorGUILayout.ObjectField(inspectorBehaviour._qrLibrary, typeof(UdonQR), true); + + EditorGUILayout.LabelField("Target canvas for QR code:"); + inspectorBehaviour._canvasTarget = (Text)EditorGUILayout.ObjectField(inspectorBehaviour._canvasTarget, typeof(Text), true); + + int[] errorCorrectionIdentifiers = { 1, 0, 3, 2 }; + string[] errorCorrectionLiterals = { "Low (L)", "Medium (M)", "Medium-High (Q)", "High (H)" }; + + inspectorBehaviour.errorCorrection = EditorGUILayout.IntPopup("Error correction level", inspectorBehaviour.errorCorrection, errorCorrectionLiterals, errorCorrectionIdentifiers); + + int[] maskPatternIdentifiers = { 0, 1, 2, 3, 4, 5, 6, 7 }; + string[] maskPatternLiterals = { "0 ((i + j) % 2 = 0)", "1 (i % 2 = 0)", "2 (j % 3 = 0)", "3 ((i + j) % 3 = 0)", "4 ((i / 2 + j / 3) % 2 = 0)", "5 ((i * j) % 2 + (i * j) % 3 = 0)", "6 (((i + j) % 3 + ((i + j) % 2)) % 2 = 0)", "7 (((i + j) % 2 + ((i + j) % 2)) % 3 = 0)" }; + + inspectorBehaviour.maskPattern = EditorGUILayout.IntPopup("Mask pattern", inspectorBehaviour.maskPattern, maskPatternLiterals, maskPatternIdentifiers); + + EditorGUILayout.Space(); + + EditorGUILayout.LabelField("Editor only", EditorStyles.boldLabel); + + EditorGUILayout.LabelField("Input for QR"); + inputString = EditorGUILayout.TextArea(inputString); + + if (GUILayout.Button("Set to value")) + { + if (inspectorBehaviour._qrLibrary == null) + EditorUtility.DisplayDialog("Error", "You need to set a library object.", "OK"); + else + inspectorBehaviour.Set(inputString); + } + } +} +#endif diff --git a/Assets/UdonQR/UdonSharp/UdonQRCanvasSetter.cs.meta b/Assets/UdonQR/UdonSharp/UdonQRCanvasSetter.cs.meta new file mode 100644 index 0000000..7fe754b --- /dev/null +++ b/Assets/UdonQR/UdonSharp/UdonQRCanvasSetter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c32b0eecbf0b1b5418acf2f2662c03a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UdonQR/version.txt b/Assets/UdonQR/version.txt new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/Assets/UdonQR/version.txt @@ -0,0 +1 @@ +1.0.0 diff --git a/Assets/UdonQR/version.txt.meta b/Assets/UdonQR/version.txt.meta new file mode 100644 index 0000000..2350139 --- /dev/null +++ b/Assets/UdonQR/version.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ef0a34ddd99d8e645a306d943cf7c04f +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/README.md b/README.md index 6740f5c..6a74969 100644 --- a/README.md +++ b/README.md @@ -1 +1,148 @@ -# vrchat-udon-qr \ No newline at end of file +*** + +

+ + + +

+

+ +a library for creating dynamic QR codes in VRChat worlds + +
+ + See it in VRChat + +

+ +*** + + +
+
+ +## How to add the library to your world + +Download the latest release from the [releases](https://github.com/Gorialis/vrchat-udon-qr/releases) page. + +You need the latest [VRCSDK3-WORLD](https://vrchat.com/home/download) and a copy of [UdonSharp](https://github.com/MerlinVR/UdonSharp/releases). + +To use the library in your scene, either drag an instance of the UdonQR prefab into the scene, or add the `UdonBehaviour` component to an existing object and give it the `UdonQR` program source. + +**You only need to have one instance of UdonQR in your world. The library object is stateless, and so it is safe for multiple behaviors or objects to use it at once.** + + +## Using the library in your world (simple method): + +The UdonQR package comes with a "QRCanvas" prefab that includes a correctly set up Canvas and Text component configured to display QR codes, as well as a frontend script. + +Drag the prefab into your world whereever you wish to display a QR code, and align the canvas such that the text is against a clean white background for the best results. + +Make sure to set your UdonQR library object in the script: + + + +**The "QRCanvas" prefab does not include the UdonQR library object within it. You must add it separately as above and set the field in QRCanvas.** + +You can set the error correction and mask pattern here as well. + +To set the displayed QR code to a given input, add a field to your custom behavior to reference the frontend script: + +```csharp +[SerializeField] +private UdonQRCanvasSetter _qrCanvas; +``` + +Then use it like this: + +```csharp +_qrCanvas.Set(text); +``` + +Make sure you set the field on your custom behavior to reference the QRCanvas object. + +## Using the library in your world (advanced method) + +Add or create the UdonQR library object as described above and add a field to your behavior to reference the library, like so: + +```csharp +[SerializeField] +private UdonQR _qrLibrary; +``` + +Make sure you set the field to reference the UdonQR prefab, or whichever object holds the program: + + + +You can then use the library from that behavior as described below. + +## API reference + +The UdonQR behavior only contains one public entrypoint. It is as such: + +`Create(string input, int error_correction, int mask_pattern, string fill_character, string clear_character) -> string` + +> **`string`** `input`: The string to store inside the QR code. +> +> If this is numeric or alphanumeric, the library will automatically detect this and use a more compact encoding within the QR code. + +> **`int`** `error_correction`: The level of error correction to use. +> +> The values are as such: +> +> **`ERROR_CORRECTION_L`** = `1` (Low error correction) +> +> **`ERROR_CORRECTION_M`** = `0` (Medium error correction) +> +> **`ERROR_CORRECTION_Q`** = `3` (Medium-high error correction) +> +> **`ERROR_CORRECTION_H`** = `2` (High error correction) +> +> The numbers here might be confusing, but this is genuinely how they are encoded within the code. +> +> I wanted to have these as accessible named constants, but it confuses Udon. + +> **`int`** `mask_pattern`: The mask pattern index to use. +> +> This can be any number from 0 to 7, inclusive. +> +> If you're not sure what to use here, just pick a number you like. There's a chance the same code with a different mask pattern will be picked up by QR code readers more easily, but the logic required to determine this objectively requires **every** mask pattern variant to be generated and individually assessed, so I didn't include automatic detection in this library for performance reasons. + +> **`string`** `fill_character`: What text should be used for each 'filled' (black) module in the QR code. +> +> This is used to generate the string output at the end of encoding. +> +> I recommend `\u2588` (FULL BLOCK) as a default. It's a filled black character with the same text metrics as other drawing symbol characters. + +> **`string`** `clear_character`: What text should be used for each 'clear' (white) module in the QR code. +> +> This is used to generate the string output at the end of encoding. +> +> I recommend `\u2591` (LIGHT SHADE) as a default. It's a feint interlaced character with the same text metrics as other drawing symbol characters. +> +> You may be tempted to use rich text to instead use FULL BLOCK in white. While this does work for small QR codes, using rich text formatting with a per-module frequency in a QR code is liable to hit the Unity 65536 generated mesh limit, which will cause your canvas to stop displaying correctly inexplicably (and with no way to tell this has happened from Udon). +> +> Thus, if you **do** want to go the extra mile to make your QR code look nice, I recommend using a custom font on your canvas text and instead making a special 'blank' character, and use that as your clear string. + +## FAQ + + +### Does this support Unicode? + +Yes, it does. This means you can safely use e.g. player usernames in your inputs and get the correct QR code. + +Udon does not actually natively expose encoding functions, so a mini-implementation of the conversion is included with the library. + +### How fast is it? + +The world linked in the header shows a demo of the library in action. + +The time taken to generate QR codes depends on the size of the input data involved. Larger amounts of data require more polls to figure out the correct versioning and encoding format, as well as more expensive polynomial calculations for error correction. + +Overall, the library is a **lot faster** than you might expect it to be (it was a lot faster than I expected, at least). Players might experience a momentary stutter during generation if their framerate is high, but this is only a fraction of a second and shouldn't be much of an issue unless you generate frequently. + +## Acknowledgements + +The library itself does not use or require anything but Udon and UdonSharp. + +This README and the sample world uses the Udon logo, which is property of VRChat Inc.