PaintARActivity

PaintARActivity.java
package com.passiolife.paintAR;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;

import com.google.ar.core.ArCoreApk;
import com.passiolife.paintAR.utils.ImageUtils;
import com.unity3d.player.UnityPlayer;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.HashMap;

public class PaintARActivity extends UnityPlayerActivity {

    private static final String TAG = "PaintARActivity";
    public boolean isArCoreInstalled;
    public String arCoreMessage;

    GetWallPatchInfos getWallPatchInfos;
    GetRawCameraImage getRawCameraImage;
    GetSavedImage getSavedImage;
    OnCornerPlaced onCornerPlaced;
    PassioSDKStatus passioSDKStatus;
    OnAdditivePatchChanged additivePatchChanged;
    OnSceneLoaded onSceneLoaded;
    GetPaintAreaInfo getPaintAreaInfo;
    public enum InteractionState {
        DISABLED(1),
        ENABLED(0);

        private int value;

        InteractionState(int value) {
            this.value = value;
        }
    }

    /**
     * provideCenterDot is called from the RemodelAR library
     * The developer can override the provideCenterDot method and it will return byte data of the image, which will be set as the Center Dot image
     * if a developer wants the default image used in the RemodelAR library then the developer can return a null
     * @return
     */
    public CenterDotInfo provideCenterDot() {
        return null;
    }

    /**
     * provideTLCorner is called from the RemodelAR library
     * The developer can override the provideTLCorner method and it will return byte data of the image, which will be set as the Top Left corner image
     * if a developer wants the default image used in the RemodelAR library then the developer can return a null
     * @return
     */
    public byte[] provideTLCorner() {
        return null;
    }

    /**
     * provideBRCorner is called from the RemodelAR library
     * The developer can override the provideBRCorner method and it will return byte data of the image, which will be set as the Bottom Right corner image
     * if a developer wants the default image used in the RemodelAR library then the developer can return a null
     * @return
     */
    public byte[] provideBRCorner() {
        return null;
    }

    /**
     * provideTRCorner is called from the RemodelAR library
     * The developer can override the provideTRCorner method and it will return byte data of the image, which will be set as the Top Right corner image
     * if a developer wants the default image used in the RemodelAR library then the developer can return a null
     * @return
     */
    public byte[] provideTRCorner() {
        return null;
    }

    /**
     * provideBLCorner is called from the RemodelAR library
     * The developer can override the provideBLCorner method and it will return byte data of the image, which will be set as the Bottom Left corner image
     * if a developer wants the default image used in the RemodelAR library then the developer can return a null
     * @return
     */
    public byte[] provideBLCorner() {
        return null;

    }

    /**
     * provideActiveColor is called from the RemodelAR library
     * The developer can override the provideActiveColor method and it will return a string of the color hex, which will be set as the selected side of the wall or patch
     * If a developer wants the default color used in the RemodelAR library then the developer can return a null, default value for the selected or Active color in the RemodelAR library is green
     * @return
     */
    public String provideActiveColor() {
        return null;
    }

    /**
     * provideInActiveColor is called from the RemodelAR library
     * The developer can override the provideActiveColor method and it will return a string of the color hex, which will be set as the inActive side of the wall or patch
     * If a developer wants the default color used in the RemodelAR library then the developer can return a null, default value for the inActive color in the RemodelAR library is white
     * @return
     */
    public String provideInActiveColor() {
        return null;
    }

