public int LoadImageMarker(string fileName, string extension)
    {
        if (wasInitialized)
        {
            if (isMobile)
            {
                return(MobileWrapper.String_LoadImageMarker("Data/Raw/" + fileName, extension));
            }
            else
            {
                string path = Application.dataPath + "/StreamingAssets/" + fileName;

                int id = DesktopWrapper.LoadImageMarker(path, extension);

                if (id < 0)
                {
                    Debug.LogWarning("Failed to load marker image \"" + path + "." + extension + "\"");
                }
                else
                {
                    Debug.Log("Loaded marker image \"" + path + "." + extension + "\"");
                }

                return(id);
            }
        }
        else
        {
            return(-1);
        }
    }
    public uint Update()
    {
        if (wasInitialized)
        {
            if (isMobile)
            {
                if (Screen.orientation != currentOrientation && Time.frameCount > 1)
                {
                    ApplyViewSettings();

                    MobileWrapper.String_SetProjectionAndViewport(_camera.projectionMatrix, _camera.rect, (int)(currentOrientation = Screen.orientation), _reorientIPhoneSplash);
                }

                markerCount = MobileWrapper.String_GetData(markerInfo, maxMarkerCount);
            }
            else
            {
                if (DesktopWrapper.IsNewFrameReady())
                {
                    DesktopWrapper.ProcessFrame((uint)videoTextures[0].GetNativeTextureID(), 0);
                    markerCount             = DesktopWrapper.GetDataQuaternionBased(markerInfo, maxMarkerCount);
                    videoPlaneObject.active = true;
                }
            }
        }
        else
        {
            // Write dummy output data
            markerCount = 1;
            markerInfo[0].DummyData();
        }

        return(markerCount);
    }
    public StringWrapper(string previewCamName, float previewCamApproxVerticalFOV, Camera camera, bool reorientIPhoneSplash, bool fullscreen, float alignment)
    {
        _camera = camera;
        _reorientIPhoneSplash        = reorientIPhoneSplash;
        _fullscreen                  = fullscreen;
        _alignment                   = alignment;
        _previewCamApproxVerticalFOV = previewCamApproxVerticalFOV;

        ApplyViewSettings();

        lock (initLock)
        {
            for (uint i = 0; wasInstantiated && i < 10; i++)
            {
                System.Threading.Monitor.Exit(initLock);
                System.Threading.Thread.Sleep(500);
                System.Threading.Monitor.Enter(initLock);
            }

            if (wasInstantiated)
            {
                throw new System.InvalidOperationException("StringWrapper was already instantiated. Only one instance of StringWrapper may exist at any given time.");
            }

            wasInstantiated = true;

            if (isMobile)
            {
                camera.clearFlags = CameraClearFlags.Nothing;

                MobileWrapper.String_UnloadImageMarkers();

                videoTextures             = new Texture2D[] { new Texture2D(1, 1, TextureFormat.ARGB32, false), new Texture2D(1, 1, TextureFormat.ARGB32, false) };
                videoTextures[0].wrapMode = TextureWrapMode.Clamp;
                videoTextures[1].wrapMode = TextureWrapMode.Clamp;

                MobileWrapper.String_SetVideoTextureNames((uint)videoTextures[0].GetNativeTextureID(), (uint)videoTextures[1].GetNativeTextureID());

                MobileWrapper.String_SetProjectionAndViewport(camera.projectionMatrix, camera.rect, (int)Screen.orientation, reorientIPhoneSplash);

                MobileWrapper.String_EnableAR(true);

                wasInitialized = true;
            }
            else
            {
                try
                {
                    InitializePreviewPlugin(previewCamName, camera);
                }
                catch
                {
                    Debug.LogWarning("Couldn't initialize String preview plugin. StringWrapper will return placeholder data. " +
                                     "If you're *not* running Unity Pro, your editor doesn't support plugins, and you can safely ignore this message. You will still be able to deploy to iOS. " +
                                     "If you *are* running Unity Pro, please make sure you've added String.bundle from the SDK to your project.");
                }
            }
        }
    }
    public static string InvokeGUIFunction(string descriptor, string[] parameters)
    {
        if (isMobile)
        {
            return(MobileWrapper.String_InvokeGUIFunction(descriptor, parameters, parameters != null ? parameters.Length : 0));
        }

        return(null);
    }
    public Texture2D GetCurrentVideoTexture(out Matrix4x4 viewToVideoTextureTransform)
    {
        if (isMobile)
        {
            uint textureName = 0;

            if (MobileWrapper.String_GetCurrentVideoTexture(out textureName, out viewToVideoTextureTransform))
            {
                if (textureName == (uint)videoTextures[0].GetNativeTextureID())
                {
                    return(videoTextures[0]);
                }
                else if (textureName == (uint)videoTextures[1].GetNativeTextureID())
                {
                    return(videoTextures[1]);
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                Debug.LogError("Failed to get current video texture. This feature is only available in Developer, Pro and Campaign builds of the String SDK.");

                return(null);
            }
        }
        else
        {
            viewToVideoTextureTransform = Matrix4x4.TRS(
                new Vector3(0.5f, 0.5f, 0), Quaternion.identity,
                new Vector3(0.5f * ((float)Screen.width / Screen.height) * (float)previewHeight / previewWidth, -0.5f, 0)) * _camera.projectionMatrix;

            return(videoTextures[0]);
        }
    }
    void ApplyViewSettings()
    {
        if (isMobile)
        {
            const float cameraAspectRatio = 4f / 3f;

            bool landscape =
                Screen.orientation == ScreenOrientation.Landscape ||
                Screen.orientation == ScreenOrientation.LandscapeLeft ||
                Screen.orientation == ScreenOrientation.LandscapeRight;

            float aspectRatio = Screen.width / (float)Screen.height;
            float halfTan     = Mathf.Tan(MobileWrapper.String_GetDeviceVerticalFOV() * Mathf.PI / 360f);

            if (landscape)
            {
                if (_fullscreen)
                {
                    halfTan *= cameraAspectRatio / aspectRatio;
                }
            }
            else
            {
                halfTan *= cameraAspectRatio;
            }

            _camera.fieldOfView = Mathf.Atan(halfTan) * 360f / Mathf.PI;

            float orientedAlignment = _alignment;

            if (Screen.orientation == ScreenOrientation.Portrait || Screen.orientation == ScreenOrientation.LandscapeRight)
            {
                orientedAlignment = 1f - orientedAlignment;
            }

            if (_fullscreen)
            {
                _camera.rect = new Rect(0, 0, 1, 1);
            }
            else
            {
                if (landscape)
                {
                    float coverage = cameraAspectRatio / aspectRatio;

                    _camera.rect = new Rect((1 - coverage) * orientedAlignment, 0, coverage, 1);
                }
                else
                {
                    float coverage = cameraAspectRatio * aspectRatio;

                    _camera.rect = new Rect(0, (1 - coverage) * orientedAlignment, 1, coverage);
                }
            }
        }
        else
        {
            _camera.fieldOfView = _previewCamApproxVerticalFOV;
            _camera.rect        = new Rect(0, 0, 1, 1);
        }
    }