protected PLIImage getLocalImageAsynchronously(String url, PLTextureColorFormat colorFormat) {
   PLIImage result = new PLImage();
   mView
       .getDownloadManager()
       .add(
           new PLLocalFileDownloader(
               mView.getActivity().getApplicationContext(),
               url,
               new PLImageFileDownloaderListener(result, colorFormat)));
   return result;
 }
 protected boolean parseSensorialRotationJSON() {
   try {
     if (!mKeepParameters.sensorialRotation && mJSON.has("sensorialRotation")) {
       if (mJSON.getBoolean("sensorialRotation")) {
         if (!mView.startSensorialRotation()) mView.updateInitialSensorialRotation();
       } else mView.stopSensorialRotation();
     } else mView.updateInitialSensorialRotation();
   } catch (Throwable e) {
     this.didError(e);
     return false;
   }
   return true;
 }
 protected void didEnd() {
   if (mView != null) {
     mView.setLocked(false);
     mView = null;
   }
   mTransition = null;
 }
 protected void didError(String error) {
   if (mTransition != null) {
     mTransition.getListeners().removeAll();
     mTransition.stop();
   }
   mView.getDownloadManager().removeAll();
   PLLoaderListener internalListener = this.getInternalListener(), listener = this.getListener();
   if (internalListener != null) internalListener.didError(this, error);
   if (listener != null) listener.didError(this, error);
   this.didEnd();
 }
 protected void didError(final Throwable e) {
   mView
       .getActivity()
       .runOnUiThread(
           new Runnable() {
             @Override
             public void run() {
               didError(e.toString());
               PLLog.error("PLJSONLoader", e);
             }
           });
 }
 protected void didStop(boolean runOnUiThread) {
   if (runOnUiThread) {
     mView
         .getActivity()
         .runOnUiThread(
             new Runnable() {
               @Override
               public void run() {
                 didStop();
               }
             });
   } else this.didStop();
 }
 /** json methods */
 protected void requestJSON(PLFileDownloaderListener listener) {
   try {
     if (mURL != null) {
       if (this.isHTTPURL(mURL)) new PLHTTPFileDownloader(mURL, listener).downloadAsynchronously();
       else
         new PLLocalFileDownloader(mView.getActivity().getApplicationContext(), mURL, listener)
             .downloadAsynchronously();
     } else if (mJSONData != null)
       new Thread(new PLDataRunnable(listener, mURL, mJSONData, System.currentTimeMillis()))
           .start();
     else listener.didErrorDownload(mURL, "JSON string is empty", -1, null);
   } catch (Throwable e) {
     PLLog.error("PLJSONLoader::requestJSON", e);
     listener.didErrorDownload(mURL, e.getMessage(), -1, null);
   }
 }
 protected void loadHotspotTexture(
     PLIHotspot hotspot, String filename, String urlBase, PLTextureColorFormat colorFormat) {
   if (filename != null) {
     String url = this.buildURL(filename, urlBase);
     if (mHotspotTextures.containsKey(url)) hotspot.addTexture(mHotspotTextures.get(url));
     else {
       boolean isHTTPURL = this.isHTTPURL(url);
       PLITexture texture =
           new PLTexture(
               isHTTPURL ? new PLImage() : this.getLocalImageAsynchronously(url, colorFormat));
       mHotspotTextures.put(url, texture);
       hotspot.addTexture(texture);
       if (isHTTPURL)
         mView
             .getDownloadManager()
             .add(
                 new PLHTTPFileDownloader(
                     url, new PLImageFileDownloaderListener(texture.getImage(), colorFormat)));
     }
   }
 }
 /** load methods */
 protected void loadCubicPanoramaImage(
     PLCubicPanorama panorama,
     PLCubeFaceOrientation face,
     JSONObject images,
     String property,
     String urlBase,
     boolean hasPreviewImage,
     PLTextureColorFormat colorFormat)
     throws Exception {
   if (images.has(property)) {
     String url = this.buildURL(images.getString(property), urlBase);
     if (this.isHTTPURL(url))
       mView
           .getDownloadManager()
           .add(
               new PLHTTPFileDownloader(
                   url,
                   new PLPanoramaImageFileDownloaderListener(
                       panorama, colorFormat, face.ordinal())));
     else panorama.setImage(this.getLocalImageAsynchronously(url, colorFormat), face);
   } else if (!hasPreviewImage)
     throw new RuntimeException(String.format("images.%s property not exists", property));
 }
  @Override
  public void load(PLIView view, PLITransition transition, float initialPitch, float initialYaw) {
    if (view != null && (mURL != null || mJSONData != null)) {
      mView = view;
      mTransition = transition;
      mInitialPitch = initialPitch;
      mInitialYaw = initialYaw;
      mIsPreloadingImages = true;
      mKeepParameters = null;
      view.setLocked(true);
      PLLoaderListener internalListener = this.getInternalListener(), listener = this.getListener();
      if (internalListener != null) internalListener.didBegin(this);
      if (listener != null) listener.didBegin(this);
      this.requestJSON(
          new PLFileDownloaderListener() {
            @Override
            public void didBeginDownload(String url, long startTime) {}

            @Override
            public void didProgressDownload(String url, int progress) {}

            @Override
            public void didStopDownload(String url) {}

            @Override
            public void didEndDownload(String url, byte[] data, long elapsedTime) {
              parseJSON(data);
            }

            @Override
            public void didErrorDownload(String url, String error, int responseCode, byte[] data) {
              didError(new Exception(error));
            }
          });
    }
  }
 protected boolean parseCameraJSON(PLIPanorama panorama) {
   try {
     JSONObject camera = mJSON.getJSONObject("camera");
     if (camera != null) {
       PLIPanorama oldPanorama = mView.getPanorama();
       PLICamera oldCamera =
           (oldPanorama != null && !(oldPanorama instanceof PLBlankPanorama)
               ? oldPanorama.getCamera()
               : null);
       PLICamera currentCamera = panorama.getCamera();
       PLCameraParameters keep =
           (oldCamera != null && camera.has("keep")
               ? PLCameraParameterType.checkCameraParametersWithStringMask(
                   camera.getString("keep"))
               : PLCameraParameterType.checkCameraParametersWithMask(
                   PLCameraParameterType.PLCameraParameterTypeNone));
       float pitch = currentCamera.getInitialPitch(), yaw = currentCamera.getInitialYaw();
       if (keep.atvMin) currentCamera.setPitchMin(oldCamera.getPitchMin());
       else if (camera.has("atvMin"))
         currentCamera.setPitchMin((float) camera.getDouble("atvMin"));
       if (keep.atvMax) currentCamera.setPitchMax(oldCamera.getPitchMax());
       else if (camera.has("atvMax"))
         currentCamera.setPitchMax((float) camera.getDouble("atvMax"));
       if (keep.athMin) currentCamera.setYawMin(oldCamera.getYawMin());
       else if (camera.has("athMin")) currentCamera.setYawMin((float) camera.getDouble("athMin"));
       if (keep.athMax) currentCamera.setYawMax(oldCamera.getYawMax());
       else if (camera.has("athMax")) currentCamera.setYawMax((float) camera.getDouble("athMax"));
       if (keep.reverseRotation) currentCamera.setReverseRotation(oldCamera.isReverseRotation());
       else if (camera.has("reverseRotation"))
         currentCamera.setReverseRotation(camera.getBoolean("reverseRotation"));
       if (keep.rotationSensitivity)
         currentCamera.setRotationSensitivity(oldCamera.getRotationSensitivity());
       else if (camera.has("rotationSensitivity"))
         currentCamera.setRotationSensitivity((float) camera.getDouble("rotationSensitivity"));
       if (mInitialPitch != PLConstants.kFloatUndefinedValue) pitch = mInitialPitch;
       else if (keep.vLookAt) pitch = oldCamera.getLookAtRotation().pitch;
       else if (camera.has("vLookAt")) pitch = (float) camera.getDouble("vLookAt");
       if (mInitialYaw != PLConstants.kFloatUndefinedValue) yaw = mInitialYaw;
       else if (keep.hLookAt) yaw = oldCamera.getLookAtRotation().yaw;
       else if (camera.has("hLookAt")) yaw = (float) camera.getDouble("hLookAt");
       currentCamera.setInitialLookAt(pitch, yaw);
       currentCamera.lookAt(pitch, yaw);
       if (keep.zoomLevels) currentCamera.setZoomLevels(oldCamera.getZoomLevels());
       else if (camera.has("zoomLevels")) currentCamera.setZoomLevels(camera.getInt("zoomLevels"));
       if (keep.fovMin) currentCamera.setFovMin(oldCamera.getFovMin());
       else if (camera.has("fovMin")) currentCamera.setFovMin((float) camera.getDouble("fovMin"));
       if (keep.fovMax) currentCamera.setFovMax(oldCamera.getFovMax());
       else if (camera.has("fovMax")) currentCamera.setFovMax((float) camera.getDouble("fovMax"));
       if (keep.fovSensitivity) currentCamera.setFovSensitivity(oldCamera.getFovSensitivity());
       else if (camera.has("fovSensitivity"))
         currentCamera.setFovSensitivity((float) camera.getDouble("fovSensitivity"));
       if (keep.fov) currentCamera.setFov(oldCamera.getFov());
       else if (camera.has("fov")) currentCamera.setFov((float) camera.getDouble("fov"));
       else if (camera.has("fovFactor"))
         currentCamera.setFovFactor((float) camera.getDouble("fovFactor"));
       else if (camera.has("zoomFactor"))
         currentCamera.setZoomFactor((float) camera.getDouble("zoomFactor"));
       else if (camera.has("zoomLevel")) currentCamera.setZoomLevel(camera.getInt("zoomLevel"));
     }
   } catch (Throwable e) {
     this.didError(e);
     return false;
   }
   return true;
 }
  protected void parseJSON(byte[] jsonData) {
    try {
      mJSON = new JSONObject(new String(jsonData, "utf-8"));
      String urlBase = mJSON.getString("urlBase").trim();
      if (urlBase == null) throw new RuntimeException("urlBase property not exists");
      else if (!this.isHTTPURL(urlBase)
          && !urlBase.startsWith("res://")
          && !urlBase.startsWith("file://"))
        throw new RuntimeException("urlBase property is wrong");
      String type = mJSON.getString("type").trim();
      final PLIPanorama panorama;
      PLPanoramaType panoramaType = PLPanoramaType.PLPanoramaTypeUnknow;
      if (type != null) {
        if (type.equals("spherical")) {
          panoramaType = PLPanoramaType.PLPanoramaTypeSpherical;
          panorama = new PLSphericalPanorama();
        } else if (type.equals("spherical2")) {
          panoramaType = PLPanoramaType.PLPanoramaTypeSpherical2;
          panorama = new PLSpherical2Panorama();
        } else if (type.equals("cubic")) {
          panoramaType = PLPanoramaType.PLPanoramaTypeCubic;
          panorama = new PLCubicPanorama();
        } else if (type.equals("cylindrical")) {
          panoramaType = PLPanoramaType.PLPanoramaTypeCylindrical;
          panorama = new PLCylindricalPanorama();
        } else throw new RuntimeException("Panorama type is wrong");
      } else throw new RuntimeException("type property not exists");
      PLTextureColorFormat colorFormat = PLTextureColorFormat.PLTextureColorFormatRGBA8888;
      if (mJSON.has("imageColorFormat")) {
        String imageColorFormat = mJSON.getString("imageColorFormat").trim().toUpperCase(Locale.US);
        if (imageColorFormat.equals("RGB565"))
          colorFormat = PLTextureColorFormat.PLTextureColorFormatRGB565;
        else if (imageColorFormat.equals("RGBA4444"))
          colorFormat = PLTextureColorFormat.PLTextureColorFormatRGBA4444;
      }
      if (panoramaType == PLPanoramaType.PLPanoramaTypeCylindrical && mJSON.has("height"))
        ((PLCylindricalPanorama) panorama).setHeight((float) mJSON.getDouble("height"));
      if (mJSON.has("divisions") && panorama instanceof PLIQuadricPanorama) {
        JSONObject divisions = mJSON.getJSONObject("divisions");
        if (divisions != null) {
          PLIQuadricPanorama quadricPanorama = (PLIQuadricPanorama) panorama;
          if (divisions.has("preview")) quadricPanorama.setPreviewDivs(divisions.getInt("preview"));
          if (divisions.has("panorama")) quadricPanorama.setDivs(divisions.getInt("panorama"));
        }
      }
      PLIPanorama oldPanorama = mView.getPanorama();
      mKeepParameters =
          (oldPanorama != null && !(oldPanorama instanceof PLBlankPanorama) && mJSON.has("keep")
              ? PLViewParameterType.checkViewParametersWithStringMask(mJSON.getString("keep"))
              : PLViewParameterType.checkViewParametersWithMask(
                  PLViewParameterType.PLViewParameterTypeNone));
      if (!mKeepParameters.reset && mJSON.has("reset")) {
        JSONObject reset = mJSON.getJSONObject("reset");
        if (reset != null) {
          if (reset.has("enabled")) mView.setResetEnabled(reset.getBoolean("enabled"));
          if (reset.has("numberOfTouches"))
            mView.setNumberOfTouchesForReset(reset.getInt("numberOfTouches"));
          if (reset.has("shake")) {
            JSONObject shake = reset.getJSONObject("shake");
            if (shake != null) {
              if (shake.has("enabled")) mView.setShakeResetEnabled(shake.getBoolean("enabled"));
              if (shake.has("threshold"))
                mView.setShakeThreshold((float) shake.getDouble("threshold"));
            }
          }
        }
      }
      if (!mKeepParameters.scrolling && mJSON.has("scrolling")) {
        JSONObject scrolling = mJSON.getJSONObject("scrolling");
        if (scrolling != null) {
          if (scrolling.has("enabled")) mView.setScrollingEnabled(scrolling.getBoolean("enabled"));
          if (scrolling.has("minDistanceToEnableScrolling"))
            mView.setMinDistanceToEnableScrolling(scrolling.getInt("minDistanceToEnableScrolling"));
        }
      }
      if (!mKeepParameters.inertia && mJSON.has("inertia")) {
        JSONObject inertia = mJSON.getJSONObject("inertia");
        if (inertia != null) {
          if (inertia.has("enabled")) mView.setInertiaEnabled(inertia.getBoolean("enabled"));
          if (inertia.has("interval"))
            mView.setInertiaInterval((float) inertia.getDouble("interval"));
        }
      }
      if (!mKeepParameters.accelerometer && mJSON.has("accelerometer")) {
        JSONObject accelerometer = mJSON.getJSONObject("accelerometer");
        if (accelerometer != null) {
          if (accelerometer.has("enabled"))
            mView.setAccelerometerEnabled(accelerometer.getBoolean("enabled"));
          if (accelerometer.has("interval"))
            mView.setAccelerometerInterval((float) accelerometer.getDouble("interval"));
          if (accelerometer.has("sensitivity"))
            mView.setAccelerometerSensitivity((float) accelerometer.getDouble("sensitivity"));
          if (accelerometer.has("leftRightEnabled"))
            mView.setAccelerometerLeftRightEnabled(accelerometer.getBoolean("leftRightEnabled"));
          if (accelerometer.has("upDownEnabled"))
            mView.setAccelerometerUpDownEnabled(accelerometer.getBoolean("upDownEnabled"));
        }
      }
      boolean hasPreviewImage = false;
      JSONObject images = mJSON.getJSONObject("images");
      if (images != null) {
        if (images.has("preview")) {
          String previewURL = this.buildURL(images.getString("preview"), urlBase);
          if (this.isHTTPURL(previewURL)) {
            byte[] previewData = new PLHTTPFileDownloader(previewURL).download();
            if (previewData != null) {
              panorama.setPreviewImage(new PLImage(previewData));
              hasPreviewImage = true;
            }
          } else {
            PLIImage previewImage = this.getLocalImage(previewURL, colorFormat);
            if (previewImage != null) {
              panorama.setPreviewImage(previewImage);
              hasPreviewImage = true;
            }
          }
        }
        if (mHotspotTextures.size() > 0) mHotspotTextures.clear();
        JSONArray hotspots = mJSON.getJSONArray("hotspots");
        if (hotspots != null) {
          for (int i = 0, hotspotsCount = hotspots.length(); i < hotspotsCount; i++) {
            JSONObject hotspot = hotspots.getJSONObject(i);
            if (hotspot != null) {
              if (hotspot.has("image")) {
                long identifier = (hotspot.has("id") ? hotspot.getLong("id") : -1);
                float atv = (hotspot.has("atv") ? (float) hotspot.getDouble("atv") : 0.0f);
                float ath = (hotspot.has("ath") ? (float) hotspot.getDouble("ath") : 0.0f);
                float width =
                    (hotspot.has("width")
                        ? (float) hotspot.getDouble("width")
                        : PLConstants.kDefaultHotspotSize);
                float height =
                    (hotspot.has("height")
                        ? (float) hotspot.getDouble("height")
                        : PLConstants.kDefaultHotspotSize);
                PLIHotspot currentHotspot = new PLHotspot(identifier, atv, ath, width, height);
                if (hotspot.has("alpha")) {
                  currentHotspot.setDefaultAlpha((float) hotspot.getDouble("alpha"));
                  currentHotspot.setAlpha(currentHotspot.getDefaultAlpha());
                }
                if (hotspot.has("overAlpha")) {
                  currentHotspot.setDefaultOverAlpha((float) hotspot.getDouble("overAlpha"));
                  currentHotspot.setOverAlpha(currentHotspot.getDefaultOverAlpha());
                }
                if (hotspot.has("onClick")) currentHotspot.setOnClick(hotspot.getString("onClick"));
                this.loadHotspotTexture(
                    currentHotspot, hotspot.getString("image"), urlBase, colorFormat);
                panorama.addHotspot(currentHotspot);
              }
            }
          }
          mHotspotTextures.clear();
        }
        if (panoramaType == PLPanoramaType.PLPanoramaTypeCubic) {
          PLCubicPanorama cubicPanorama = (PLCubicPanorama) panorama;
          this.loadCubicPanoramaImage(
              cubicPanorama,
              PLCubeFaceOrientation.PLCubeFaceOrientationFront,
              images,
              "front",
              urlBase,
              hasPreviewImage,
              colorFormat);
          this.loadCubicPanoramaImage(
              cubicPanorama,
              PLCubeFaceOrientation.PLCubeFaceOrientationBack,
              images,
              "back",
              urlBase,
              hasPreviewImage,
              colorFormat);
          this.loadCubicPanoramaImage(
              cubicPanorama,
              PLCubeFaceOrientation.PLCubeFaceOrientationLeft,
              images,
              "left",
              urlBase,
              hasPreviewImage,
              colorFormat);
          this.loadCubicPanoramaImage(
              cubicPanorama,
              PLCubeFaceOrientation.PLCubeFaceOrientationRight,
              images,
              "right",
              urlBase,
              hasPreviewImage,
              colorFormat);
          this.loadCubicPanoramaImage(
              cubicPanorama,
              PLCubeFaceOrientation.PLCubeFaceOrientationUp,
              images,
              "up",
              urlBase,
              hasPreviewImage,
              colorFormat);
          this.loadCubicPanoramaImage(
              cubicPanorama,
              PLCubeFaceOrientation.PLCubeFaceOrientationDown,
              images,
              "down",
              urlBase,
              hasPreviewImage,
              colorFormat);
        } else {
          if (images.has("image")) {
            String imageURL = this.buildURL(images.getString("image"), urlBase);
            if (this.isHTTPURL(imageURL))
              mView
                  .getDownloadManager()
                  .add(
                      new PLHTTPFileDownloader(
                          imageURL,
                          new PLPanoramaImageFileDownloaderListener(panorama, colorFormat)));
            else if (panoramaType == PLPanoramaType.PLPanoramaTypeSpherical2)
              ((PLSpherical2Panorama) panorama).setImage(this.getLocalImage(imageURL, colorFormat));
            else if (panorama instanceof PLIQuadricPanorama)
              ((PLIQuadricPanorama) panorama)
                  .setImage(this.getLocalImageAsynchronously(imageURL, colorFormat));
          } else if (!hasPreviewImage)
            throw new RuntimeException("images.image and images.preview properties not exist");
        }
        if (images.has("preload")) mIsPreloadingImages = images.getBoolean("preload");
      } else throw new RuntimeException("images property not exists");
      if (mIsPreloadingImages) mView.getDownloadManager().start();
      mView
          .getActivity()
          .runOnUiThread(
              new Runnable() {
                @Override
                public void run() {
                  mView.reset(false);
                  if (mTransition != null && mView.getPanorama() != null) {
                    mTransition
                        .getListeners()
                        .add(
                            new PLTransitionListener() {
                              @Override
                              public boolean isRemovableListener() {
                                return true;
                              }

                              @Override
                              public void didBeginTransition(PLITransition transition) {
                                synchronized (transition) {
                                  parseCameraJSON(transition.getNewPanorama());
                                }
                              }

                              @Override
                              public void didProcessTransition(
                                  PLITransition transition, int progressPercentage) {}

                              @Override
                              public void didStopTransition(
                                  PLITransition transition, int progressPercentage) {
                                if (parseSensorialRotationJSON()) {
                                  mView.getDownloadManager().removeAll();
                                  didStop(true);
                                }
                              }

                              @Override
                              public void didEndTransition(PLITransition transition) {
                                if (parseSensorialRotationJSON()) {
                                  if (!mIsPreloadingImages) mView.getDownloadManager().start();
                                  didComplete(true);
                                }
                              }
                            });
                    mView.startTransition(mTransition, panorama);
                  } else {
                    if (parseCameraJSON(panorama)) {
                      mView.setPanorama(panorama);
                      if (parseSensorialRotationJSON()) {
                        if (!mIsPreloadingImages) mView.getDownloadManager().start();
                        didComplete(false);
                      }
                    }
                  }
                }
              });
    } catch (Throwable e) {
      this.didError(e);
    }
  }
 protected PLIImage getLocalImage(String url, PLTextureColorFormat colorFormat) {
   Bitmap bitmap =
       PLUtils.getBitmap(mView.getActivity().getApplicationContext(), url, colorFormat);
   return (bitmap != null ? new PLImage(bitmap, false) : null);
 }