    public void pickColor(String colorHex) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "PickColor", colorHex);
    }

    private void pickTexture(Bitmap texture) {

        String path = new ImageUtils(this)
                .setFileName("tex.png")
                .setDirectory("internal-transfer")
                .setExternal(false)
                .save(texture);

        pickTexture(path);
    }

    /**
     * Library will load texture from the texture path
     * @param texturePath
     */
    public void pickTexture(String texturePath) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "PickTexture", texturePath);
    }

    /**
     * Library will use colorHex to implement color on patch, load texture using texture path and will assign metadata using metaHashMap
     * @param colorHex
     * @param texturePath
     * @param metaHashMap
     */
    public void changeColor(String colorHex, String texturePath, HashMap<String, String> metaHashMap) {

        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("color", colorHex);
            jsonObject.put("texturePath", texturePath);
            JSONObject metaHashMapObject = new JSONObject();

            for (String key : metaHashMap.keySet()) {
                metaHashMapObject.put(key, metaHashMap.get(key));
            }
            jsonObject.put("metaHashMap", metaHashMapObject.toString());

            UnityPlayer.UnitySendMessage("PaintARSDKInterface", "ChangeColor", jsonObject.toString());

        } catch (JSONException je) {
            je.printStackTrace();
        }

    }

    /**
     * Library will remove the wall using wallPatchID
     * @param wallPatchID
     */
    public void removeWall(int wallPatchID) {
        removeWall(wallPatchID, null, null);
    }

    /**
     * Library will remove the wall using colorHex
     * @param colorHex
     */
    public void removeWall(String colorHex) {
        removeWall(colorHex, null);
    }

    /**
     * Library will remove the wall using colorHex and texturePath
     * @param colorHex
     * @param texturePath
     */
    public void removeWall(String colorHex, String texturePath) {
        removeWall(-1, colorHex, texturePath);
    }

    /**
     * Library will remove the wall using wallPatchID, colorHex and texturePath
     * @param colorHex
     * @param texturePath
     */
    public void removeWall(int wallPatchID, String colorHex, String texturePath) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("wallPatchID", wallPatchID);
            jsonObject.put("color", colorHex);
            jsonObject.put("texturePath", texturePath);

            UnityPlayer.UnitySendMessage("PaintARSDKInterface", "RemoveWall", jsonObject.toString());

        } catch (JSONException je) {
            je.printStackTrace();
        }
    }

    /**
     * Library will deselect all the walls
     */
    public void deSelectAllWallPatch() {
        this.onCornerPlaced = onCornerPlaced;
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "DeSelectAllWallPatch", "");
    }

    /**
     * The library will place the grid on calling this method.
     * In swatch approach on calling this method, wall will be placed
     * In the FloorPlan and PaintAreaCalculation approach, calling this AR core will start scanning the environment, and when it detects the plane,
     * The grid will be placed at that place automatically
     * @param onCornerPlaced
     */
    public void placeGrid(OnCornerPlaced onCornerPlaced) {
        this.onCornerPlaced = onCornerPlaced;
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "OnPlaceGridClick", "");
    }

    /**
     * Library will add wall patch
     */
    public void addWallFurniturePatch() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "AddWallFurniturePatch", "");
    }

    /**
     * Library will add floor patch
     */
    public void addFloorFurniturePatch() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "AddFloorFurniturePatch", "");
    }

    /***
     * onGridPlaced is called from the RemodelAR library
     * When the user scan the environment and first grid detected from the AR core, library will send the callback that the grid is placed
     * This method works for FloorPlan and PaintAreaCalculator approaches
     */
    public void onGridPlaced() {
        Log.d(TAG, "onGridPlaced");
    }

    /**
     * Library will authenticate the license on calling this method
     * To use this method, developer must first call the setSessionId method.
     * @param key Client's license key
     * @param uniqueDeviceIdentifier Unique device Identifier
     * @param appVersion App Version
     * @param passioSDKStatus Status of the PassIO SDK
     */
    public void configure(String key, String uniqueDeviceIdentifier, String appVersion, PassioSDKStatus passioSDKStatus) {
        try {
            JSONObject authJsonObject = new JSONObject();
            authJsonObject.put("key", key);
            authJsonObject.put("uniqueDeviceIdentifier", uniqueDeviceIdentifier);
            authJsonObject.put("appVersion", appVersion);

            this.passioSDKStatus = passioSDKStatus;
            UnityPlayer.UnitySendMessage("PaintARSDKInterface", "Configure",  authJsonObject.toString());

        } catch (JSONException je) {
            je.printStackTrace();
        }
    }

    /**
     * Library will store the session id to local data for the use while authenticating license
     * This method is necessary to call before calling the configure method.
     * @param sessionId
     */
    public void setSessionId(String sessionId)
    {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "SetSessionId", sessionId);
    }

    /**
     * onPassioSDKValid is called from the RemodelAR library
     * When SDK authentication is successful for the first time,
     * after a new session starts, on authentication success, SDK will use the onPassioSDKValid callback instead of the onPassioSDKLicensed.
     * @param message
     */
    public void onPassioSDKValid(String message) {
        Log.d(TAG, "NewDebugThis on Passio SDK Valid");
        if (passioSDKStatus != null)
            passioSDKStatus.onPassioSDKValid();
    }

    /**
     * onColor1Selected is called from the RemodelAR library
     * When the user selects the first color, the developer will call OnSelectColor1ByTouch from the app to obtain the color hex code.
     * The library will then use this callback to send the color hex code to the app.
     * @param colorCode
     */
    public void onColor1Selected(String colorCode) {

    }

    /**
     * onColor2Selected is called from the RemodelAR library
     * When the user selects the first color, the developer will call OnSelectColor2ByTouch from the app to obtain the color hex code.
     * The library will then use this callback to send the color hex code to the app.
     * @param colorCode
     */
    public void onColor2Selected(String colorCode) {

    }

    /**
     * onColor3Selected is called from the RemodelAR library
     * When the user selects the first color, the developer will call OnSelectColor3ByTouch from the app to obtain the color hex code.
     * The library will then use this callback to send the color hex code to the app.
     * @param colorCode
     */
    public void onColor3Selected(String colorCode) {

    }

    /**
     * onCameraReady is called from the RemodelAR library
     * When the camera renders the first frame, it gives a callback to an app that the camera is ready.
     * @param message
     */
    public void onCameraReady(String message) {
        Log.d(TAG, "Camera Is Ready " + message);
        if (passioSDKStatus != null) passioSDKStatus.onCameraReady();
    }

    /**
     * onPassioSDKError is called from the RemodelAR library
     * When SDK authentication is failed, SDK will use this callback to notify the app.
     * @param
     */
    public void onPassioSDKError(String error) {
        Log.d(TAG, "PassIo SDK Error  :- " + error);
        if (passioSDKStatus != null) passioSDKStatus.onPassioSDKError(error);
    }

    /**
     * onPassioSDKLicensed is called from the RemodelAR library
     * When SDK authentication is successful for the first time, SDK will use this callback to notify the app.
     * @param message
     */
    public void onPassioSDKLicensed(String message) {
        Log.d(TAG, "PassIo SDK Licensed " + message);
        if (passioSDKStatus != null)
            passioSDKStatus.onPassioSDKLicensed();
    }

    /**
     * The library will select the first sample color from the touch position
     * Here library will get a sample color by fetching the average color from the touch position
     */
    public void OnSelectColor1ByTouch() {
        OnSelectColor1ByTouch(false);
    }

    /**
     * The library will select first sample color from the touch position
     * Here library will get a sample color by fetching the average color from the touch position
     * @param applyToAll On passing true value selected color will apply to all the walls
     */
    public void OnSelectColor1ByTouch(boolean applyToAll) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "OnSelectColor1ByTouch", applyToAll ? "true" : "false");
    }

    /**
     * The library will select second sample color from the touch position
     * Here library will get a sample color by fetching the average color from the touch position
     */
    public void OnSelectColor2ByTouch() {
        OnSelectColor2ByTouch(false);
    }

    /**
     * The library will select second sample color from the touch position
     * Here library will get a sample color by fetching the average color from the touch position
     * @param applyToAll On passing true value selected color will apply to all the walls
     */
    public void OnSelectColor2ByTouch(boolean applyToAll) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "OnSelectColor2ByTouch", applyToAll ? "true" : "false");
    }

    /**
     * The library will select third sample color from the touch position
     * Here library will get a sample color by fetching the average color from the touch position
     */
    public void OnSelectColor3ByTouch() {
        OnSelectColor3ByTouch(false);
    }

    /**
     * The library will select third sample color from the touch position
     * Here library will get a sample color by fetching the average color from the touch position
     * @param applyToAll On passing true value selected color will apply to all the walls
     */
    public void OnSelectColor3ByTouch(boolean applyToAll) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "OnSelectColor3ByTouch", applyToAll ? "true" : "false");
    }

    /**
     * The library will stop picking sample colors after calling this method
     */
    public void stopPickingColor() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "StopPickingColor", "");
    }

    /**
     * The library will get the first sample color from the camera position
     * Here library will get a sample color by fetching the average color from the camera center position
     */
    public void selectBackgroundColor1() {
        selectBackgroundColor1(false);
    }

    /**
     * The library will get the first sample color from the camera position
     * Here library will get a sample color by fetching the average color from the camera center position
     * @param applyToAll On passing true value selected color will apply to all the walls
     */
    public void selectBackgroundColor1(boolean applyToAll) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "OnSelectColor1Click", applyToAll ? "true" : "false");
    }

    /**
     * The library will get the second sample color from the camera position
     * Here library will get a sample color by fetching the average color from the camera center position
     */
    public void selectBackgroundColor2() {
        selectBackgroundColor2(false);
    }

    /**
     * The library will get the second sample color from the camera position
     * Here library will get a sample color by fetching the average color from the camera center position
     * @param applyToAll On passing true value selected color will apply to all the walls
     */
    public void selectBackgroundColor2(boolean applyToAll) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "OnSelectColor2Click", applyToAll ? "true" : "false");
    }

    /**
     * The library will get the third sample color from the camera position
     * Here library will get a sample color by fetching the average color from the camera center position
     */
    public void selectBackgroundColor3() {
        selectBackgroundColor3(false);
    }

    /**
     * The library will get the third sample color from the camera position
     * Here library will get a sample color by fetching the average color from the camera center position
     * @param applyToAll On passing true value selected color will apply to all the walls
     */
    public void selectBackgroundColor3(boolean applyToAll) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "OnSelectColor3Click", applyToAll ? "true" : "false");
    }

    /**
     * Library will reset the occlusion
     */
    public void resetOcclusion() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "ResetOcclusion", "");
    }

    /**
     * The library will activate all the unPainted walls
     * @param paintIt On passing true the library will activate all the wall regardless of its paint status
     */
    public void showUnPaintedWalls(boolean paintIt) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "ShowUnPaintedWalls", paintIt ? "true" : "false");
    }

    /**
     * The library set the value for the occlusion
     * @param value amount of occlusion
     */
    public void setOcclusionThreshold(float value) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "OnThresholdChange", Float.toString(value));
    }

    /**
     * The library will take the sample average color from the camera center to calculate brightness
     */
    public void selectColorForBrightness() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "SelectColorForBrightness", "");
    }

    /**
     * The library will reset the entire scene
     */
    public void resetScene() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "ResetScene", "");
    }

    /**
     * The library will remove the select wall patch
     */
    public void removeActiveWallPatch() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "RemoveActiveWallPatch", "");
    }

    /**
     * The library will save image of that frame to the given path
     * Library will give callback when the image saved and will notify the app using receivedRawCameraImage callback
     * @param path The destination path to store the image
     * @param getRawCameraImage
     */
    public void retrieveRawCameraImage(String path, GetRawCameraImage getRawCameraImage) {
        this.getRawCameraImage = getRawCameraImage;
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "RetrieveRawCameraImage", path);
    }

    /**
     * The library will take screenshot on the frame this method is called
     * And it will store the image at the given path
     * The library will also give callback when the photo is saved on the given destination path using onImageSaved callback
     * @param path The destination path to store the image
     * @param getSavedImage
     */
    public void savePhoto(String path, GetSavedImage getSavedImage) {
        this.getSavedImage = getSavedImage;
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "SavePhoto", path);
    }

    /**
     * The library will return the wall patch info of all the walls
     * The app will receive a callback from the library when all paint-related information for the walls is collected, using the onImageSaved callback.
     * @param getWallPatchInfos
     */
    public void getPaintsInfo(GetWallPatchInfos getWallPatchInfos) {
        this.getWallPatchInfos = getWallPatchInfos;
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "GetPaintsInfo", "");

    }

    /**
     * The library will return the painted area info of all the walls
     * The app will receive a callback from the library when all painted area related information for the walls is collected, using the receivedPaintAreaInfo callback.
     * @param getPaintAreaInfo
     */
    public void getGetPaintAreaInfo(GetPaintAreaInfo getPaintAreaInfo) {
        this.getPaintAreaInfo = getPaintAreaInfo;
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "GetPaintAreaInfo", "");
    }

    /**
     * activeWallChanged is called from the RemodelAR library
     * When the user selects a different wall than the currently selected wall,
     * the library will notify the app with a callback that the active wall has been updated.
     * @param isActive
     */
    public void activeWallChanged(boolean isActive) {
        Log.d(TAG, "activeWallChanged " + isActive);
    }

    /**
     * analyticsEvent is called from the RemodelAR library
     * The library will use this callback function to handle any analytics event triggered within the library.
     * @param values
     */
    public void analyticsEvent(String values) {
        Log.d(TAG, "trackAnalytics> 4 " + values);
    }

    public void closeApp() {
        Log.d(TAG, "closeApp Triggered()");
        runOnUiThread(() -> onBackPressed());
    }

    public void sharePhoto(String path) {
/*        Intent share = new Intent(Intent.ACTION_SEND);
        share.setType("image/jpeg");
        Uri imageUri =  Uri.parse(path);
        share.putExtra(Intent.EXTRA_STREAM, imageUri);
        startActivity(Intent.createChooser(share, "Share image"));*/
        InputStream image_stream;
        try {
            image_stream = getContentResolver().openInputStream(Uri.parse(path));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return;
        }

        Bitmap bitmap = BitmapFactory.decodeStream(image_stream);
        Intent share = new Intent(Intent.ACTION_SEND);
        share.setType("image/jpeg");
        String bitmapPath = MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Image", null);
        Uri imageUri = Uri.parse(bitmapPath);
        share.putExtra(Intent.EXTRA_STREAM, imageUri);
        startActivity(Intent.createChooser(share, "Share Image"));

    }

    public class ARCoreStatus {
        public ArCoreApk.Availability code;
        public boolean supportAvailable = false;
        public String message;

        public ARCoreStatus(ArCoreApk.Availability code, boolean supportAvailable, String message) {
            this.code = code;
            this.supportAvailable = supportAvailable;
            this.message = message;
        }
    }

    public interface ARSupportStateListener {
        public void onARSupportStateChanged(ARCoreStatus arCoreState);
    }

    //TODO: remove json and use a class
    public void checkArCoreAvailability(ARSupportStateListener arSupportStateListener) {
        arCoreMessage = "";
        isArCoreInstalled = false;
        ArCoreApk.Availability code = ArCoreApk.getInstance().checkAvailability(this);
        try {
            switch (code) {
                case UNKNOWN_ERROR: {
                    arCoreMessage = "This device does not support AR Core";
                }
                case UNKNOWN_CHECKING: {
                    arCoreMessage = "Awaiting update";
                    Thread.sleep(250);
                    checkArCoreAvailability(arSupportStateListener);
                }
                case UNKNOWN_TIMED_OUT: {
                    arCoreMessage = "This device does not support AR Core";
                }
                case UNSUPPORTED_DEVICE_NOT_CAPABLE: {
                    arCoreMessage = "This device does not support AR Core";
                }
                case SUPPORTED_NOT_INSTALLED: {
                    arCoreMessage = "Please install ArCore to use this app";
                }
                case SUPPORTED_APK_TOO_OLD: {
                    arCoreMessage = "Please update ArCore to continue using this app";
                }
                case SUPPORTED_INSTALLED: {
                    isArCoreInstalled = true;
                    arCoreMessage = "AR Core is supported and ready to use";
                }
                default: {
                    arCoreMessage = "This device does not support AR Core";
                }
            }
//        } catch (UnavailableArcoreNotInstalledException e) {
//            arCoreMessage = "Please install ARCore to use this functionality";
//        } catch (UnavailableUserDeclinedInstallationException e) {
//            arCoreMessage = "Please install ARCore to use this functionality";
//        } catch (UnavailableApkTooOldException e) {
//            arCoreMessage = "Please install ARCore to use this functionality";
//        } catch (UnavailableSdkTooOldException e) {
//            arCoreMessage = "Please update this app";
        } catch (java.lang.Exception e) {
            arCoreMessage = "This device does not support AR";
        }

        //Toast.makeText(this, arCoreMessage, Toast.LENGTH_LONG).show();

        arSupportStateListener.onARSupportStateChanged(new ARCoreStatus(code, isArCoreInstalled, arCoreMessage));

    }

    /**
     * receivedWallPatchInfos is called from the RemodelAR library
     * When the developer uses the GetPaintsInfo endpoint to retrieve wall paint information,
     * the response library sends a callback with details such as width, height, and color.
     * @param value
     */
    public void receivedWallPatchInfos(Object[] value) {
        if (getWallPatchInfos != null) {
            if (value == null) getWallPatchInfos.receivedWallPatchInfos(null);
            else {
                WallPatchInfo[] covnertedArray = new WallPatchInfo[value.length];
                for (int index = 0; index < value.length; index++) {
                    covnertedArray[index] = (WallPatchInfo) value[index];
                }
                getWallPatchInfos.receivedWallPatchInfos(covnertedArray);
            }
            getWallPatchInfos = null;
        }
    }

    /**
     * receivedPaintAreaInfo is called from the RemodelAR library
     * When the developer uses the getGetPaintAreaInfo endpoint to retrieve wall paint area information,
     * the response library sends a callback with details such as width, height, and wall area.
     * @param value
     */
    public void receivedPaintAreaInfo(Object[] value) {
        if (getPaintAreaInfo != null) {
            if (value == null) getPaintAreaInfo.receivedPaintAreaInfo(null);
            else {
                PaintAreaInfo[] convertedArray = new PaintAreaInfo[value.length];
                for (int index = 0; index < value.length; index++) {
                    convertedArray[index] = (PaintAreaInfo) value[index];
                }
                getPaintAreaInfo.receivedPaintAreaInfo(convertedArray);
            }
            getPaintAreaInfo = null;
        }
    }

//    public void receivedRawCameraImage(byte[] value)
//    {
//        Log.d(TAG, "receivedRawCameraImage ");
//
//        if(getRawCameraImage!=null){
//            if(value.length==0) {
//                getRawCameraImage.failed();
//            }else{
//                getRawCameraImage.receivedGetRawCameraImage(value);
//            }
//            getRawCameraImage = null;
//        }
//    }

    /**
     * The library will start tracking the camera angle with Horizon
     * Camera angle is used in swatch approach while placing the grid or wall
     * The library will give callback when the camera angle is changed using onCameraAngleChange callback
     */
    public void startListeningCameraAngle() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "StartListeningCameraAngle", "");
    }

    /**
     * The library will stop tracking the camera angle with Horizon
     * Camera angle is used in swatch approach while placing the grid or wall
     */
    public void stopListeningCameraAngle() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "StopListeningCameraAngle", "");
    }

    /**
     * onCameraAngleChange is called from the RemodelAR library
     * When the startListeningCameraAngle endpoint is called to track the camera angle with Horizon,
     * the library will only return the angle if it has changed from the previous value.
     * @param angle
     */
    public void onCameraAngleChange(float angle) {
        Log.d(TAG, "onCameraAngleChange " + angle);
    }

//    public void showPlaceWallButton(boolean show){
//        Log.d(TAG, "showButton " + show);
//    }

    /**
     * The library will start tracking the camera distance from the wall
     * Camera distance is used in swatch approach to maintain the certain distance from the wall after placing the grid or wall
     */
    public void startListeningCameraDistance() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "StartListeningCameraDistance", "");
    }

    /**
     * The library will stop tracking the camera distance from the wall
     */
    public void stopListeningCameraDistance() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "StopListeningCameraDistance", "");
    }

    /**
     * onCameraDistanceChange is called from the RemodelAR library
     * When the startListeningCameraDistance endpoint is called to track the distance from the,
     * the library will only return the angle if it has changed from the previous value.
     * @param distance
     */
    public void onCameraDistanceChange(float distance) {
        //Log.d(TAG, "onCameraDistanceChange " + distance);
    }


    /**
     * stateChanged is called from the RemodelAR library
     * Whenever the state changes, the RemodelAR library calls the stateChanged callback function.
     * The current state of the AR system is represented by state.
     * @param state
     */
    public void stateChanged(String state) {
        Log.w(TAG, "STATE " + state);
    }

    /**
     * onCameraDistanceChange is called from the RemodelAR library
     * The library will return the path of the image stored by the library after capturing the image callback is called,
     * When to choose the environment user is scanning is the environment
     * @param value
     */
    public void receivedRawCameraImage(String value) {
        Log.d(TAG, "receivedRawCameraImage " + value.toString());

        if (getRawCameraImage != null) {
            if (value.isEmpty()) {
                getRawCameraImage.failed();
            } else {
                getRawCameraImage.receivedGetRawCameraImage(value);
            }
            getRawCameraImage = null;
        }
    }

    /**
     * onImageSaved is called from the RemodelAR library
     * When developer call the savePhoto endpoint to save the photo,
     * Library will return path of that image
     * @param value
     */
    public void onImageSaved(String[] value) {
        Log.d(TAG, "onImageSaved " + value.toString());
        if (getSavedImage != null) {
            if (value.length == 0 || value[0].length() == 0) {
                getSavedImage.failed();
            } else {
                getSavedImage.receivedSavedImage(value[0]);
            }
            getSavedImage = null;
        }
    }

    /**
     * Sets the interaction state with the patch
     * @param newState if the value enable then user can interact with the patch otherwise not.
     */
    public void setInteractionState(InteractionState newState) {
        Log.d(TAG, "PaintARActivity.setInteractionState" + "newState = " + newState + " | " + String.valueOf(newState.value));

        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "SetInteractionState", String.valueOf(newState.value));
    }

    /**
     * onFirstCornerSelected is called from the RemodelAR library
     * When user place the first point library will give this callback to app
     * This callback is relevant to the swatch approach only
     */
    public void onFirstCornerSelected() {
        if (onCornerPlaced != null) onCornerPlaced.onFirstCornerSelected();
    }

    /**
     * onSecondCornerSelected is called from the RemodelAR library
     * When user place the second point library will give this callback to app
     * This callback is relevant to the swatch approach only
     */
    public void onSecondCornerSelected() {
        if (onCornerPlaced != null) {
            onCornerPlaced.onSecondCornerSelected();
            onCornerPlaced = null;
        }
    }

    /**
     * onFirstPointSelected is called from the RemodelAR library
     * When user place the first point on the grid, library will give this callback to app
     * This callback is relevant to the FloorPlan and AreaCalculator approaches
     */
    public void onFirstPointSelected() {
    }

    /**
     * onLastPointSelected is called from the RemodelAR library
     * When user place the last point on the grid to complete the point placement, library will give this callback to app
     * This callback is relevant to the FloorPlan and AreaCalculator approaches
     */
    public void onLastPointSelected() {
    }

    //Will be called on adding new point as well as On removing point.

    /**
     * onOcclusionPointCountChanged is called from the RemodelAR library
     * On adding or removing the point this callback will be used by library to update the vertex count
     * @param vertexCount
     */
    public void onOcclusionPointCountChanged(int vertexCount) {
        Log.d(TAG, "onOcclusionPointCountChanged(" + vertexCount + ")");
    }

    /**
     * onOcclusionPointLoopClosed is called from the RemodelAR library
     * When the point placement loop is complete this callback will be used by library
     * @param
     */
    public void onOcclusionPointLoopClosed() {
        Log.d(TAG, "onOcclusionPointLoopClosed");
    }

    /*
    * Deprecated, use onPassioSDKReady instead via passioSDKStatus

    public void OnCameraReady() {
    }
    */

    /**
     * The library will start Swatch approach
     * @param onSceneLoaded library will give this callback when the scene is loaded completely after which to this approach
     */
    public void startLegacyApproach(OnSceneLoaded onSceneLoaded) {
        this.onSceneLoaded = onSceneLoaded;
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "StartLegacyApproach", "");
    }

    /**
     * The library will start FloorPlan approach
     * @param onSceneLoaded library will give this callback when the scene is loaded completely after which to this approach
     */
    public void startFloorPlanApproach(OnSceneLoaded onSceneLoaded) {
        this.onSceneLoaded = onSceneLoaded;
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "StartFloorPlanApproach", "");
    }

    /**
     * The library will start Shader approach
     * @param onSceneLoaded library will give this callback when the scene is loaded completely after which to this approach
     */
    public void startShaderApproach(OnSceneLoaded onSceneLoaded) {
        this.onSceneLoaded = onSceneLoaded;
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "StartShaderApproach", "");
    }

    /**
     * The library will start Wood approach
     * @param onSceneLoaded library will give this callback when the scene is loaded completely after which to this approach
     */
    public void startFurnitureApproach(OnSceneLoaded onSceneLoaded) {
        this.onSceneLoaded = onSceneLoaded;
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "StartFurnitureApproach", "");
    }

    /**
     * setOnSceneLoaded is called from the RemodelAR library
     * The library consists of two separate scenes - one for the Shader and another for the Swatch and FloorPlan approach.
     * Whenever a new approach is selected and a new scene is loaded,
     * the library initiates a callback to notify the app that the loading process of the new scene has been completed.
     * @param
     */
    public void setOnSceneLoaded() {
        if (this.onSceneLoaded != null) {
            this.onSceneLoaded.onSceneLoadComplete();
            Log.d(TAG, "onSceneLoadComplete");
            this.onSceneLoaded = null;
        }
    }

    /**
     * onWallBrightnessChange is called from the RemodelAR library
     * This callback will be triggered when there is a change in the brightness of the wall
     * @param newBrightness
     */
    public void onWallBrightnessChange(float newBrightness) {
        Log.d(TAG, "onWallBrightnessChange(" + newBrightness + ")");
    }

    /**
     * In floor plan approach after point placement is complete this method can be call to finish the shape
     * @param closeIt If the value is true, the library will complete the shape of the placed point,
     *                regardless of whether or not the points are placed in a loop.
     */
    public void finishShape(boolean closeIt) {
        finishShape(closeIt ? "true" : "false");
    }

    /**
     * In floor plan approach after point placement is complete this method can be call to finish the shape
     * @param closeIt If the value is true, the library will complete the shape of the placed point,
     *                regardless of whether or not the points are placed in a loop.
     */
    public void finishShape(String closeIt) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "FinishShape", closeIt);
    }

    /**
     * In FloorPlan or PaintAreaCalculator approach after setting the height of the on calling this method current height will be set
     */
    public void finishSettingHeight() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "FinishSettingHeight", "");
    }

    /**
     * The library will undo last placed point in FloorPlan or PaintAreaCalculator approach
     */
    public void undo() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "Undo", "");
    }

    /**
     * onVertexRemoved is called from the RemodelAR library
     * This callback will be triggered when vertex is removed
     * @param verticeCount the count of vertices
     */
    public void onVertexRemoved(int verticeCount) {
        Log.d(TAG, "onVertexRemoved(" + verticeCount + ")");
    }

    /**
     * onVertexRemoved is called from the RemodelAR library
     * This callback will be triggered when vertex is added
     * @param verticeCount the count of vertices
     */
    public void onVertexAdded(int verticeCount) {
        Log.d(TAG, "onVertexAdded(" + verticeCount + ")");
    }

    /**
     * onFirstOcclusionPointSelected is called from the RemodelAR library
     * This callback will be triggered when first point the occlusion patch is placed
     */
    public void onFirstOcclusionPointSelected() {
        Log.d(TAG, "First Occlusion Point Is Initiated");
    }

    /**
     * onSecondOcclusionPointSelected is called from the RemodelAR library
     * This callback will be triggered when second point the occlusion patch is placed
     */
    public void onSecondOcclusionPointSelected() {
        Log.d(TAG, "Second Occlusion Point Is Initiated");
    }

    /**
     * THe library will set the interaction state with the occlusion
     * @param wantToEnableOcclusionPatch If the value is false, the user cannot interact with the occlusion patch.
     *                                   If the value is true, the user can interact with the patch.
     */
    public void setOcclusionPatchState(boolean wantToEnableOcclusionPatch) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "SetOcclusionPatchState", wantToEnableOcclusionPatch ? "true" : "false");
    }

    /**
     * If point placement is not complete and this method called then the library will remove unfinished patch
     */
    public void stopAddingOcclusionPatch() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "StopAddingOcclusionPatch", "");
    }

    /**
     * The library will start process of adding Occlusion patch
     */
    public void addOcclusionPatch() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "AddOcclusionPatch", "");
    }

    /**
     * The library will start process of adding Extension patch
     */
    public void addExtensionPatch() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "AddExtensionPatch", "");
    }

    /**
     * The library will start process of adding 2D Point Extension patch
     */
    public void addPointExtensionPatch() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "AddPointExtensionPatch", "");
    }

    /**
     * The library will start process of adding 2D Point Occlusion patch
     */
    public void addPointOcclusionPatch() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "AddPointOcclusionPatch", "");
    }
    /**
     * The library will start process of adding 3D Point Extension patch
     */
    public void addPointExtensionPatch3D() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "AddPointExtensionPatch3D", "");
    }
    /**
     * The library will start process of adding 3D Point Occlusion patch
     */
    public void addPointOcclusionPatch3D() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "AddPointOcclusionPatch3D", "");
    }
    /**
     * The library will start process of adding Wood patch
     */
    public void addFurniturePatch() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "AddFurniturePatch", "");
    }
    /**
     * The library will convert the selected additive patch in 2D
     */
    public void convertSelectedAdditivePatch() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "ConvertSelectedAdditivePatch", "");
    }

    /**
     * The library will convert the selected additive patch in 3D
     */
    public void convertSelectedAdditivePatchInDimension() {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "ConvertSelectedAdditivePatchInDimension", "");
    }

    /**
     * The library will convert the selected additive patch to given type
     */
    public void convertSelectedAdditivePatchInDimension(String typeToConvert) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "ConvertSelectedAdditivePatchInDimension", typeToConvert);
    }

    /**
     * The library will remove the patch
     * @param wantToRemoveAllPatches If the parameter is set to true, all applied patches will be removed. Otherwise, only the selected patch will be removed.
     */
    public void removeAdditivePatch(boolean wantToRemoveAllPatches) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "RemoveAdditivePatch", wantToRemoveAllPatches ? "true" : "false");
    }

    /**
     * getDynamicCenterDotInfo is called from the RemodelAR library
     * If the developer wants to animate the center dot image, they can use this callback function provided by the library.
     * If the function returns null, the library will use the image from the provided callback for the center dot.
     * @return
     */
    public DynamicCenterDotInfo getDynamicCenterDotInfo() {
        return null;
    }

    /**
     * onAdditivePatchChangedInfo is called from the RemodelAR library
     * There are different types of additive patches supported by the Library, such as OcclusionPatch, ExtensionPatch, PointExtensionPatch, etc.
     * When the currently selected additive patch type changes, this callback is used by the library.
     * @param value
     */
    public void onAdditivePatchChangedInfo(Object value)
    {
        if (additivePatchChanged != null)
        {
            if (value == null)
            {
                additivePatchChanged.onAdditivePatchChanged(null);
                Log.d(TAG, "AdditivePatchInfo is null");
            }
            else
            {
                AdditivePatchInfo additivePatchInfo = (AdditivePatchInfo) value;
                additivePatchChanged.onAdditivePatchChanged(additivePatchInfo);
                Log.d(TAG, "AdditivePatchInfo " + additivePatchInfo);
            }
        }
    }

    public void registerForAdditivePatchChanges(OnAdditivePatchChanged additivePatchChanged){
        this.additivePatchChanged = additivePatchChanged;
    }

    /**
     * The library will set the height setting mode to touch,
     * Height will be set using the touch point or position
     */
    public void setHeightWithTouch()
    {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "SetHeightWithTouch", "");
    }

    /**
     * The library will set the height setting mode to camera
     * Height will be set using the camera position
     */
    public void setHeightWithCameraPosition()
    {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "SetHeightWithCameraPosition", "");
    }

    /**
     * The library will give this callback when applied color on the patch is changed
     * @param newColor
     */
    public void onColorChanged(String newColor) {
        Log.d(TAG, "callback : onColorChanged (" + newColor + ")");
    }

    /**
     * Sets the corner Restriction Mode for the added patches
     * @param isOn If the value is set to true, the corners of the patches will be restricted within the boundaries of the wall patch.
     *             Otherwise, they can be moved beyond the boundaries.
     */
    public void setCornerRestrictionMode(boolean isOn) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "SetCornerRestrictionMode", isOn ? "true" : "false");
    }

    /**
     * Sets the center dot animation mode
     * @param wantToAnimateFromSDK If the value is set to true, center dot will be animated otherwise not.
     *                             In order to animate the center, it is necessary to provide the "provideCenterDot" function to the SDK.
     */
    public void setCenterDotAnimationMode(boolean wantToAnimateFromSDK) {
        UnityPlayer.UnitySendMessage("PaintARSDKInterface", "SetCenterDotAnimationMode", wantToAnimateFromSDK ? "true" : "false");
    }
}


Last updated