PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 9.0.2
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v9.0.2
9.1.3 9.1.2 9.1.1 9.1.0 9.0.3 9.0.2 9.0.1 9.0.0 8.5.79 8.5.78 8.5.77 8.5.76 8.5.75 8.5.74 8.5.73 8.5.72 8.5.71 8.5.70 8.5.69 8.5.68 8.5.35 8.5.36 8.5.37 8.5.38 8.5.39 All 222 releases
wpvr / legacy / wpvr.php

wpvr.php in WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress 9.0.2, at legacy/wpvr.php

4,366 lines 202.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Legacy bootstrap for WP VR plugin
3 // This file is a direct copy of the original wpvr.php before architecture migration.
4 // Do not edit legacy logic here; only update if the legacy code itself changes.
5
6 if (!defined('WPINC')) {
7 die;
8 }
9
10 require WPVR_PLUGIN_LEGACY_DIR_PATH . 'elementor/elementor.php';
11 if ( file_exists( dirname( WPVR_PLUGIN_LEGACY_DIR_PATH ) . '/vendor/autoload.php' ) ) {
12 require_once dirname( WPVR_PLUGIN_LEGACY_DIR_PATH ) . '/vendor/autoload.php';
13 } elseif ( file_exists( WPVR_PLUGIN_LEGACY_DIR_PATH . 'vendor/autoload.php' ) ) {
14 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'vendor/autoload.php';
15 }
16
17 if ( wp_get_theme('bricks')->exists() && 'bricks' === get_template()) {
18 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'bricks/bricks.php';
19 }
20
21
22 /**
23 * Currently plugin version.
24 * Start at version 1.0.0 and use SemVer - https://semver.org
25 * Rename this for your plugin and update it as you release new versions.
26 */
27 define( 'WPVR_WEBHOOK_URL', sanitize_url( 'https://rextheme.com/?mailmint=1&route=webhook&topic=contact&hash=bbd19901-6d42-4ae5-a7a8-01eb1013c553' ) );
28 if ( ! defined( 'WPVR_TELEMETRY_API_KEY' ) ) {
29 define( 'WPVR_TELEMETRY_API_KEY', 'phc_amk3VQz1P5ZqZOMRRoWM1B41QMFpf3hu8pg7yRfzSXW' );
30 }
31 if ( ! defined( 'WPVR_TELEMETRY_API_SECRET' ) ) {
32 define( 'WPVR_TELEMETRY_API_SECRET', 'sec_dfb2ab8e84391ae7a0f9' );
33 }
34 if ( ! defined( 'WPVR_TELEMETRY_HOST' ) ) {
35 define( 'WPVR_TELEMETRY_HOST', 'https://eu.i.posthog.com' );
36 }
37
38
39 if ( ! function_exists( 'activate_wpvr' ) ) {
40 /**
41 * The code that runs during plugin activation.
42 * This action is documented in includes/class-wpvr-activator.php
43 */
44 function activate_wpvr()
45 {
46 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'includes/class-wpvr-activator.php';
47 Wpvr_Activator::activate();
48
49 // Trigger plugin activation tracking
50 do_action( 'wpvr_plugin_activated' );
51 }
52 }
53
54 if ( ! function_exists( 'deactivate_wpvr' ) ) {
55 /**
56 * The code that runs during plugin deactivation.
57 * This action is documented in includes/class-wpvr-deactivator.php
58 */
59 function deactivate_wpvr()
60 {
61 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'includes/class-wpvr-deactivator.php';
62 Wpvr_Deactivator::deactivate();
63
64 // Trigger plugin deactivation tracking
65 do_action( 'wpvr_plugin_deactivated' );
66 }
67 }
68
69 register_activation_hook( WPVR_FILE, 'activate_wpvr' );
70 register_deactivation_hook( WPVR_FILE, 'deactivate_wpvr' );
71
72 /**
73 * The core plugin class that is used to define internationalization,
74 * admin-specific hooks, and public-facing site hooks.
75 */
76 require WPVR_PLUGIN_LEGACY_DIR_PATH . 'includes/class-wpvr.php';
77
78 // Include banner classes
79 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'admin/classes/class-wpvr-occasion-banner.php';
80 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'admin/classes/class-wpvr-sells-notification-bar.php';
81 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'admin/classes/class-wpvr-first-tour-banner.php';
82 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'admin/classes/class-wpvr-onboarding-notice.php';
83 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'admin/classes/class-wpvr-new-user-tour.php';
84
85 if ( defined( 'WPB_VC_VERSION' ) ) {
86 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'builders/wpbakery/wpvr-loader.php';
87 if ( class_exists( 'Vc_Manager' ) ) {
88 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'builders/wpbakery/wpvr-element.php';
89 }
90 }
91
92
93 /**
94 * Begins execution of the plugin.
95 *
96 * Since everything within the plugin is registered via hooks,
97 * then kicking off the plugin from this point in the file does
98 * not affect the page life cycle.
99 *
100 * @since 7.3.6
101 */
102 function run_wpvr()
103 {
104
105 $plugin = new Wpvr();
106 $plugin->run();
107 // new Tracker();
108
109 // black friday banner class initialization
110 // new WPVR_Special_Occasion_Banner(
111 // 'halloween_deal_2025',
112 // '2025-10-01 00:00:01',
113 // '2025-11-05 23:59:59'
114 // );
115
116 if (!defined('WPVR_PRO_VERSION') && 'no' === get_option('wpvr_sell_eid_ul_fitr_2026_notification_bar', 'no')) {
117 new WPVR_Notification_Bar(
118 'Eid_Ul_Fitr_2026',
119 '2026-03-16 00:00:00',
120 '2026-03-24 23:59:59'
121 );
122 }
123
124 // Initialize first tour banner
125 new WPVR_First_Tour_Banner();
126
127 // Initialize listing-page onboarding notice ("Remind me later" flow)
128 new WPVR_Onboarding_Notice();
129
130 // Auto-launch guided tour for truly-new users on the Add New Tour page.
131 new WPVR_New_User_Tour();
132
133 // Pro preview banner (shown via JS when free user toggles Advanced Controls)
134 if (!defined('WPVR_PRO_VERSION')) {
135 add_action('admin_notices', 'wpvr_render_pro_preview_banner', 11);
136 }
137
138 }
139 run_wpvr();
140
141 /**
142 * Render Pro preview banner as admin notice.
143 * Hidden by default; shown via JS when free user toggles Advanced Controls.
144 *
145 * @since 8.5.44
146 */
147 function wpvr_render_pro_preview_banner() {
148 $screen = get_current_screen();
149 if (!$screen || $screen->id !== 'wpvr_item') {
150 return;
151 }
152 ?>
153 <div class="wpvr-pro-preview-banner" id="wpvr-pro-preview-banner" style="display:none;">
154 <div class="wpvr-pro-preview-banner__left">
155 <span class="wpvr-pro-preview-banner__icon">
156 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zm0 12.5c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>
157 </span>
158 <span class="wpvr-pro-preview-banner__text"><?php esc_html_e('You are previewing Pro features in action.', 'wpvr'); ?></span>
159 </div>
160 <div class="wpvr-pro-preview-banner__pricing">
161 <div class="wpvr-pro-preview-banner__pricing-top">
162 <span class="wpvr-pro-preview-banner__old-price"><?php esc_html_e('Normally $99.99/year', 'wpvr'); ?></span>
163 <span class="wpvr-pro-preview-banner__badge"><?php esc_html_e('SAVE 20%', 'wpvr'); ?></span>
164 </div>
165 <span class="wpvr-pro-preview-banner__new-price"><?php esc_html_e('Starting at $79.99/year', 'wpvr'); ?></span>
166 </div>
167 <a href="<?php echo esc_url('https://rextheme.com/wpvr/wpvr-pricing/?utm_source=plugin&utm_medium=pro-preview-banner&utm_campaign=advanced-controls'); ?>" class="wpvr-pro-preview-banner__btn" target="_blank" rel="noopener noreferrer">
168 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M5 16L3 5l5.5 5L12 4l3.5 6L21 5l-2 11H5zm0 2h14v1c0 .55-.45 1-1 1H6c-.55 0-1-.45-1-1v-1z"/></svg>
169 <?php esc_html_e('Upgrade to save changes', 'wpvr'); ?>
170 </a>
171 </div>
172 <?php
173 }
174
175
176 /**
177 * Array information checker
178 *
179 * @param mixed $needle
180 * @param mixed $haystack
181 * @param bool $strict
182 *
183 * @return bool
184 * @since 7.3.6
185 */
186 function wpvr_in_array_r($needle, $haystack, $strict = false)
187 {
188 foreach ($haystack as $item) {
189 if ((($strict ? $item === $needle : $item == $needle)) || is_array($item) && wpvr_in_array_r($needle, $item, $strict)) {
190 return true;
191 }
192 }
193 return false;
194 }
195
196 if ( ! function_exists( 'wpvr_parse_custom_control' ) ) {
197 /**
198 * Normalize custom control data into an array.
199 *
200 * @param mixed $custom_control Raw custom control value from meta.
201 *
202 * @return array
203 * @since 8.5.63
204 */
205 function wpvr_parse_custom_control( $custom_control ) {
206 if ( is_array( $custom_control ) ) {
207 return $custom_control;
208 }
209
210 if ( is_object( $custom_control ) ) {
211 return (array) $custom_control;
212 }
213
214 if ( ! is_string( $custom_control ) || '' === trim( $custom_control ) ) {
215 return array();
216 }
217
218 $unserialized = maybe_unserialize( $custom_control );
219 if ( is_array( $unserialized ) ) {
220 return $unserialized;
221 }
222
223 $decoded = json_decode( wp_unslash( $custom_control ), true );
224 if ( is_array( $decoded ) ) {
225 return $decoded;
226 }
227
228 return array();
229 }
230 }
231
232 if ( ! function_exists( 'wpvr_restore_modern_layout_default_controls' ) ) {
233 /**
234 * Restore Pannellum's default controls after WP VR Pro adds Modern layout CSS.
235 *
236 * The Modern layout stylesheet is added by WP VR Pro at filter priority 10.
237 * Running at priority 20 keeps this compatibility rule in the Free plugin while
238 * ensuring it is output after the Pro stylesheet, regardless of plugin load order.
239 *
240 * @param string $html Generated tour HTML.
241 * @param array $postdata Saved tour settings.
242 * @param int $id Tour post ID.
243 *
244 * @return string
245 * @since 9.0.0
246 */
247 function wpvr_restore_modern_layout_default_controls( $html, $postdata, $id ) {
248 $tour_layout = is_array( $postdata['tourLayout'] ?? null )
249 ? ( $postdata['tourLayout']['layout'] ?? 'default' )
250 : ( $postdata['tourLayout'] ?? 'default' );
251
252 if (
253 ! defined( 'WPVR_PRO_VERSION' )
254 || 'layout1' !== $tour_layout
255 || empty( $postdata['showControls'] )
256 ) {
257 return $html;
258 }
259
260 $custom_control = wp_parse_args(
261 wpvr_parse_custom_control( $postdata['customcontrol'] ?? array() ),
262 array(
263 'panupSwitch' => 'off',
264 'panDownSwitch' => 'off',
265 'panLeftSwitch' => 'off',
266 'panRightSwitch' => 'off',
267 'panZoomInSwitch' => 'off',
268 'panZoomOutSwitch' => 'off',
269 'panFullscreenSwitch' => 'off',
270 'gyroscopeSwitch' => 'off',
271 'backToHomeSwitch' => 'off',
272 )
273 );
274
275 $gyro_enabled = isset( $postdata['gyro'] )
276 && in_array( $postdata['gyro'], array( true, 1, '1', 'on' ), true );
277 $gyro_button_enabled = function_exists( 'wpvr_isMobileDevice' )
278 && wpvr_isMobileDevice()
279 && $gyro_enabled
280 && 'on' === $custom_control['gyroscopeSwitch'];
281
282 $custom_navigation_enabled = $gyro_button_enabled;
283 foreach (
284 array(
285 'panupSwitch',
286 'panDownSwitch',
287 'panLeftSwitch',
288 'panRightSwitch',
289 'panZoomInSwitch',
290 'panZoomOutSwitch',
291 'panFullscreenSwitch',
292 'backToHomeSwitch',
293 ) as $switch
294 ) {
295 if ( 'on' === $custom_control[ $switch ] ) {
296 $custom_navigation_enabled = true;
297 break;
298 }
299 }
300
301 if ( $custom_navigation_enabled ) {
302 return $html;
303 }
304
305 $pano_id = 'pano' . absint( $id );
306 $sprites_url = esc_url( WPVR_PLUGIN_PUBLIC_DIR_URL . 'lib/pannellum/src/css/img/sprites.svg' );
307
308 $html .= '<style id="wpvr-modern-default-controls-' . esc_attr( $id ) . '">
309 #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-zoom-controls.pnlm-controls {
310 display: block !important;
311 width: 28px !important;
312 height: 52px !important;
313 right: auto !important;
314 bottom: auto !important;
315 margin-top: 4px !important;
316 border: 1px solid rgba(0, 0, 0, 0.4) !important;
317 border-radius: 3px !important;
318 background-color: #fff !important;
319 background-image: none !important;
320 background-position: 0 0 !important;
321 background-repeat: repeat !important;
322 background-size: auto !important;
323 }
324
325 #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-fullscreen-toggle-button {
326 display: block !important;
327 width: 28px !important;
328 height: 26px !important;
329 right: auto !important;
330 bottom: auto !important;
331 margin-top: 4px !important;
332 border: 1px solid rgba(0, 0, 0, 0.4) !important;
333 border-radius: 3px !important;
334 background-color: #fff !important;
335 background-image: url("' . $sprites_url . '") !important;
336 background-repeat: repeat !important;
337 background-size: auto !important;
338 }
339
340 #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-fullscreen-toggle-button-inactive {
341 background-position: 1px -52px !important;
342 }
343
344 #et-boc .et-l #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-fullscreen-toggle-button-inactive {
345 background-position: -1px -53px !important;
346 }
347
348 #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-fullscreen-toggle-button-active {
349 background-position: 0 -78px !important;
350 }
351
352 #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-control:hover {
353 background-color: #f8f8f8 !important;
354 }
355 </style>';
356
357 return $html;
358 }
359 }
360
361 add_filter( 'wpvr_generate_tour_layout_html', 'wpvr_restore_modern_layout_default_controls', 20, 3 );
362
363 if ( ! function_exists( 'wpvr_render_scene_info_row' ) ) {
364 /**
365 * Keep scene title and author metadata aligned for every tour layout.
366 *
367 * WP VR Pro can replace the Pannellum asset registered by the Free plugin and
368 * adds Modern layout CSS at priority 10. This late, tour-scoped layer keeps
369 * both Pannellum copies and both layouts consistent without modifying Pro.
370 *
371 * @param string $html Generated tour HTML.
372 * @param array $postdata Saved tour settings.
373 * @param int $id Tour post ID.
374 *
375 * @return string
376 * @since 9.0.0
377 */
378 function wpvr_render_scene_info_row( $html, $postdata, $id ) {
379 $pano_id = 'pano' . absint( $id );
380 $pano_id_json = wp_json_encode( $pano_id );
381 $by_label = wp_json_encode( __( 'By', 'wpvr' ) );
382 $tour_layout = is_array( $postdata['tourLayout'] ?? null )
383 ? ( $postdata['tourLayout']['layout'] ?? 'default' )
384 : ( $postdata['tourLayout'] ?? 'default' );
385 $is_classic_layout = wp_json_encode( 'layout1' !== $tour_layout );
386
387 $html .= '<style id="wpvr-scene-info-' . esc_attr( $id ) . '">
388 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row {
389 display: flex !important;
390 align-items: center !important;
391 justify-content: center !important;
392 gap: 10px !important;
393 box-sizing: border-box !important;
394 min-width: 0 !important;
395 overflow: hidden !important;
396 text-align: center !important;
397 z-index: 2147483647 !important;
398 -webkit-transform: translateZ(10000px) !important;
399 transform: translateZ(10000px) !important;
400 }
401
402 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row .pnlm-title-box {
403 flex: 0 1 auto !important;
404 min-width: 0 !important;
405 max-width: calc(70% - 5px) !important;
406 width: auto !important;
407 margin: 0 !important;
408 padding: 0 !important;
409 display: block !important;
410 overflow: hidden !important;
411 text-overflow: ellipsis !important;
412 white-space: nowrap !important;
413 }
414
415 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row .pnlm-author-box {
416 flex: 0 1 auto !important;
417 min-width: 0 !important;
418 max-width: calc(30% - 5px) !important;
419 margin: 0 !important;
420 border-left: 1px solid rgba(255, 255, 255, 0.45) !important;
421 padding: 0 0 0 10px !important;
422 display: block !important;
423 overflow: hidden !important;
424 line-height: 1.2 !important;
425 text-overflow: ellipsis !important;
426 white-space: nowrap !important;
427 }
428
429 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info .wpvr-author-label {
430 flex: none !important;
431 margin-right: 4px !important;
432 font-size: 10px !important;
433 font-weight: 700 !important;
434 letter-spacing: 0.06em !important;
435 opacity: 0.8 !important;
436 text-transform: uppercase !important;
437 }
438
439 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info .pnlm-author-box a {
440 color: inherit !important;
441 text-decoration: underline !important;
442 text-underline-offset: 2px !important;
443 }
444
445 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-has-title:not(.wpvr-has-author) .pnlm-title-box,
446 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-has-author:not(.wpvr-has-title) .pnlm-author-box {
447 max-width: 100% !important;
448 border-left: 0 !important;
449 padding-left: 0 !important;
450 }
451
452 #' . esc_attr( $pano_id ) . '.wpvr-layout-classic.wpvr-has-scene-info .scene-gallery.wpvr-gallery--classic {
453 bottom: calc(var(--wpvr-scene-info-height, 34px) + 8px) !important;
454 }
455
456 #' . esc_attr( $pano_id ) . '.wpvr-layout-classic.wpvr-has-scene-info .vrgcontrols {
457 bottom: calc(var(--wpvr-scene-info-height, 34px) + 4px) !important;
458 }
459
460 #' . esc_attr( $pano_id ) . '.wpvr-layout-classic.wpvr-has-scene-info .wpvr_slider_nav {
461 bottom: calc(var(--wpvr-scene-info-height, 34px) + 15px) !important;
462 }
463
464 #' . esc_attr( $pano_id ) . '.wpvr-layout-classic.wpvr-has-scene-info .controls {
465 bottom: calc(var(--wpvr-scene-info-height, 34px) + 6px) !important;
466 }
467
468 @media (max-width: 767px) {
469 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row {
470 gap: 7px !important;
471 padding-right: 10px !important;
472 padding-left: 10px !important;
473 }
474
475 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row .pnlm-title-box {
476 max-width: calc(65% - 4px) !important;
477 }
478
479 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row .pnlm-author-box {
480 max-width: calc(35% - 4px) !important;
481 padding-left: 7px !important;
482 }
483 }
484 </style>
485 <script id="wpvr-scene-info-script-' . esc_attr( $id ) . '">
486 (function () {
487 var pano = document.getElementById(' . $pano_id_json . ');
488 var byLabel = ' . $by_label . ';
489
490 if (!pano || !window.MutationObserver) {
491 return;
492 }
493
494 function addAuthorLabel(author) {
495 if (!author || !author.textContent.trim() || author.querySelector(".wpvr-author-label")) {
496 return;
497 }
498
499 var firstNode = author.firstChild;
500 if (firstNode && firstNode.nodeType === 3) {
501 var prefix = byLabel + " ";
502 if (firstNode.nodeValue.indexOf(prefix) === 0) {
503 firstNode.nodeValue = firstNode.nodeValue.slice(prefix.length);
504 }
505 }
506
507 var label = document.createElement("span");
508 label.className = "wpvr-author-label";
509 label.textContent = byLabel;
510 author.insertBefore(label, author.firstChild);
511 }
512
513 function syncSceneInfo() {
514 var info = pano.querySelector(".pnlm-panorama-info");
515 if (!info) {
516 return;
517 }
518
519 // Keep the Pannellum full-screen drag layer in its original
520 // stacking order so hotspots remain clickable. Promote only
521 // the compact metadata bar to the tour root instead.
522 if (info.parentNode !== pano) {
523 pano.appendChild(info);
524 }
525
526 var title = info.querySelector(".pnlm-title-box");
527 var author = info.querySelector(".pnlm-author-box");
528 var hasTitle = !!(title && title.textContent.trim());
529 var hasAuthor = !!(author && author.textContent.trim());
530
531 if (hasTitle) {
532 title.setAttribute("title", title.textContent.trim());
533 } else if (title) {
534 title.removeAttribute("title");
535 }
536
537 if (hasAuthor) {
538 addAuthorLabel(author);
539 var authorName = author.textContent.replace(byLabel, "").trim();
540 author.setAttribute("aria-label", byLabel + " " + authorName);
541 author.setAttribute("title", authorName);
542 } else if (author) {
543 author.removeAttribute("aria-label");
544 author.removeAttribute("title");
545 }
546
547 info.classList.toggle("wpvr-scene-info-row", hasTitle || hasAuthor);
548 info.classList.toggle("wpvr-has-title", hasTitle);
549 info.classList.toggle("wpvr-has-author", hasAuthor);
550 info.style.display = hasTitle || hasAuthor ? "flex" : "none";
551
552 var hasSceneInfo = hasTitle || hasAuthor;
553 var isClassicLayout = ' . $is_classic_layout . ';
554 pano.classList.toggle("wpvr-has-scene-info", hasSceneInfo);
555 pano.classList.toggle("wpvr-layout-classic", isClassicLayout);
556
557 if (hasSceneInfo) {
558 pano.style.setProperty("--wpvr-scene-info-height", info.offsetHeight + "px");
559 } else {
560 pano.style.removeProperty("--wpvr-scene-info-height");
561 }
562 }
563
564 var observer = new MutationObserver(syncSceneInfo);
565 observer.observe(pano, { childList: true, subtree: true, characterData: true });
566 syncSceneInfo();
567 }());
568 </script>';
569
570 return $html;
571 }
572 }
573
574 add_filter( 'wpvr_generate_tour_layout_html', 'wpvr_render_scene_info_row', 30, 3 );
575
576 if ( ! function_exists( 'wpvr_render_explainer_button' ) ) {
577 /**
578 * Render the WPVR explainer button independently.
579 *
580 * @param array|null $custom_control
581 * @param array $postdata
582 * @param bool $is_pro
583 * @param bool $autoload
584 * @param string $explainer_right
585 * @param int|string $id
586 *
587 * @return string
588 * @since 8.5.63
589 */
590 function wpvr_render_explainer_button( $custom_control, $postdata, $is_pro, $autoload, $explainer_right, $id ) {
591 $html = '';
592 $explainer_enabled = isset( $postdata['explainerSwitch'] )
593 && in_array( $postdata['explainerSwitch'], array( true, 1, '1', 'on' ), true );
594 $explainer_icon = 'fa fa-video';
595 $explainer_color = '#f7fffb';
596
597 if ( isset( $custom_control ) ) {
598 $explainer_icon = isset( $custom_control['explainerIcon'] ) ? $custom_control['explainerIcon'] : $explainer_icon;
599 $explainer_color = isset( $custom_control['explainerColor'] ) ? $custom_control['explainerColor'] : $explainer_color;
600 } elseif ( isset( $postdata['customcontrol'] ) ) {
601 $raw_control = wpvr_parse_custom_control( $postdata['customcontrol'] );
602 $explainer_icon = isset( $raw_control['explainerIcon'] ) ? $raw_control['explainerIcon'] : $explainer_icon;
603 $explainer_color = isset( $raw_control['explainerColor'] ) ? $raw_control['explainerColor'] : $explainer_color;
604 }
605
606 $pro_license_status = get_option( 'wpvr_edd_license_status' );
607 if ( $explainer_enabled && $pro_license_status === 'valid' && $is_pro ) {
608 $explainer_style = empty( $postdata['explainerContent'] )
609 ? 'pointer-events: none; opacity: 0.5;'
610 : '';
611
612 // Initial display:none to prevent flash for non-autoload tours.
613 $initial_display = ! $autoload ? 'display:none; ' : '';
614
615 $html .= '<div class="explainer_button" id="explainer_button_' . esc_attr( $id ) . '" style="' . $initial_display . 'right:' . esc_attr( $explainer_right ) . '; ' . esc_attr( $explainer_style ) . '">';
616 $html .= '<div class="ctrl" id="explainer_target_' . esc_attr( $id ) . '"><i class="' . esc_attr( $explainer_icon ) . '" style="color:' . esc_attr( $explainer_color ) . ';"></i></div>';
617 $html .= '</div>';
618 }
619
620 return $html;
621 }
622 }
623
624 // Linno telemetry integration
625 function wpvr_block()
626 {
627 wp_register_script(
628 'wpvr-block',
629 plugins_url('build/index.build.js', __FILE__),
630 array('wp-blocks', 'wp-element', 'wp-components', 'wp-editor')
631 );
632
633 if (is_admin()) {
634 wp_enqueue_style(
635 'gutyblocks/guty-block',
636 plugins_url('src/view.css', __FILE__),
637 array()
638 );
639 }
640
641
642 if (function_exists('register_block_type')) {
643 register_block_type('wpvr/wpvr-block', array(
644 'attributes' => array(
645 'id' => array(
646 'type' => 'string',
647 'default' => '0',
648 ),
649 'width' => array(
650 'type' => 'string',
651 'default' => '600',
652 ),
653 'width_unit' => array(
654 'type' => 'string',
655 'default' => 'px',
656 ),
657 'height' => array(
658 'type' => 'string',
659 'default' => '400',
660 ),
661 'height_unit' => array(
662 'type' => 'string',
663 'default' => 'px',
664 ),
665 'mobile_height' => array(
666 'type' => 'string',
667 'default' => '300',
668 ),
669 'mobile_height_unit' => array(
670 'type' => 'string',
671 'default' => 'px',
672 ),
673 'radius' => array(
674 'type' => 'string',
675 'default' => '0',
676 ),
677 'border_width' => array(
678 'type' => 'string',
679 'default' => '0px',
680 ),
681 'border_style' => array(
682 'type' => 'string',
683 'default' => 'none',
684 ),
685 'border_color' => array(
686 'type' => 'string',
687 'default' => 'none',
688 ),
689 'radius_unit' => array(
690 'type' => 'string',
691 'default' => 'px',
692 ),
693 'content' => array(
694 'type' => 'string',
695 'source' => 'html',
696 'default' => '<script> </script>'
697 ),
698 ),
699 'editor_script' => 'wpvr-block',
700 'render_callback' => 'wpvr_block_render',
701 ));
702 }
703 }
704
705 add_action('init', 'wpvr_block');
706
707 function wpvr_block_render($attributes)
708 {
709 if ( function_exists( 'wpvr_enqueue_frontend_scripts' ) ) {
710 wpvr_enqueue_frontend_scripts( 'scene' );
711 }
712 if (isset($attributes['id'])) {
713 $id = $attributes['id'];
714 } else {
715 $id = 0;
716 }
717
718 do_action('rex_wpvr_embadded_tour', $id);
719
720 $memberpress_active = defined('MEPR_VERSION');
721 $rcp_active = is_plugin_active( 'restrict-content-pro/restrict-content-pro.php' );
722
723 if (($memberpress_active || $rcp_active ) && apply_filters('is_wpvr_pro_active', false)) {
724
725 if (!is_user_logged_in()) {
726 return esc_html__('You need to log in to access this content.', 'wpvr');
727 }
728
729 $user_id = get_current_user_id();
730 $allowed_access = false;
731
732 // Get saved membership levels from post meta
733 $allowed_membership_levels = get_post_meta($id, '_wpvr_allowed_roles_levels', true);
734 if ( isset($allowed_membership_levels) && 'none' !== $allowed_membership_levels ) {
735 if (!is_array($allowed_membership_levels)) {
736 $allowed_membership_levels = array($allowed_membership_levels);
737 }
738
739 // Check MemberPress Access
740 if ($memberpress_active) {
741 $user = new MeprUser($user_id);
742 $active_memberships = $user->active_product_subscriptions();
743 if (array_intersect($allowed_membership_levels, $active_memberships) ) {
744 $allowed_access = true;
745 }
746 }
747
748 // Check Restrict Content Pro Access
749 if ($rcp_active) {
750 $user_rcp_memberships = rcp_get_customer_memberships($user_id);
751 foreach ($user_rcp_memberships as $membership) {
752 $rcp_access_level = array(
753 $membership->get_object_id()
754 );
755 if (array_intersect($allowed_membership_levels, $rcp_access_level) ) {
756 $allowed_access = true;
757 break;
758 }
759 }
760 }
761 } else {
762 // If no membership restriction is set, allow access by default
763 $allowed_access = true;
764 }
765
766 if (!$allowed_access) {
767 return esc_html__('You do not have access to this content.', 'wpvr');
768 }
769 }
770
771
772 if (isset($attributes['width'])) {
773 $width = $attributes['width'];
774 }
775 if (isset($attributes['width_unit'])) {
776 $width_unit = $attributes['width_unit'];
777 }
778 if (isset($attributes['height'])) {
779 $height = $attributes['height'];
780 }
781 if (isset($attributes['height_unit'])) {
782 $height_unit = $attributes['height_unit'];
783 }
784 if (isset($attributes['mobile_height'])) {
785 $mobile_height = $attributes['mobile_height'];
786 }
787 if (isset($attributes['mobile_height_unit'])) {
788 $mobile_height_unit = $attributes['mobile_height_unit'];
789 }
790 if (isset($attributes['radius']) && isset($attributes['radius_unit'])) {
791 $radius = $attributes['radius'] . $attributes['radius_unit'];
792 }
793 $border_style = '';
794 if (isset($attributes['border_width'], $attributes['border_style'], $attributes['border_color'])) {
795 $border_style = $attributes['border_width'] . 'px ' . $attributes['border_style'] . ' ' . $attributes['border_color'];
796 }
797
798 if (isset($attributes['className'])) {
799 $className = $attributes['className'];
800 } else {
801 $className = '';
802 }
803 $get_post = get_post_status($id);
804 if ($get_post !== 'publish') {
805 return esc_html__('Oops! It seems like this post isn\'t published yet. Stay tuned for updates!', 'wpvr');
806 }
807 if (post_password_required($id)) {
808 return get_the_password_form();
809 }
810 $postdata = get_post_meta($id, 'panodata', true);
811 $postdata = is_array( $postdata ) ? wpvr_get_effective_panodata( $postdata ) : [];
812 $panoid = 'pano' . $id;
813 $panoid2 = 'pano2' . $id;
814 if (!isset($postdata) || empty($postdata)) {
815 return wp_kses(
816 __('Oops! It seems that you have not selected any tour yet. Please select a tour from the dropdown of WPVR block.<br>', 'wpvr'),
817 ['br' => []]
818 );
819 }
820 if (isset($postdata['streetviewdata'])) {
821 if (empty($width)) {
822 $width = '600px';
823 }
824 if (empty($height)) {
825 $height = '400px';
826 }
827 $streetviewurl = $postdata['streetviewurl'];
828 $html = '';
829 $html .= '<div class="vr-streetview ' . esc_attr( $className ) . '" style="text-align: center; max-width:100%; width:' . esc_attr( $width ) . esc_attr( $width_unit ) . '; height:' . esc_attr( $height ) . esc_attr( $height_unit ) . '; margin: 0 auto;">';
830 $html .= '<iframe src="' . esc_url( $streetviewurl ) . '" frameborder="0" style="border:0; width:100px; height:100%;" allowfullscreen=""></iframe>';
831 $html .= '</div>';
832
833 return $html;
834 }
835 $is_pro = apply_filters('is_wpvr_pro_active', false);
836
837 if (isset($postdata['vidid'])) {
838 if (empty($width)) {
839 $width = '600';
840 }
841 if (empty($height)) {
842 $height = '400';
843 }
844 $videourl = $postdata['vidurl'];
845
846 $videourl = $postdata['vidurl'];
847 $autoplay = 'off';
848 if (isset($postdata['autoplay'])) {
849 $autoplay = $postdata['autoplay'];
850 }
851 $loop = 'off';
852 if (isset($postdata['loop'])) {
853 $loop = $postdata['loop'];
854 }
855
856 if (strpos($videourl, 'youtube') > 0 || strpos($videourl, 'youtu') > 0) {
857 $explodeid = '';
858 $explodeid = explode("=", $videourl);
859 $foundid = '';
860 $muted = '&mute=1';
861
862 if ($autoplay == 'on') {
863 $autoplay = '&autoplay=1';
864 } else {
865 $autoplay = '';
866 }
867
868 if ($loop == 'on') {
869 $loop = '&loop=1';
870 } else {
871 $loop = '';
872 }
873
874 if (strpos($videourl, 'youtu') > 0) {
875 $explodeid = explode("/", $videourl);
876 $foundid = $explodeid[3] . '?' . $autoplay . $loop;
877 $expdata = $explodeid[3];
878 } else {
879 $foundid = $explodeid[1] . '?' . $autoplay . $loop;
880 $expdata = $explodeid[1];
881 }
882
883 $playlist = '&playlist=' . $expdata;
884 $playlist = str_replace("?feature=shared", "", $playlist);
885
886
887 $html = '';
888 $html .= '<div class="' . esc_attr($className) . '" style="text-align:center; max-width:100%; width:' . esc_attr($width) . esc_attr($width_unit) . '; height:' . esc_attr($height) . esc_attr($height_unit) . '; border-radius: ' . esc_attr($radius) . '; margin: 0 auto;">';
889
890 // Compatibility check script
891 $html .= '<script>
892 function wpvr_check_360_support() {
893 var support = {
894 supported: false,
895 fullySupported: false,
896 webgl: false,
897 orientation: false,
898 gyroscope: false,
899 touch: false,
900 browser: "unknown",
901 isMobile: false,
902 isIPhone: false,
903 details: []
904 };
905
906 support.isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
907 support.isIPhone = /iPhone/i.test(navigator.userAgent);
908 if (support.isMobile) support.details.push("Mobile device detected");
909 if (support.isIPhone) support.details.push("iPhone detected");
910
911 var ua = navigator.userAgent;
912 if (/^((?!chrome|android).)*safari/i.test(ua)) {
913 support.browser = "safari";
914 support.details.push("Safari browser detected");
915 } else if (ua.indexOf("Chrome") > -1) {
916 support.browser = "chrome";
917 support.details.push("Chrome browser detected");
918 } else if (ua.indexOf("Firefox") > -1) {
919 support.browser = "firefox";
920 support.details.push("Firefox browser detected");
921 } else if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1) {
922 support.browser = "ie";
923 support.details.push("Internet Explorer detected");
924 } else if (ua.indexOf("Edge") > -1 || ua.indexOf("Edg") > -1) {
925 support.browser = "edge";
926 support.details.push("Edge browser detected");
927 } else if (ua.indexOf("Opera") > -1 || ua.indexOf("OPR") > -1) {
928 support.browser = "opera";
929 support.details.push("Opera browser detected");
930 }
931
932 try {
933 var canvas = document.createElement("canvas");
934 support.webgl = !!(window.WebGLRenderingContext &&
935 (canvas.getContext("webgl") || canvas.getContext("experimental-webgl")));
936 support.details.push(support.webgl ? "WebGL supported" : "WebGL not supported");
937 } catch (e) {
938 support.webgl = false;
939 support.details.push("WebGL detection error: " + e.message);
940 }
941
942 support.orientation = !!(window.DeviceOrientationEvent);
943 support.details.push(support.orientation ? "Device Orientation API supported" : "Device Orientation API not supported");
944
945 support.gyroscope = !!window.Gyroscope;
946 support.details.push(support.gyroscope ? "Gyroscope supported" : "Gyroscope not supported");
947
948 support.touch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
949 support.details.push(support.touch ? "Touch supported" : "Touch not supported");
950
951 support.supported = support.webgl;
952 support.fullySupported = support.webgl && ((support.isMobile && support.orientation) || !support.isMobile);
953
954 if (support.browser === "safari" && support.isIPhone) {
955 support.browserWarning = "iPhone has limited support for 360 videos in browser. The experience may not be optimal.";
956 support.fullySupported = false;
957 } else if (support.browser === "ie") {
958 support.browserWarning = "Internet Explorer has limited support for 360 videos.";
959 support.fullySupported = false;
960 } else if (!support.supported) {
961 support.browserWarning = "Your browser does not support 360° videos. Use Chrome or Firefox with WebGL.";
962 }
963
964 return support;
965 }
966 </script>';
967
968 $random_id = 'video-container-' . rand(10000, 99999);
969 $html .= '<div id="' . $random_id . '-container" style="position:relative; width:100%; height:100%;">';
970
971 // Compatibility check screen (initially hidden for all, will show only for iPhone)
972 $html .= '<div id="' . $random_id . '-compatibility-check" style="position:absolute; top:0; left:0; width:100%; height:100%; display:none; flex-direction:column; justify-content:center; align-items:center; background-color:#f9f9f9; border-radius:' . esc_attr( $radius ) . ';">
973 <div style="margin-bottom:20px; text-align:center;">
974 <div class="wpvr-loading-spinner" style="border:5px solid #f3f3f3; border-top:5px solid #3498db; border-radius:50%; width:50px; height:50px; margin:0 auto 15px; animation:wpvr-spin 1s linear infinite;"></div>
975 <p style="margin:0;">Checking browser compatibility...</p>
976 </div>
977 </div>';
978
979 // Spinner animation
980 $html .= '<style>@keyframes wpvr-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }</style>';
981
982 // Iframe (initial display set to block)
983 $html .= '<div id="' . $random_id . '-frame" class="' . esc_attr($className) . '" style="display:block; max-width:100%; width:' . esc_attr($width) . esc_attr($width_unit) . '; height:' . esc_attr($height) . esc_attr($height_unit) . '; border-radius: ' . esc_attr($radius) . '; margin: 0 auto;">';
984 $html .= '<iframe id="' . $random_id . '-iframe" src="https://www.youtube.com/embed/' . rawurlencode(sanitize_text_field($expdata)) . '?rel=0&modestbranding=1' . esc_attr($loop) . '&autohide=1' . esc_attr($muted) . '&showinfo=0&controls=1' . esc_attr($autoplay) . esc_attr($playlist) . '&enablejsapi=1" width="100%" height="100%" style="border-radius: ' . esc_attr($radius) . ';" frameborder="0" allowfullscreen allow="accelerometer; gyroscope; picture-in-picture"></iframe>';
985 $html .= '</div>';
986
987 // Permission request (mobile only)
988 $html .= '<div id="' . $random_id . '-permission-request" style="position:absolute; top:0; left:0; width:100%; height:100%; display:none; flex-direction:column; justify-content:center; align-items:center; background-color:rgba(0,0,0,0.7); color:white; text-align:center; border-radius:' . esc_attr( $radius ) . ';">';
989 $html .= '<p style="font-size:16px; margin:0 20px 15px;">For the best 360° video experience on mobile</p>';
990 $html .= '<button id="' . $random_id . '-permission-button" style="padding:10px 15px; background-color:#0085ba; color:#fff; border:none; border-radius:4px; cursor:pointer;">Allow motion and orientation access</button>';
991 $html .= '</div>';
992
993 // Browser warning
994 $html .= '<div id="' . $random_id . '-browser-warning" style="position:absolute; top:0; left:0; width:100%; height:100%; display:none; flex-direction:column; justify-content:center; align-items:center; background-color:rgba(0,0,0,0.7); color:white; text-align:center; border-radius:' . esc_attr( $radius ) . ';">';
995 $html .= '<p id="' . $random_id . '-warning-text" style="font-size:16px; margin:0 20px 5px;"></p>';
996 $html .= '<p style="font-size:14px; margin:5px 20px 15px;">For the best experience, use Chrome or Firefox.</p>';
997 $html .= '<button id="' . $random_id . '-browser-continue" style="padding:10px 15px; background-color:#0085ba; color:#fff; border:none; border-radius:4px; cursor:pointer;">Continue Anyway</button>';
998 $html .= '</div>';
999
1000 // Main script
1001 $html .= '<script>
1002 document.addEventListener("DOMContentLoaded", function() {
1003 var supportInfo = wpvr_check_360_support();
1004 var compatibilityCheck = document.getElementById("' . $random_id . '-compatibility-check");
1005 var frameContainer = document.getElementById("' . $random_id . '-frame");
1006 var warning = document.getElementById("' . $random_id . '-browser-warning");
1007 var warningText = document.getElementById("' . $random_id . '-warning-text");
1008 var continueBtn = document.getElementById("' . $random_id . '-browser-continue");
1009
1010 // Only show compatibility check and warning for iPhone
1011 if (supportInfo.isIPhone) {
1012 // Hide the iframe initially for iPhone
1013 frameContainer.style.display = "none";
1014
1015 // Show compatibility check for iPhone
1016 compatibilityCheck.style.display = "flex";
1017
1018 // After delay, hide compatibility check and show warning
1019 setTimeout(function() {
1020 compatibilityCheck.style.display = "none";
1021 warningText.textContent = supportInfo.browserWarning || "Your browser may not fully support 360° videos.";
1022 warning.style.display = "flex";
1023
1024 continueBtn.addEventListener("click", function() {
1025 warning.style.display = "none";
1026
1027 if (supportInfo.fullySupported && supportInfo.isMobile) {
1028 document.getElementById("' . $random_id . '-permission-request").style.display = "flex";
1029 document.getElementById("' . $random_id . '-permission-button").addEventListener("click", function() {
1030 requestDevicePermissions();
1031 });
1032 } else {
1033 showVideo();
1034 }
1035 });
1036 }, 1000);
1037 } else {
1038 // For non-iPhone devices, directly initialize the player
1039 initializeYouTubePlayer();
1040 }
1041
1042 function requestDevicePermissions() {
1043 try {
1044 if (typeof DeviceOrientationEvent !== "undefined" &&
1045 typeof DeviceOrientationEvent.requestPermission === "function") {
1046 DeviceOrientationEvent.requestPermission().then(function(response) {
1047 if (response === "granted") {
1048 if (typeof DeviceMotionEvent !== "undefined" &&
1049 typeof DeviceMotionEvent.requestPermission === "function") {
1050 DeviceMotionEvent.requestPermission().then(showVideo).catch(showVideo);
1051 } else {
1052 showVideo();
1053 }
1054 } else {
1055 showVideo();
1056 }
1057 }).catch(showVideo);
1058 } else {
1059 showVideo();
1060 }
1061 } catch (e) {
1062 showVideo();
1063 }
1064 }
1065
1066 function showVideo() {
1067 document.getElementById("' . $random_id . '-permission-request").style.display = "none";
1068 frameContainer.style.display = "block";
1069 initializeYouTubePlayer();
1070 }
1071
1072 function initializeYouTubePlayer() {
1073 if (window.YT) {
1074 initPlayer();
1075 } else {
1076 var tag = document.createElement("script");
1077 tag.src = "https://www.youtube.com/iframe_api";
1078 var firstScriptTag = document.getElementsByTagName("script")[0];
1079 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
1080 window.onYouTubeIframeAPIReady = initPlayer;
1081 }
1082
1083 function initPlayer() {
1084 new YT.Player("' . $random_id . '-iframe", {
1085 events: {
1086 "onReady": function(event) {}
1087 }
1088 });
1089 }
1090 }
1091 });
1092 </script>';
1093
1094 $html .= '</div>'; // Close container
1095 $html .= '</div>'; // Close outer wrapper
1096 } else {
1097 $html = '';
1098 $html .= '<div id="pano' . esc_attr($id) . '" class="pano-wrap ' . esc_attr($className) . '" style="max-width:100%; width:' . esc_attr($width) . esc_attr($width_unit) . '; height: ' . esc_attr($height) . esc_attr($height_unit) . '; border-radius:' . esc_attr($radius) . '; margin: 0 auto;">';
1099 $html .= '<div style="width:100%; height:100%; border-radius: ' . esc_attr($radius) . ';">' . wp_kses(
1100 $postdata['panoviddata'],
1101 array(
1102 'video' => array(
1103 'id' => array(),
1104 'class' => array(),
1105 'src' => array(),
1106 'controls' => array(),
1107 'autoplay' => array(),
1108 'loop' => array(),
1109 'muted' => array(),
1110 'poster' => array(),
1111 'preload' => array(),
1112 'width' => array(),
1113 'height' => array(),
1114 'style' => array(),
1115 'playsinline' => array(),
1116 'crossorigin' => array(),
1117 'data-*' => true,
1118 ),
1119 'source' => array(
1120 'src' => array(),
1121 'type' => array(),
1122 ),
1123 'track' => array(
1124 'kind' => array(),
1125 'src' => array(),
1126 'srclang' => array(),
1127 'label' => array(),
1128 'default' => array(),
1129 ),
1130 'div' => array(
1131 'id' => array(),
1132 'class' => array(),
1133 'style' => array(),
1134 'data-*' => true,
1135 ),
1136 'span' => array(
1137 'id' => array(),
1138 'class' => array(),
1139 'style' => array(),
1140 ),
1141 'button' => array(
1142 'id' => array(),
1143 'class' => array(),
1144 'style' => array(),
1145 'type' => array(),
1146 'title' => array(),
1147 ),
1148 )
1149 ) . '</div>';
1150
1151 $html .= '
1152 <style>
1153 .video-js {
1154 border-radius:' . esc_attr($radius) . ';
1155 }
1156 .video-js canvas{
1157 border-radius:' . esc_attr($radius) . ';
1158 }
1159 #pano' . esc_attr($id) . ' .vjs-poster {
1160 border-radius: ' . esc_attr($radius) . ';
1161 }
1162 </style>
1163
1164 ';
1165
1166 // $html .= '<script>';
1167 // $html .= 'videojs(' . $postdata['vidid'] . ', {';
1168 // $html .= 'plugins: {';
1169 // $html .= 'pannellum: {}';
1170 // $html .= '}';
1171 // $html .= '});';
1172 // $html .= '</script>';
1173 $html .= '</div>';
1174
1175 //video js vr setup //
1176 $html .= '<script>';
1177 $html .= '
1178 (function (window, videojs) {
1179 var player = window.player = videojs("' . $postdata['vidid'] . '");
1180 player.mediainfo = player.mediainfo || {};
1181 player.mediainfo.projection = "equirectangular";
1182
1183 // AUTO is the default and looks at mediainfo
1184 var vr = window.vr = player.vr({ projection: "AUTO", debug: true, forceCardboard: false, antialias: false });
1185 }(window, window.videojs));
1186
1187 ';
1188 $html .= '</script>';
1189 //video js vr end //
1190 }
1191 return $html;
1192 }
1193
1194 $control = false;
1195 if (isset($postdata['showControls'])) {
1196 $control = $postdata['showControls'];
1197 }
1198
1199 if ($control) {
1200 if (isset($postdata['customcontrol'])) {
1201 $custom_control = wpvr_parse_custom_control($postdata['customcontrol']);
1202 $custom_control = wp_parse_args($custom_control, array(
1203 'panupSwitch' => 'off',
1204 'panDownSwitch' => 'off',
1205 'panLeftSwitch' => 'off',
1206 'panRightSwitch' => 'off',
1207 'panZoomInSwitch' => 'off',
1208 'panZoomOutSwitch' => 'off',
1209 'panFullscreenSwitch' => 'off',
1210 'gyroscopeSwitch' => 'off',
1211 'backToHomeSwitch' => 'off',
1212 'explainerSwitch' => 'off',
1213 ));
1214 $gyro_enabled = isset($postdata['gyro']) && in_array($postdata['gyro'], array(true, 1, '1', 'on'), true);
1215 $custom_control['gyroSwitch'] = $gyro_enabled ? 'on' : 'off';
1216 $gyro_button_enabled = wpvr_isMobileDevice() && $custom_control['gyroSwitch'] == "on" && $custom_control['gyroscopeSwitch'] == "on";
1217 if ($custom_control['panupSwitch'] == "on" || $custom_control['panDownSwitch'] == "on" || $custom_control['panLeftSwitch'] == "on" || $custom_control['panRightSwitch'] == "on" || $custom_control['panZoomInSwitch'] == "on" || $custom_control['panZoomOutSwitch'] == "on" || $custom_control['panFullscreenSwitch'] == "on" || $gyro_button_enabled || $custom_control['backToHomeSwitch'] == "on") {
1218 $control = false;
1219 }
1220 }
1221 }
1222
1223 $floor_plan_enable = 'off';
1224 $floor_plan_image = '';
1225 if (isset($postdata['floor_plan_tour_enabler']) && $postdata['floor_plan_tour_enabler'] == 'on') {
1226 $floor_plan_enable = $postdata['floor_plan_tour_enabler'];
1227 if (isset($postdata['floor_plan_attachment_url']) && !empty($postdata['floor_plan_attachment_url'])) {
1228 $floor_plan_image = $postdata['floor_plan_attachment_url'];
1229 }
1230 }
1231
1232 $vrgallery = false;
1233 if (isset($postdata['vrgallery'])) {
1234 $vrgallery = $postdata['vrgallery'];
1235 }
1236
1237 $vrgallery_title = false;
1238 if (isset($postdata['vrgallery_title'])) {
1239 $vrgallery_title = $postdata['vrgallery_title'];
1240 }
1241
1242 $vrgallery_display = false;
1243 if (isset($postdata['vrgallery_display'])) {
1244 $vrgallery_display = $postdata['vrgallery_display'];
1245 }
1246 $vrgallery_icon_size = false;
1247 if (isset($postdata['vrgallery_icon_size'])) {
1248 $vrgallery_icon_size = $postdata['vrgallery_icon_size'];
1249 }
1250
1251 $gyro = false;
1252 $gyro_orientation = false;
1253 if (isset($postdata['gyro'])) {
1254 $gyro = in_array($postdata['gyro'], array(true, 1, '1', 'on'), true);
1255 if ($gyro && isset($postdata['deviceorientationcontrol'])) {
1256 $gyro_orientation = in_array($postdata['deviceorientationcontrol'], array(true, 1, '1', 'on'), true);
1257 }
1258 }
1259
1260 $compass = false;
1261 $audio_right = "5px";
1262 if (isset($postdata['compass'])) {
1263 $compass = $postdata['compass'] == 'on' || $postdata['compass'] != null ? true : false;
1264 if ($compass) {
1265 $audio_right = "60px";
1266 }
1267 }
1268 $floor_map_right = "25px";
1269 if ((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')) {
1270 $floor_map_right = "85px";
1271 } elseif (isset($postdata['compass']) && $postdata['compass'] == 'on') {
1272 $floor_map_right = "55px";
1273 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
1274 $floor_map_right = "25px";
1275 }
1276
1277 //===explainer handle===//
1278
1279 //===explainer handle===//
1280 $explainer_right = "10px";
1281 if ((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on') && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1282 $explainer_right = "130px";
1283 } elseif (isset($postdata['compass']) && $postdata['compass'] == 'on' && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1284 $explainer_right = "100px";
1285 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on" && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1286 $explainer_right = "55px";
1287 } elseif ((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')) {
1288 $explainer_right = "80px";
1289 } elseif (isset($postdata['compass']) && $postdata['compass'] == 'on') {
1290 $explainer_right = "55px";
1291 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
1292 $explainer_right = "30px";
1293 } elseif ($floor_plan_enable == 'on' && !empty($floor_plan_image)) {
1294 $explainer_right = "70px";
1295 }
1296 $enable_cardboard = '';
1297 $is_cardboard = get_option('wpvr_cardboard_disable');
1298 if (wpvr_isMobileDevice() && $is_cardboard == 'true') {
1299 $enable_cardboard = 'enable-cardboard';
1300 $audio_right = "73px";
1301 if (isset($postdata['compass'])) {
1302 $compass = $postdata['compass'] == 'on' || $postdata['compass'] != null ? true : false;
1303 if ($compass) {
1304 $audio_right = "130px";
1305 }
1306 }
1307
1308 $floor_map_right = "60px";
1309 if ((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')) {
1310 $floor_map_right = "150px";
1311 } elseif (isset($postdata['compass']) && $postdata['compass'] == 'on') {
1312 $floor_map_right = "120px";
1313 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
1314 $floor_map_right = "90px";
1315 }
1316
1317 //===explainer handle===//
1318
1319 $explainer_right = "65px";
1320
1321 if ((isset($postdata['compass']) && $postdata['compass'] == true) && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')) {
1322 $explainer_right = "150px";
1323 } elseif ((isset($postdata['compass']) && $postdata['compass'] == true) && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on') && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1324 $explainer_right = "180px";
1325 } elseif (isset($postdata['compass']) && $postdata['compass'] == true && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1326 $explainer_right = "150px";
1327 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on" && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1328 $explainer_right = "120px";
1329 } elseif (isset($postdata['compass']) && $postdata['compass'] == true) {
1330 $explainer_right = "130px";
1331 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
1332 $explainer_right = "90px";
1333 } elseif ($floor_plan_enable == 'on' && !empty($floor_plan_image)) {
1334 $explainer_right = "90px";
1335 }
1336 }
1337
1338 //===explainer handle===//
1339
1340 $mouseZoom = true;
1341 if (isset($postdata['mouseZoom'])) {
1342 if ($postdata['mouseZoom'] == "off") {
1343 $mouseZoom = false;
1344 } else {
1345 $mouseZoom = true;
1346 }
1347 }
1348
1349 $draggable = true;
1350 if (isset($postdata['draggable'])) {
1351 $draggable = ! in_array( $postdata['draggable'], array( 'off', 'false', false ), true );
1352 }
1353 $diskeyboard = false;
1354 if (isset($postdata['diskeyboard'])) {
1355 $diskeyboard = ! in_array( $postdata['diskeyboard'], array( 'off', 'false', false ), true );
1356 }
1357
1358 $keyboardzoom = true;
1359 if (isset($postdata['keyboardzoom'])) {
1360 $keyboardzoom = ! in_array( $postdata['keyboardzoom'], array( 'off', 'false', false ), true );
1361 }
1362
1363 $autoload = false;
1364
1365 if (isset($postdata['autoLoad'])) {
1366 $autoload = in_array( $postdata['autoLoad'], array( true, 1, '1', 'on', 'true' ), true );
1367 }
1368
1369 $default_scene = '';
1370 if (isset($postdata['defaultscene'])) {
1371 $default_scene = $postdata['defaultscene'];
1372 }
1373
1374 $preview = '';
1375 if (isset($postdata['preview'])) {
1376 $preview = $postdata['preview'];
1377 }
1378
1379 $autorotation = '';
1380 if (isset($postdata["autoRotate"])) {
1381 $autorotation = $postdata["autoRotate"];
1382 }
1383 $autorotationinactivedelay = '';
1384 if (isset($postdata["autoRotateInactivityDelay"])) {
1385 $autorotationinactivedelay = $postdata["autoRotateInactivityDelay"];
1386 }
1387 $autorotationstopdelay = '';
1388 if (isset($postdata["autoRotateStopDelay"])) {
1389 $autorotationstopdelay = $postdata["autoRotateStopDelay"];
1390 }
1391
1392 $scene_fade_duration = '';
1393 if (isset($postdata['scenefadeduration'])) {
1394 $scene_fade_duration = $postdata['scenefadeduration'];
1395 }
1396
1397 $panodata = array();
1398 if (isset($postdata['panodata'])) {
1399 $panodata = $postdata['panodata'];
1400 }
1401
1402 $show_scene_info = ( $postdata['scene-info-enabled'] ?? 'on' ) !== 'off';
1403 $tour_layout = is_array( $postdata['tourLayout'] ?? null )
1404 ? ( $postdata['tourLayout']['layout'] ?? 'default' )
1405 : ( $postdata['tourLayout'] ?? 'default' );
1406 $is_classic_layout = 'layout1' !== $tour_layout;
1407
1408 $default_zoom_global = 100;
1409 if (isset($postdata['hfov']) && $postdata['hfov'] != '') {
1410 $default_zoom_global = $postdata['hfov'];
1411 }
1412
1413 $min_zoom_global = 50;
1414 if (isset($postdata['minHfov']) && $postdata['minHfov'] != '') {
1415 $min_zoom_global = $postdata['minHfov'];
1416 }
1417
1418 $max_zoom_global = 120;
1419 if (isset($postdata['maxHfov']) && $postdata['maxHfov'] != '') {
1420 $max_zoom_global = $postdata['maxHfov'];
1421 }
1422
1423 $hotspoticoncolor = '#00b4ff';
1424 $hotspotblink = 'on';
1425 $default_data = array();
1426 $default_data = array('firstScene' => $default_scene, 'sceneFadeDuration' => $scene_fade_duration, 'hfov' => $default_zoom_global, 'maxHfov' => $max_zoom_global, 'minHfov' => $min_zoom_global);
1427 $scene_data = array();
1428 if (is_array($panodata) && isset($panodata['scene-list'])) {
1429 if (!empty($panodata['scene-list'])) {
1430 foreach ($panodata['scene-list'] as $panoscenes) {
1431 $scene_ititle = '';
1432 if (isset($panoscenes["scene-ititle"])) {
1433 $scene_ititle = esc_html($panoscenes["scene-ititle"]);
1434 }
1435
1436 $scene_author = '';
1437 if (isset($panoscenes["scene-author"])) {
1438 $scene_author = esc_html($panoscenes["scene-author"]);
1439 }
1440
1441 $scene_author_url = '';
1442 if (isset($panoscenes["scene-author-url"])) {
1443 $scene_author_url = sanitize_text_field($panoscenes["scene-author-url"]);
1444 }
1445
1446 $scene_vaov = 180;
1447 if (isset($panoscenes["scene-vaov"])) {
1448 $scene_vaov = (float)$panoscenes["scene-vaov"];
1449 }
1450
1451 $scene_haov = 360;
1452 if (isset($panoscenes["scene-haov"])) {
1453 $scene_haov = (float)$panoscenes["scene-haov"];
1454 }
1455
1456 $scene_vertical_offset = 0;
1457 if (isset($panoscenes["scene-vertical-offset"])) {
1458 $scene_vertical_offset = (float)$panoscenes["scene-vertical-offset"];
1459 }
1460
1461 $default_scene_pitch = null;
1462 if (isset($panoscenes["scene-pitch"])) {
1463 $default_scene_pitch = (float)$panoscenes["scene-pitch"];
1464 }
1465
1466 $default_scene_yaw = null;
1467 if (isset($panoscenes["scene-yaw"])) {
1468 $default_scene_yaw = (float)$panoscenes["scene-yaw"];
1469 }
1470
1471 $scene_max_pitch = '';
1472 if (isset($panoscenes["scene-maxpitch"])) {
1473 $scene_max_pitch = (float)$panoscenes["scene-maxpitch"];
1474 }
1475
1476
1477 $scene_min_pitch = '';
1478 if (isset($panoscenes["scene-minpitch"])) {
1479 $scene_min_pitch = (float)$panoscenes["scene-minpitch"];
1480 }
1481
1482
1483 $scene_max_yaw = '';
1484 if (isset($panoscenes["scene-maxyaw"])) {
1485 $scene_max_yaw = (float)$panoscenes["scene-maxyaw"];
1486 }
1487
1488
1489 $scene_min_yaw = '';
1490 if (isset($panoscenes["scene-minyaw"])) {
1491 $scene_min_yaw = (float)$panoscenes["scene-minyaw"];
1492 }
1493
1494 $default_zoom = 100;
1495 if (isset($panoscenes["scene-zoom"]) && $panoscenes["scene-zoom"] != '') {
1496 $default_zoom = (int)$panoscenes["scene-zoom"];
1497 } else {
1498 if ($default_zoom_global != '') {
1499 $default_zoom = (int)$default_zoom_global;
1500 }
1501 }
1502
1503
1504 $max_zoom = 120;
1505 if (isset($panoscenes["scene-maxzoom"]) && $panoscenes["scene-maxzoom"] != '') {
1506 $max_zoom = (int)$panoscenes["scene-maxzoom"];
1507 } else {
1508 if ($max_zoom_global != '') {
1509 $max_zoom = (int)$max_zoom_global;
1510 }
1511 }
1512
1513 $min_zoom = 120;
1514 if (isset($panoscenes["scene-minzoom"]) && $panoscenes["scene-minzoom"] != '') {
1515 $min_zoom = (int)$panoscenes["scene-minzoom"];
1516 } else {
1517 if ($min_zoom_global != '') {
1518 $min_zoom = (int)$min_zoom_global;
1519 }
1520 }
1521
1522 $hotspot_datas = array();
1523 if (isset($panoscenes['hotspot-list'])) {
1524 $hotspot_datas = $panoscenes['hotspot-list'];
1525 }
1526
1527 $hotspots = array();
1528
1529 foreach ($hotspot_datas as $hotspot_data) {
1530 $status = get_option('wpvr_edd_license_status');
1531 if ($status !== false && $status == 'valid') {
1532
1533 if (isset($hotspot_data["hotspot-customclass-pro"]) && $hotspot_data["hotspot-customclass-pro"] != 'none') {
1534 $hotspot_data['hotspot-customclass'] = $hotspot_data["hotspot-customclass-pro"] . ' custom-' . $id . '-' . $panoscenes['scene-id'] . '-' . $hotspot_data['hotspot-title'];
1535 }
1536 if (isset($hotspot_data['hotspot-blink'])) {
1537 $hotspotblink = $hotspot_data['hotspot-blink'];
1538 }
1539 }
1540 $hotspot_scene_pitch = '';
1541 if (isset($hotspot_data["hotspot-scene-pitch"])) {
1542 $hotspot_scene_pitch = $hotspot_data["hotspot-scene-pitch"];
1543 }
1544 $hotspot_scene_yaw = '';
1545 if (isset($hotspot_data["hotspot-scene-yaw"])) {
1546 $hotspot_scene_yaw = $hotspot_data["hotspot-scene-yaw"];
1547 }
1548
1549 $hotspot_type = $hotspot_data["hotspot-type"] !== 'scene' ? 'info' : $hotspot_data["hotspot-type"];
1550 $hotspot_content = '';
1551
1552 ob_start();
1553 do_action('wpvr_hotspot_content', $hotspot_data);
1554 $hotspot_content = ob_get_clean();
1555
1556 if (!$hotspot_content) {
1557 $hotspot_content = $hotspot_data["hotspot-content"];
1558 }
1559
1560 if (isset($hotspot_data["wpvr_url_open"][0])) {
1561 $wpvr_url_open = $hotspot_data["wpvr_url_open"][0];
1562 } else {
1563 $wpvr_url_open = "off";
1564 }
1565 $on_hover_content = preg_replace_callback(
1566 '/<p>\s*(<img[^>]*>)\s*<br>\s*<\/p>/i',
1567 function ($matches) {
1568 return $matches[1];
1569 },
1570 $hotspot_data['hotspot-hover'] ?? ''
1571 );
1572
1573 if('fluent_form' !== $hotspot_data["hotspot-type"]){
1574 $on_hover_content = sanitize_content_preserve_styles($on_hover_content ?? '');
1575 $on_click_content = preg_replace_callback('/<img[^>]*>/', "replace_callback", $hotspot_content ?? '');
1576 $on_click_content = sanitize_content_preserve_styles($on_click_content ?? '');
1577 }else{
1578 $on_hover_content = $on_hover_content ?? '';
1579 $on_click_content = $hotspot_content ?? '';
1580 }
1581
1582
1583 // Shape is independent of the optional custom icon in the
1584 // new editor, so it must always be included in the public
1585 // hotspot configuration.
1586 $hotspot_shape = isset( $hotspot_data['hotspot-shape'] )
1587 && in_array( $hotspot_data['hotspot-shape'], [ 'round', 'square', 'hexagon' ], true )
1588 ? $hotspot_data['hotspot-shape']
1589 : 'round';
1590
1591 $hotspot_data_for_on_click=[];
1592 if( ('info' === $hotspot_type || 'fluent_form' === $hotspot_data["hotspot-type"] ) && !empty($on_click_content)){
1593 $hotspot_data_for_on_click = [
1594 'on_click_content' => $on_click_content,
1595 'tour_id' => $id,
1596 'scene_id' => $panoscenes['scene-id'],
1597 'hotspot_id' => sanitize_html_class($hotspot_data['hotspot-title']),
1598 ];
1599 } elseif('info' === $hotspot_type && !empty($hotspot_data["hotspot-url"])){
1600 $hotspot_data_for_on_click = [
1601 'on_click_content' => '',
1602 'tour_id' => $id,
1603 'scene_id' => $panoscenes['scene-id'],
1604 'hotspot_id' => sanitize_html_class($hotspot_data['hotspot-title']),
1605 ];
1606 }
1607
1608 $hotspot_info = array(
1609 'text' => esc_html(sanitize_text_field($hotspot_data['hotspot-title'])),
1610 'pitch' => $hotspot_data['hotspot-pitch'],
1611 'yaw' => $hotspot_data['hotspot-yaw'],
1612 'type' => $hotspot_type,
1613 'cssClass' => $hotspot_data['hotspot-customclass'],
1614 'URL' => $hotspot_data['hotspot-url'],
1615 "wpvr_url_open" => $wpvr_url_open,
1616 "clickHandlerArgs" => $hotspot_data_for_on_click,
1617 'createTooltipArgs' => !empty(trim($on_hover_content)) ? trim($on_hover_content) : '',
1618 "sceneId" => $hotspot_data["hotspot-scene"],
1619 "targetPitch" => (float)$hotspot_scene_pitch,
1620 "targetYaw" => (float)$hotspot_scene_yaw,
1621 'hotspot_type' => $hotspot_data['hotspot-type'],
1622 'hotspot_shape' => $hotspot_shape,
1623 );
1624
1625 $hotspot_info['URL'] = ($hotspot_data['hotspot-type'] === 'fluent_form' || $hotspot_data['hotspot-type'] === 'wc_product') ? '' : $hotspot_info['URL'];
1626
1627 if ($hotspot_data["hotspot-customclass"] == 'none' || $hotspot_data["hotspot-customclass"] == '') {
1628 unset($hotspot_info["cssClass"]);
1629 }
1630 if (empty($hotspot_data["hotspot-scene"])) {
1631 unset($hotspot_info['targetPitch']);
1632 unset($hotspot_info['targetYaw']);
1633 }
1634 array_push($hotspots, $hotspot_info);
1635 }
1636
1637 $device_scene = $panoscenes['scene-attachment-url'];
1638 $mobile_media_resize = get_option('mobile_media_resize');
1639 $file_accessible = ini_get('allow_url_fopen');
1640 if ($mobile_media_resize == "true" && $device_scene) {
1641 if ($file_accessible == "1") {
1642 $image_info = getimagesize($device_scene);
1643 if ($image_info && $image_info[0] > 4096) {
1644 $src_to_id_for_mobile = '';
1645 $src_to_id_for_desktop = '';
1646 if (wpvr_isMobileDevice()) {
1647 $src_to_id_for_mobile = attachment_url_to_postid($panoscenes['scene-attachment-url']);
1648 if ($src_to_id_for_mobile) {
1649 $mobile_scene = wp_get_attachment_image_src($src_to_id_for_mobile, 'wpvr_mobile');
1650 if ($mobile_scene[3]) {
1651 $device_scene = $mobile_scene[0];
1652 }
1653 }
1654 } else {
1655 $src_to_id_for_desktop = attachment_url_to_postid($panoscenes['scene-attachment-url']);
1656 if ($src_to_id_for_desktop) {
1657 $desktop_scene = wp_get_attachment_image_src($src_to_id_for_mobile, 'full');
1658 if ($desktop_scene && $desktop_scene[0]) {
1659 $device_scene = $desktop_scene[0];
1660 }
1661 }
1662 }
1663 }
1664 }
1665 }
1666
1667 $scene_info = array();
1668
1669 if ($panoscenes["scene-type"] == 'cubemap') {
1670 $pano_type = 'cubemap';
1671 $pano_attachment = array(
1672 $panoscenes["scene-attachment-url-face0"],
1673 $panoscenes["scene-attachment-url-face1"],
1674 $panoscenes["scene-attachment-url-face2"],
1675 $panoscenes["scene-attachment-url-face3"],
1676 $panoscenes["scene-attachment-url-face4"],
1677 $panoscenes["scene-attachment-url-face5"]
1678 );
1679
1680 $scene_info = array('type' => $panoscenes['scene-type'], 'cubeMap' => $pano_attachment, "pitch" => $default_scene_pitch, "maxPitch" => $scene_max_pitch, "minPitch" => $scene_min_pitch, "maxYaw" => $scene_max_yaw, "minYaw" => $scene_min_yaw, "yaw" => $default_scene_yaw, "hfov" => $default_zoom, "maxHfov" => $max_zoom, "minHfov" => $min_zoom, "title" => $scene_ititle, "author" => $scene_author, "authorURL" => $scene_author_url, "vaov" => $scene_vaov, "haov" => $scene_haov, "vOffset" => $scene_vertical_offset, 'hotSpots' => $hotspots);
1681 } else {
1682 $scene_info = array('type' => $panoscenes['scene-type'], 'panorama' => $device_scene, "pitch" => $default_scene_pitch, "maxPitch" => $scene_max_pitch, "minPitch" => $scene_min_pitch, "maxYaw" => $scene_max_yaw, "minYaw" => $scene_min_yaw, "yaw" => $default_scene_yaw, "hfov" => $default_zoom, "maxHfov" => $max_zoom, "minHfov" => $min_zoom, "title" => $scene_ititle, "author" => $scene_author, "authorURL" => $scene_author_url, "vaov" => $scene_vaov, "haov" => $scene_haov, "vOffset" => $scene_vertical_offset, 'hotSpots' => $hotspots);
1683 }
1684
1685
1686
1687 if (isset($panoscenes["ptyscene"])) {
1688 if ($panoscenes["ptyscene"] == "off") {
1689 unset($scene_info['pitch']);
1690 unset($scene_info['yaw']);
1691 }
1692 }
1693
1694 if (!$show_scene_info || empty($panoscenes["scene-ititle"])) {
1695 unset($scene_info['title']);
1696 }
1697 if (!$show_scene_info || empty($panoscenes["scene-author"])) {
1698 unset($scene_info['author']);
1699 }
1700 if (!$show_scene_info || empty($panoscenes["scene-author-url"])) {
1701 unset($scene_info['authorURL']);
1702 }
1703
1704 if (empty($scene_vaov)) {
1705 unset($scene_info['vaov']);
1706 }
1707
1708 if (empty($scene_haov)) {
1709 unset($scene_info['haov']);
1710 }
1711
1712 if (empty($scene_vertical_offset)) {
1713 unset($scene_info['vOffset']);
1714 }
1715
1716 if (isset($panoscenes["cvgscene"])) {
1717 if ($panoscenes["cvgscene"] == "off") {
1718 unset($scene_info['maxPitch']);
1719 unset($scene_info['minPitch']);
1720 }
1721 }
1722 if (empty($panoscenes["scene-maxpitch"])) {
1723 unset($scene_info['maxPitch']);
1724 }
1725
1726 if (empty($panoscenes["scene-minpitch"])) {
1727 unset($scene_info['minPitch']);
1728 }
1729
1730 if (isset($panoscenes["chgscene"])) {
1731 if ($panoscenes["chgscene"] == "off") {
1732 unset($scene_info['maxYaw']);
1733 unset($scene_info['minYaw']);
1734 }
1735 }
1736 if (empty($panoscenes["scene-maxyaw"])) {
1737 unset($scene_info['maxYaw']);
1738 }
1739
1740 if (empty($panoscenes["scene-minyaw"])) {
1741 unset($scene_info['minYaw']);
1742 }
1743
1744 // if (isset($panoscenes["czscene"])) {
1745 // if ($panoscenes["czscene"] == "off") {
1746 // unset($scene_info['hfov']);
1747 // unset($scene_info['maxHfov']);
1748 // unset($scene_info['minHfov']);
1749 // }
1750 // }
1751
1752 $scene_array = array();
1753 $scene_array = array(
1754 $panoscenes['scene-id'] => $scene_info
1755 );
1756
1757 $scene_data[$panoscenes['scene-id']] = $scene_info;
1758 }
1759 }
1760 }
1761 $pano_id_array = array();
1762 $pano_id_array = array('panoid' => $panoid);
1763 $pano_response = array();
1764 $pano_response = array('autoLoad' => $autoload, 'showControls' => $control, 'compass' => $compass, 'orientationOnByDefault' => $gyro_orientation, 'mouseZoom' => $mouseZoom, 'draggable' => $draggable, 'disableKeyboardCtrl' => $diskeyboard, 'keyboardZoom' => $keyboardzoom, "preview" => $preview, "autoRotate" => $autorotation, "autoRotateInactivityDelay" => $autorotationinactivedelay, "autoRotateStopDelay" => $autorotationstopdelay, 'default' => $default_data, 'scenes' => $scene_data);
1765 if (empty($autorotation)) {
1766 unset($pano_response['autoRotate']);
1767 unset($pano_response['autoRotateInactivityDelay']);
1768 unset($pano_response['autoRotateStopDelay']);
1769 }
1770 if (empty($autorotationinactivedelay)) {
1771 unset($pano_response['autoRotateInactivityDelay']);
1772 }
1773 if (empty($autorotationstopdelay)) {
1774 unset($pano_response['autoRotateStopDelay']);
1775 }
1776
1777 $response = array();
1778 $response = array($pano_id_array, $pano_response);
1779 if (!empty($response)) {
1780 $response = json_encode($response);
1781 }
1782 if (empty($width)) {
1783 $width = '600';
1784 }
1785 if (empty($height)) {
1786 $height = '400';
1787 }
1788 if ('fullwidth' == $width) {
1789 $width = "100%";
1790 }
1791
1792 $foreground_color = '#fff';
1793 $pulse_color = wpvr_hex2rgb($hotspoticoncolor);
1794 $rgb = wpvr_HTMLToRGB($hotspoticoncolor);
1795 $hsl = wpvr_RGBToHSL($rgb);
1796 if ($hsl->lightness > 200) {
1797 $foreground_color = '#000000';
1798 } else {
1799 $foreground_color = '#fff';
1800 }
1801
1802 $class = 'myclass';
1803 $html = 'test';
1804 $html = '';
1805 $html .= '<style>';
1806 if ($width == 'embed') {
1807 $html .= 'body{
1808 overflow: hidden;
1809 }';
1810 }
1811 $status = get_option('wpvr_edd_license_status');
1812 if ($status !== false && $status == 'valid') {
1813 if (isset($postdata['customcss_enable']) && $postdata['customcss_enable'] == 'on') {
1814 $html .= isset($postdata['customcss']) ? $postdata['customcss'] : '';
1815 }
1816 }
1817 if ($status !== false && $status == 'valid') {
1818 if (is_array($panodata) && isset($panodata['scene-list'])) {
1819 foreach ($panodata['scene-list'] as $panoscenes) {
1820
1821 foreach ($panoscenes['hotspot-list'] as $hotspot) {
1822 if (isset($hotspot['hotspot-customclass-color-icon-value']) && !empty($hotspot['hotspot-customclass-color-icon-value'])) {
1823 $hotspoticoncolor = $hotspot['hotspot-customclass-color-icon-value'];
1824 } else {
1825 $hotspoticoncolor = "#00b4ff";
1826 }
1827 $hotspot_border = '';
1828 if(isset($hotspot['hotspot-border']) && $hotspot['hotspot-border'] == 'on'){
1829 $border_width = $hotspot['hotspot-border-width'];
1830 $border_color = $hotspot['hotspot-border-color'];
1831 $border_style = $hotspot['hotspot-border-style'];
1832
1833 $hotspot_border = 'border: '.$border_width.'px '.$border_style.' '.$border_color.';';
1834 }
1835 $hotspot_background_color = 'background-color: ' . $hotspoticoncolor . ';';
1836 $hotspot_animation = ' animation: icon-pulse' . $panoid . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' 1.5s infinite cubic-bezier(.25, 0, 0, 1);
1837 '. $hotspot_border.'';
1838
1839
1840 $pulse_color = wpvr_hex2rgb($hotspoticoncolor);
1841 if (isset($hotspot["hotspot-customclass-pro"]) && $hotspot["hotspot-customclass-pro"] != 'none') {
1842 $border_radius = ' border-radius: 100%;';
1843 $hotspot_shape = isset($hotspot["hotspot-shape"]) ? $hotspot["hotspot-shape"] : 'round';
1844 if($hotspot_shape === 'square'){
1845 $border_radius = '';
1846 }
1847 if ($hotspot_shape === 'hexagon') {
1848 $border_radius = '';
1849 $hotspot_background_color = 'background-color: transparent;';
1850 $hotspot_animation = '';
1851 }
1852
1853 if(isset($hotspot['hotspot-custom-icon-color-value']) && !empty($hotspot['hotspot-custom-icon-color-value'])){
1854 $foreground_color = $hotspot['hotspot-custom-icon-color-value'];
1855 }
1856 $html .= '#' . esc_attr( $panoid ). ' div.pnlm-hotspot-base.fas.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1857 #' . esc_attr( $panoid ). ' div.pnlm-hotspot-base.fab.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1858 #' . esc_attr( $panoid ). ' div.pnlm-hotspot-base.fa.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1859 #' . esc_attr( $panoid ). ' div.pnlm-hotspot-base.fa-solid.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1860 #' . esc_attr( $panoid ). ' div.pnlm-hotspot-base.far.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' {
1861 display: block !important;
1862 '.$hotspot_background_color.'
1863 color: ' . $foreground_color . ';
1864 '.$border_radius.'
1865 width: 30px;
1866 height: 30px;
1867 font-size: 16px;
1868 line-height: 30px;
1869 '.$hotspot_animation.'
1870 }';
1871 if($hotspot_shape === 'hexagon'){
1872
1873 $html .= '#' . esc_attr( $panoid ) . ' .custom-' . esc_attr( $id ) . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' .hexagon-wrapper svg path {
1874 fill: ' . $hotspoticoncolor . ';
1875 }';
1876
1877 $html .= '#' . esc_attr( $panoid ) . ' .custom-' . esc_attr( $id ) . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . '.pnlm-tooltip:after{
1878 content: "";
1879 position: absolute;
1880 left: 50%;
1881 top: 50%;
1882 transform: translate(-50%, -50%);
1883 width: 85%;
1884 height: 85%;
1885 animation: icon-pulse' . esc_attr( $panoid ) . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' 1.5s infinite cubic-bezier(.25, 0, 0, 1);
1886 border-radius: 100%;
1887 z-index: -2;
1888 }';
1889
1890 }
1891 $html .= '#' . esc_attr( $panoid2 ). ' div.pnlm-hotspot-base.fas.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1892 #' . esc_attr( $panoid2 ). ' div.pnlm-hotspot-base.fab.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1893 #' . esc_attr( $panoid2 ). ' div.pnlm-hotspot-base.fa-solid.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1894 #' . esc_attr( $panoid2) . ' div.pnlm-hotspot-base.fa.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1895 #' . esc_attr( $panoid2 ). ' div.pnlm-hotspot-base.far.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' {
1896 display: block !important;
1897 '.esc_attr( $hotspot_background_color).'
1898 color: ' . esc_attr( $foreground_color) . ';
1899 '.esc_attr( $border_radius).'
1900 width: 30px;
1901 height: 30px;
1902 font-size: 16px;
1903 line-height: 30px;
1904 '.esc_attr( $hotspot_animation).'
1905 }';
1906 }
1907 if (isset($hotspot['hotspot-blink'])) {
1908 $hotspotblink = $hotspot['hotspot-blink'];
1909 if ($hotspotblink == 'on') {
1910 $html .= '@-webkit-keyframes icon-pulse' . esc_attr( $panoid) . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' {
1911 0% {
1912 box-shadow: 0 0 0 0px rgba(' . esc_attr( $pulse_color[0]) . ', 1);
1913 }
1914 100% {
1915 box-shadow: 0 0 0 10px rgba(' . esc_attr( $pulse_color[0]) . ', 0);
1916 }
1917 }
1918 @keyframes icon-pulse' . esc_attr( $panoid) . ' {
1919 0% {
1920 box-shadow: 0 0 0 0px rgba(' . esc_attr( $pulse_color[0]) . ', 1);)
1921 }
1922 100% {
1923 box-shadow: 0 0 0 10px rgba(' . esc_attr( $pulse_color[0] ). ', 0);
1924 }
1925 }';
1926 }
1927 }
1928 }
1929 }
1930 }
1931 }
1932
1933 $status = get_option('wpvr_edd_license_status');
1934 if ($status !== false && $status == 'valid') {
1935 if (!$gyro) {
1936 $html .= '#' . esc_attr( $panoid ). ' div.pnlm-orientation-button {
1937 display: none;
1938 }';
1939 }
1940 } else {
1941 $html .= '#' . esc_attr( $panoid ). ' div.pnlm-orientation-button {
1942 display: none;
1943 }';
1944 }
1945 $floor_plan_custom_color = isset($postdata['floor_plan_custom_color']) ? $postdata['floor_plan_custom_color'] : '#cca92c';
1946 $foreground_color_pointer = '#fff';
1947 if ($floor_plan_custom_color != '') {
1948 $pointer_pulse = wpvr_hex2rgb($floor_plan_custom_color);
1949 $floor_rgb = wpvr_HTMLToRGB($floor_plan_custom_color);
1950 $floor_hsl = wpvr_RGBToHSL($floor_rgb);
1951 if ($floor_hsl->lightness > 200) {
1952 $foreground_color_pointer = '#000000';
1953 }
1954 $html .= '
1955 .wpvr-floor-map .floor-plan-pointer.add-pulse:before {
1956 border: 17px solid ' . esc_attr( $floor_plan_custom_color ) . ';
1957 }
1958 @-webkit-keyframes pulse {
1959 0% {
1960 -webkit-box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0.7);
1961 }
1962 70% {
1963 -webkit-box-shadow: 0 0 0 10px rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1964 }
1965 100% {
1966 -webkit-box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1967 }
1968 }
1969 @keyframes pulse {
1970 0% {
1971 -moz-box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0.7);
1972 box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0.7);
1973 }
1974 70% {
1975 -moz-box-shadow: 0 0 0 10px rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1976 box-shadow: 0 0 0 10px rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1977 }
1978 100% {
1979 -moz-box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1980 box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1981 }
1982 }';
1983 }
1984 $html .= '</style>';
1985
1986 $scene_animation = isset($postdata['sceneAnimation']) ? $postdata['sceneAnimation'] : 'off';
1987 $scene_animation_enabled = in_array( $scene_animation, array( 'on', '1', 1, true ), true );
1988
1989 if( $scene_animation_enabled && is_plugin_active( 'wpvr-pro/wpvr-pro.php' ) ) {
1990 $animation_type = isset($postdata['sceneAnimationName']) ? $postdata['sceneAnimationName'] : 'none';
1991 $animation_type = $animation_type === 'fade' ? 'fade_in' : $animation_type;
1992 $animationDuration = isset($postdata['sceneAnimationTransitionDuration']) ? $postdata['sceneAnimationTransitionDuration'] : '500ms';
1993 $animationDelay = isset($postdata['sceneAnimationTransitionDelay']) ? $postdata['sceneAnimationTransitionDelay'] : '0ms';
1994 $animation_css = apply_filters('wpvr_tour_scene_animation',$animation_type,$animationDuration, $animationDelay, $postdata,$id);
1995 $html .= $animation_css;
1996 }
1997
1998 if (wpvr_isMobileDevice()) {
1999 $html .= '<div id="master-container" class="wpvr-cardboard ' . esc_attr( $className ) . ' ' . esc_attr( $enable_cardboard ) . ' " style="max-width:' . esc_attr( $width ) . esc_attr( $width_unit ) . '; width: 100%; height: ' . esc_attr( $mobile_height ) . esc_attr( $mobile_height_unit ) . '; border-radius:' . esc_attr( $radius ) . '; direction:ltr; border : ' . esc_attr( $border_style ) . ' ">';
2000 } else {
2001 $html .= '<div id="master-container" class="wpvr-cardboard ' . esc_attr( $className ) . ' ' . esc_attr( $enable_cardboard ) . '" style="max-width:' . esc_attr( $width ) . esc_attr( $width_unit ) . '; width: 100%; height: ' . esc_attr( $height ) . esc_attr( $height_unit ) . '; border-radius:' . esc_attr( $radius ) . '; direction:ltr; border : ' . esc_attr( $border_style ) . '">';
2002 }
2003 $status = get_option('wpvr_edd_license_status');
2004 $is_cardboard = get_option('wpvr_cardboard_disable');
2005 if ($status !== false && 'valid' == $status && $is_pro && wpvr_isMobileDevice() && $is_cardboard == 'true') {
2006 $html .= '<button class="fullscreen-button">';
2007 $html .= '<span class="expand">';
2008 $html .= '<i class="fas fa-expand" aria-hidden="true"></i>';
2009 $html .= '</span>';
2010
2011 $html .= '<span class="compress">';
2012 $html .= '<i class="fas fa-minimize" aria-hidden="true"></i>';
2013 $html .= '</span>';
2014 $html .= '</button>';
2015 $html .= '<label class="wpvr-cardboard-switcher">
2016 <input type="checkbox" class="vr_mode_change' . $id . '" name="vr_mode_change" value="off">
2017 <span class="switcher-box">
2018 <span class="normal-mode-tooltip">Normal VR Mode</span>
2019 <svg width="78" height="60" viewBox="0 0 78 60" fill="none" xmlns="http://www.w3.org/2000/svg">
2020 <path d="M42.25 21.4286C42.25 22.2811 41.9076 23.0986 41.2981 23.7014C40.6886 24.3042 39.862 24.6429 39 24.6429C38.138 24.6429 37.3114 24.3042 36.7019 23.7014C36.0924 23.0986 35.75 22.2811 35.75 21.4286C35.75 20.5761 36.0924 19.7585 36.7019 19.1557C37.3114 18.5529 38.138 18.2143 39 18.2143C39.862 18.2143 40.6886 18.5529 41.2981 19.1557C41.9076 19.7585 42.25 20.5761 42.25 21.4286ZM19.5 30C18.9254 30 18.3743 30.2258 17.9679 30.6276C17.5616 31.0295 17.3333 31.5745 17.3333 32.1429C17.3333 32.7112 17.5616 33.2562 17.9679 33.6581C18.3743 34.06 18.9254 34.2857 19.5 34.2857H28.1667C28.7413 34.2857 29.2924 34.06 29.6987 33.6581C30.1051 33.2562 30.3333 32.7112 30.3333 32.1429C30.3333 31.5745 30.1051 31.0295 29.6987 30.6276C29.2924 30.2258 28.7413 30 28.1667 30H19.5ZM47.6667 32.1429C47.6667 31.5745 47.8949 31.0295 48.3013 30.6276C48.7076 30.2258 49.2587 30 49.8333 30H58.5C59.0746 30 59.6257 30.2258 60.0321 30.6276C60.4384 31.0295 60.6667 31.5745 60.6667 32.1429C60.6667 32.7112 60.4384 33.2562 60.0321 33.6581C59.6257 34.06 59.0746 34.2857 58.5 34.2857H49.8333C49.2587 34.2857 48.7076 34.06 48.3013 33.6581C47.8949 33.2562 47.6667 32.7112 47.6667 32.1429ZM32.5 0C31.9254 0 31.3743 0.225765 30.9679 0.627629C30.5616 1.02949 30.3333 1.57454 30.3333 2.14286V8.57143H18.4167C14.8693 8.57183 11.4528 9.89617 8.84994 12.2798C6.24706 14.6634 4.64954 17.9306 4.37667 21.4286H2.16667C1.59203 21.4286 1.04093 21.6543 0.634602 22.0562C0.228273 22.4581 0 23.0031 0 23.5714V36.4286C0 36.9969 0.228273 37.5419 0.634602 37.9438C1.04093 38.3457 1.59203 38.5714 2.16667 38.5714H4.33333V46.0714C4.33333 49.7655 5.81711 53.3083 8.45825 55.9204C11.0994 58.5325 14.6815 60 18.4167 60H25.3933C29.1269 59.9986 32.7071 58.5311 35.347 55.92L37.921 53.3786C38.0618 53.2393 38.229 53.1288 38.4131 53.0534C38.5971 52.978 38.7943 52.9392 38.9935 52.9392C39.1927 52.9392 39.3899 52.978 39.5739 53.0534C39.758 53.1288 39.9252 53.2393 40.066 53.3786L42.6357 55.92C45.2766 58.5322 48.8586 59.9998 52.5937 60H59.5833C63.3185 60 66.9006 58.5325 69.5418 55.9204C72.1829 53.3083 73.6667 49.7655 73.6667 46.0714V38.5714H75.8333C76.408 38.5714 76.9591 38.3457 77.3654 37.9438C77.7717 37.5419 78 36.9969 78 36.4286V23.5714C78 23.0031 77.7717 22.4581 77.3654 22.0562C76.9591 21.6543 76.408 21.4286 75.8333 21.4286H73.6233C73.3505 17.9306 71.753 14.6634 69.1501 12.2798C66.5472 9.89617 63.1307 8.57183 59.5833 8.57143H47.6667V2.14286C47.6667 1.57454 47.4384 1.02949 47.0321 0.627629C46.6257 0.225765 46.0746 0 45.5 0H32.5ZM69.3333 22.5V46.0714C69.3333 48.6289 68.3061 51.0816 66.4776 52.89C64.6491 54.6983 62.1692 55.7143 59.5833 55.7143H52.5937C50.0093 55.7132 47.5311 54.6973 45.7037 52.89L43.1297 50.3486C42.5864 49.8108 41.9413 49.3842 41.2312 49.0931C40.5211 48.8021 39.76 48.6522 38.9913 48.6522C38.2227 48.6522 37.4616 48.8021 36.7515 49.0931C36.0414 49.3842 35.3963 49.8108 34.853 50.3486L32.2833 52.89C30.4559 54.6973 27.9777 55.7132 25.3933 55.7143H18.4167C15.8308 55.7143 13.3509 54.6983 11.5224 52.89C9.6939 51.0816 8.66667 48.6289 8.66667 46.0714V22.5C8.66667 19.9426 9.6939 17.4899 11.5224 15.6815C13.3509 13.8731 15.8308 12.8571 18.4167 12.8571H59.5833C62.1692 12.8571 64.6491 13.8731 66.4776 15.6815C68.3061 17.4899 69.3333 19.9426 69.3333 22.5Z" fill="#216DF0"/>
2021 </svg>
2022 </span>
2023 </label>';
2024 }
2025
2026 if ($width == 'fullwidth') {
2027 if (wpvr_isMobileDevice()) {
2028 $html .= '<div class="cardboard-vrfullwidth vrfullwidth">';
2029 $html .= '<div id="pano2' . esc_attr( $id ) . '" class="pano-wrap pano-left cardboard-half" style="width: 49%!important; border-radius:' . esc_attr( $radius ). ' ;text-align:center; direction:ltr;" ><div id="center-pointer2' . esc_attr( $id ). '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
2030 $html .= '<div id="pano' . esc_attr( $id ) . '" class="pano-wrap pano-right" style="width: 100%; text-align:center; direction:ltr; border-radius:' . esc_attr( $radius ) . '" >';
2031 } else {
2032 $html .= '<div id="pano2' . esc_attr( $id ) . '" class="pano-wrap pano-left" style="width: 49%; border-radius:' . esc_attr( $radius ) . ';"><div id="center-pointer2' . esc_attr( $id ). '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
2033 $html .= '<div id="pano' . esc_attr( $id ) . '" class="pano-wrap vrfullwidth" style=" text-align:center; height: ' . esc_attr( $height ) . esc_attr( $height_unit ) . '; border-radius:' . esc_attr( $radius ) . '; direction:ltr;" >';
2034 }
2035 } else {
2036 if (wpvr_isMobileDevice()) {
2037 $html .= '<div id="pano2' . esc_attr( $id ) . '" class="pano-wrap pano-left cardboard-half" style="width: 49%; border-radius:' . esc_attr( $radius ) . ';">
2038 <div id="center-pointer2' . esc_attr( $id ) . '" class="vr-pointer-container">
2039 <span class="center-pointer"></span>
2040 </div>
2041 </div>';
2042 $html .= '<div id="pano' . esc_attr( $id ) . '" class="pano-wrap pano-right" style=" width: 100%; border-radius:' . esc_attr( $radius ) . ';">';
2043 } else {
2044
2045 $html .= '<div id="pano2' . esc_attr( $id ) . '" class="pano-wrap pano-left" style="width: 49%; border-radius:' . esc_attr( $radius ) . ';"><div id="center-pointer2' . esc_attr( $id ) . '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
2046
2047 $html .= '<div id="pano' . esc_attr( $id ) . '" class="pano-wrap pano-right" style="width: 100%; border-radius:' . esc_attr( $radius ) . ';">';
2048 }
2049 }
2050 // Vr mode transction scene to scene
2051 if ($status !== false && 'valid' == $status && $is_pro && wpvr_isMobileDevice() && $is_cardboard == 'true') {
2052 $html .= '<div id="center-pointer' . esc_attr( $id ) . '" class="vr-pointer-container" style="display:none"><span class="center-pointer"></span></div>';
2053 }
2054
2055
2056 //===company logo===//
2057 if (isset($postdata['cpLogoSwitch'])) {
2058 $cpLogoImg = $postdata['cpLogoImg'] ?? '';
2059 $cpLogoContent = $postdata['cpLogoContent'] ?? '';
2060 if ($postdata['cpLogoSwitch'] == 'on' && 'valid' == $status && $is_pro) {
2061 $html .= '<div id="cp-logo-controls">';
2062 $html .= '<div class="cp-logo-ctrl" id="cp-logo">';
2063 if ($cpLogoImg) {
2064 $html .= '<img loading="lazy" src="' . esc_attr( $cpLogoImg ) . '" alt="Company Logo">';
2065 }
2066
2067 if ($cpLogoContent) {
2068 $html .= '<div class="cp-info">' . esc_html( $cpLogoContent ) . '</div>';
2069 }
2070 $html .= '</div>';
2071 $html .= '</div>';
2072 }
2073 }
2074 //===company logo ends===//
2075
2076 //===Background Tour===//
2077 if (isset($postdata['bg_tour_enabler'])) {
2078
2079 $bg_tour_enabler = $postdata['bg_tour_enabler'];
2080 if ($bg_tour_enabler == 'on') {
2081 $bg_tour_navmenu = $postdata['bg_tour_navmenu'] ?? 'off';
2082 $bg_tour_title = $postdata['bg_tour_title'] ?? '';
2083 $bg_tour_subtitle = $postdata['bg_tour_subtitle'] ?? '';
2084
2085 if ($bg_tour_navmenu == 'on') {
2086 $menuLocations = get_nav_menu_locations();
2087 $menuID = $menuLocations['primary'];
2088 $primaryNav = wp_get_nav_menu_items($menuID);
2089
2090 if ($primaryNav) {
2091 $html .= '<div class="wpvr-navbar-container">';
2092 foreach ($primaryNav as $primaryNav_key => $primaryNav_value) {
2093 if ($primaryNav_value->menu_item_parent == "0") {
2094 $html .= '<li>';
2095 $html .= '<a href="' . esc_url( $primaryNav_value->url ) . '">' . esc_attr( $primaryNav_value->title ) . '</a>';
2096 $html .= '<ul class="wpvr-navbar-dropdown">';
2097 foreach ($primaryNav as $pm_key => $pm_value) {
2098 if ($pm_value->menu_item_parent == $primaryNav_value->ID) {
2099 $html .= '<li>';
2100 $html .= '<a href="' . esc_url( $pm_value->url ) . '">' . esc_attr( $pm_value->title ) . '</a>';
2101 $html .= '</li>';
2102 }
2103 }
2104 $html .= '</ul>';
2105 $html .= '</li>';
2106 }
2107 }
2108 $html .= '</div>';
2109 }
2110 }
2111
2112 if($is_pro && 'valid' == $status ){
2113 $html .= '<div class="wpvr-home-content">';
2114 $html .= '<div class="wpvr-home-title">' . $bg_tour_title . '</div>';
2115 $html .= '<div class="wpvr-home-subtitle">' . $bg_tour_subtitle . '</div>';
2116 $html .= '</div>';
2117 }
2118 }
2119 }
2120 //===Background Tour End===//
2121
2122 //===Custom Control===//
2123 if (isset($custom_control)) {
2124 $gyro_button_enabled = wpvr_isMobileDevice() && $custom_control['gyroSwitch'] == "on" && $custom_control['gyroscopeSwitch'] == "on";
2125 if ($custom_control['panZoomInSwitch'] == "on" || $custom_control['panZoomOutSwitch'] == "on" || $gyro_button_enabled || $custom_control['backToHomeSwitch'] == "on") {
2126 $html .= '<div id="zoom-in-out-controls' . esc_attr( $id ) . '" class="zoom-in-out-controls">';
2127
2128 if ($custom_control['backToHomeSwitch'] == "on" && 'valid' == $status && $is_pro) {
2129 $html .= '<div class="ctrl" id="backToHome' . esc_attr( $id ) . '"><i class="' . $custom_control['backToHomeIcon'] . '" style="color:' . esc_attr( $custom_control['backToHomeColor'] ) . ';"></i></div>';
2130 }
2131
2132 if ($custom_control['panZoomInSwitch'] == "on" && 'valid' == $status && $is_pro) {
2133 $html .= '<div class="ctrl" id="zoom-in' . esc_attr( $id ) . '"><i class="' . $custom_control['panZoomInIcon'] . '" style="color:' . esc_attr( $custom_control['panZoomInColor'] ) . ';"></i></div>';
2134 }
2135
2136 if ($custom_control['panZoomOutSwitch'] == "on" && 'valid' == $status && $is_pro) {
2137 $html .= '<div class="ctrl" id="zoom-out' . esc_attr( $id ) . '"><i class="' . $custom_control['panZoomOutIcon'] . '" style="color:' . esc_attr( $custom_control['panZoomOutColor'] ) . ';"></i></div>';
2138 }
2139
2140 if ($gyro_button_enabled && 'valid' == $status && $is_pro) {
2141 $html .= '<div class="ctrl" id="gyroscope' . esc_attr( $id ) . '"><i class="' . $custom_control['gyroscopeIcon'] . '" style="color:' . esc_attr( $custom_control['gyroscopeColor'] ) . ';"></i></div>';
2142 }
2143
2144 $html .= '</div>';
2145 }
2146 //===zoom in out Control===//
2147
2148 if ( ($custom_control['panupSwitch'] == "on" || $custom_control['panDownSwitch'] == "on" || $custom_control['panLeftSwitch'] == "on" || $custom_control['panRightSwitch'] == "on" || $custom_control['panFullscreenSwitch'] == "on" ) && 'valid' == $status && $is_pro) {
2149
2150 //===Custom Control===//
2151 $html .= '<div class="controls" id="controls' . esc_attr( $id ) . '">';
2152
2153 if ($custom_control['panupSwitch'] == "on") {
2154 $html .= '<div class="ctrl pan-up" id="pan-up' . esc_attr( $id ) . '"><i class="' . $custom_control['panupIcon'] . '" style="color:' . esc_attr( $custom_control['panupColor'] ) . ';"></i></div>';
2155 }
2156
2157 if ($custom_control['panDownSwitch'] == "on") {
2158 $html .= '<div class="ctrl pan-down" id="pan-down' . esc_attr( $id ) . '"><i class="' . $custom_control['panDownIcon'] . '" style="color:' . esc_attr( $custom_control['panDownColor'] ) . ';"></i></div>';
2159 }
2160
2161 if ($custom_control['panLeftSwitch'] == "on") {
2162 $html .= '<div class="ctrl pan-left" id="pan-left' . esc_attr( $id ) . '"><i class="' . $custom_control['panLeftIcon'] . '" style="color:' . esc_attr( $custom_control['panLeftColor'] ) . ';"></i></div>';
2163 }
2164
2165 if ($custom_control['panRightSwitch'] == "on") {
2166 $html .= '<div class="ctrl pan-right" id="pan-right' . esc_attr( $id ) . '"><i class="' . $custom_control['panRightIcon'] . '" style="color:' . esc_attr( $custom_control['panRightColor'] ) . ';"></i></div>';
2167 }
2168
2169 if ($custom_control['panFullscreenSwitch'] == "on") {
2170 $html .= '<div class="ctrl fullscreen" id="fullscreen' . esc_attr( $id ) . '"><i class="' . $custom_control['panFullscreenIcon'] . '" style="color:' . esc_attr( $custom_control['panFullscreenColor'] ) . ';"></i></div>';
2171 }
2172 $html .= '</div>';
2173 }
2174 }
2175
2176 //===explainer button===//
2177 $html .= wpvr_render_explainer_button(
2178 isset( $custom_control ) ? $custom_control : null,
2179 $postdata,
2180 $is_pro,
2181 $autoload,
2182 $explainer_right,
2183 $id
2184 );
2185 //===explainer button end===//
2186
2187 //===Scene navigation Control===//
2188 if (isset($postdata['scene_navigation']) && $postdata['scene_navigation'] === 'on' && 'valid' == $status && $is_pro) {
2189 $scene_navigation_nav_class = 'custom-scene-navigation-nav' . ( $is_classic_layout ? ' wpvr-scene-navigation-nav--classic' : '' );
2190 $html .= '<style>
2191 #et-boc .et-l .pnlm-controls-container,
2192 .pnlm-controls-container{
2193 top: 33px;
2194 }
2195
2196 #et-boc .et-l .zoom-in-out-controls,
2197 .zoom-in-out-controls {
2198 top: 37px;
2199 }
2200 </style>';
2201 $html .= '<div id="custom-scene-navigation' . esc_attr( $id ) . '" class="custom-scene-navigation">
2202 <span class="hamburger-menu"><svg width="16" height="10" fill="none" viewBox="0 0 22 15" xmlns="http://www.w3.org/2000/svg"><rect width="21.177" height="2.647" fill="#f7fffb" rx="1.324"/><rect width="21.177" height="2.647" y="6.177" fill="#f7fffb" rx="1.324"/><rect width="21.177" height="2.647" y="12.352" fill="#f7fffb" rx="1.324"/></svg></span>
2203 </div>
2204
2205 <div id="custom-scene-navigation-nav' . esc_attr( $id ) . '" class="' . esc_attr( $scene_navigation_nav_class ) . '">
2206 <ul></ul>
2207 </div>
2208 ';
2209 }
2210
2211 //===Scene navigation Control===//
2212
2213 /**
2214 * Generic Form Handler
2215 * Renders a generic form with modal functionality if enabled in post data
2216 *
2217 * @param array $postdata Array containing form configuration data
2218 * @param string $id Unique identifier for the form instance
2219 * @return string $html Generated HTML content
2220 */
2221
2222 // Check if generic form is enabled and validate the setting
2223 if (isset($postdata["genericform"]) && $postdata["genericform"] === 'on' && 'valid' == $status && $is_pro) {
2224
2225 // Process shortcode with fallback handling
2226 $shortcode_content = '';
2227 if (isset($postdata["genericformshortcode"]) && !empty(trim($postdata["genericformshortcode"]))) {
2228 $shortcode_content = do_shortcode( $postdata["genericformshortcode"] );
2229 } else {
2230 $shortcode_content = '<p class="error-message">No shortcode found.</p>';
2231 }
2232
2233 // Generate the form trigger button
2234 $generic_form_icon = isset($postdata['genericformicon']) ? (string) $postdata['genericformicon'] : 'fab fa-wpforms';
2235 $generic_form_icon = implode(' ', array_filter(array_map('sanitize_html_class', preg_split('/\s+/', $generic_form_icon))));
2236 $generic_form_icon = $generic_form_icon ?: 'fab fa-wpforms';
2237 $generic_form_icon_color = sanitize_hex_color($postdata['genericformiconcolor'] ?? '') ?: '#f7fffb';
2238 $html .= '<div class="generic_form_button" id="generic_form_button_' . esc_attr( $id ) . '">';
2239 $html .= '<div class="generic-form-icon" title ="Generic Form" id="generic_form_target_' . esc_attr( $id ) . '"><i class="' . esc_attr( $generic_form_icon ) . '" style="color:' . esc_attr( $generic_form_icon_color ) . ';"></i></div>';
2240 $html .= '</div>';
2241
2242 // Generate the modal form container
2243 $html .= '<div class="wpvr-generic-form" id="wpvr-generic-form' . esc_attr( $id ) . '" style="display: none">';
2244 $html .= '<span class="close-generic-form"><i class="fa fa-times"></i></span>';
2245 $html .= '<div class="generic-form-container">' . $shortcode_content . '</div>';
2246 $html .= '</div>';
2247 }
2248 //=====custom generic form=====//
2249
2250 //===Floor map button===//
2251 $status = get_option('wpvr_edd_license_status');
2252 if ($status !== false && 'valid' == $status && $is_pro) {
2253 if ($floor_plan_enable == "on" && !empty($floor_plan_image)) {
2254 $html .= '<div class="floor_map_button" id="floor_map_button_' . esc_attr( $id ) . '" style="right:' . esc_attr( $floor_map_right ) . '">';
2255 $html .= '<div class="ctrl" id="floor_map_target_' . esc_attr( $id ) . '"><i class="fas fa-map" style="color:#f7fffb;"></i></div>';
2256 $html .= '</div>';
2257 }
2258 }
2259
2260 //===floor map button===//
2261 if ($vrgallery && 'valid' == $status && $is_pro ) {
2262 //===Carousal setup===//
2263 $size = '';
2264 if ($vrgallery_icon_size) {
2265 $size = 'vrg-icon-size-large';
2266 }
2267 $html .= '<div id="vrgcontrols' . esc_attr( $id ) . '" class="vrgcontrols">';
2268
2269 $html .= '<div class="vrgctrl' . esc_attr( $id ) . ' vrbounce ' . esc_attr( $size ) . '">';
2270 $html .= '</div>';
2271 $html .= '</div>';
2272
2273 $tour_layout = is_array( $postdata['tourLayout'] ?? null )
2274 ? ( $postdata['tourLayout']['layout'] ?? 'default' )
2275 : ( $postdata['tourLayout'] ?? 'default' );
2276 $gallery_layout_class = 'layout1' === $tour_layout
2277 ? 'wpvr-gallery--modern'
2278 : 'wpvr-gallery--classic';
2279
2280 $html .= '<div id="sccontrols' . esc_attr( $id ) . '" class="scene-gallery vrowl-carousel owl-theme ' . esc_attr( $gallery_layout_class ) . '">';
2281 if (isset($panodata["scene-list"])) {
2282 foreach ($panodata["scene-list"] as $panoscenes) {
2283 $scene_key = $panoscenes['scene-id'];
2284 if ($vrgallery_title == 'on') {
2285 $scene_key_title = isset($panoscenes['scene-ititle']) ? esc_html($panoscenes['scene-ititle']) : '';
2286 } else {
2287 $scene_key_title = "";
2288 }
2289
2290 if ($panoscenes['scene-type'] == 'cubemap') {
2291 $img_src_url = $panoscenes['scene-attachment-url-face0'];
2292 } else {
2293 $img_src_url = $panoscenes['scene-attachment-url'];
2294 }
2295
2296
2297 $src_to_id = attachment_url_to_postid($img_src_url);
2298 $thumbnail_array = wp_get_attachment_image_src($src_to_id, 'thumbnail');
2299 if ($thumbnail_array) {
2300 $thumbnail = $thumbnail_array[0];
2301 } else {
2302 $thumbnail = $img_src_url;
2303 }
2304 if ( 'layout1' !== $tour_layout ) {
2305 $html .= '<ul><li title="Double click to view scene"><span class="scene-title" title="' . esc_attr($scene_key_title) . '"> ' . $scene_key_title . '</span><img loading="lazy" class="scctrl" id="' . $scene_key . '_gallery_' . $id . '" src="' . $thumbnail . '"></li></ul>';
2306 }else {
2307 $html .= '<ul><li title="Double click to view scene"><img loading="lazy" class="scctrl" id="' . $scene_key . '_gallery_' . $id . '" src="' . $thumbnail . '"><span class="scene-title" title="' . esc_attr($scene_key_title) . '">' . $scene_key_title . '</span></li></ul>';
2308 }
2309 }
2310 }
2311 $html .= '</div>';
2312 $html .= '
2313 <div class="owl-nav wpvr_slider_nav">
2314 <button type="button" role="presentation" class="owl-prev wpvr_owl_prev">
2315 <div class="nav-btn prev-slide"><i class="fa fa-angle-left"></i></div>
2316 </button>
2317 <button type="button" role="presentation" class="owl-next wpvr_owl_next">
2318 <div class="nav-btn next-slide"><i class="fa fa-angle-right"></i></div>
2319 </button>
2320 </div>
2321 ';
2322 //===Carousal setup end===//
2323 }
2324
2325 $bg_music = isset($postdata['bg_music']) ? $postdata['bg_music'] : 'off';
2326 $bg_music_url = isset($postdata['bg_music_url']) ? $postdata['bg_music_url'] : '';
2327 $autoplay_bg_music = isset($postdata['autoplay_bg_music']) ? $postdata['autoplay_bg_music'] : 'off';
2328 $loop_bg_music = isset($postdata['loop_bg_music']) ? $postdata['loop_bg_music'] : 'off';
2329
2330 $bg_loop = ($loop_bg_music === 'on') ? 'loop' : '';
2331 $autoplay_attr = ($autoplay_bg_music === 'on') ? 'autoplay' : '';
2332 $audio_muted_attr = ($autoplay_bg_music === 'on') ? 'muted' : '';
2333 $audio_icon_class = 'fa-volume-mute'; // Always start with mute icon
2334
2335 if ($bg_music === 'on' && 'valid' == $status && $is_pro) {
2336 $html .= '<div id="adcontrol' . esc_attr( $id ) . '" class="adcontrol" style="right:' . esc_attr( $audio_right ) . '">';
2337 $html .= '<audio id="vrAudio' . esc_attr($id) . '" class="vrAudioDefault" data-autoplay="' . esc_attr($autoplay_bg_music) . '" onended="audionEnd' . esc_attr($id) . '()" ' . $autoplay_attr . ' ' . $audio_muted_attr . ' ' . $bg_loop . '>
2338 <source src="' . esc_url($bg_music_url) . '" type="audio/mpeg">
2339 Your browser does not support the audio element.
2340 </audio>';
2341 $html .= '<button onclick="playPause' . esc_attr($id) . '()" class="ctrl audio_control" id="audio_control' . esc_attr($id) . '">
2342 <i id="vr-volume' . esc_attr($id) . '" class="wpvrvolumeicon' . esc_attr($id) . ' fas ' . esc_attr($audio_icon_class) . '" style="color:#fff;"></i>
2343 </button>';
2344 $html .= '</div>';
2345 }
2346
2347 //===Explainer video section===//
2348 $explainerContent = "";
2349 if (isset($postdata['explainerContent'])) {
2350 $explainerContent = wpvr_sanitize_iframe_only($postdata['explainerContent']);
2351 }
2352 $html .= '<div class="explainer" id="explainer' . esc_attr( $id ) . '" style="display: none">';
2353 $html .= '<span class="close-explainer-video"><i class="fa fa-times"></i></span>';
2354 $html .= '' . $explainerContent . '';
2355 $html .= '</div>';
2356 //===Explainer video section End===//
2357
2358 //===Floor plan section===//
2359 $floor_map_image = "";
2360 $floor_map_pointer = array();
2361 $floor_map_scene_id = '';
2362 $floor_plan_custom_color = '#cca92c';
2363 $floor_plan_direction_indicator = isset($postdata['floor_plan_direction_indicator']) ? $postdata['floor_plan_direction_indicator'] : 'on';
2364
2365 if (isset($postdata['floor_plan_attachment_url'])) {
2366 $floor_map_image = $postdata['floor_plan_attachment_url'];
2367 $floor_map_pointer = $postdata['floor_plan_pointer_position'];
2368 $floor_map_scene_id = $postdata['floor_plan_data_list'];
2369 $floor_plan_custom_color = $postdata['floor_plan_custom_color'];
2370 }
2371 $html .= '<div class="wpvr-floor-map" id="wpvr-floor-map' . $id . '" style="display: none">';
2372 $html .= '<span class="close-floor-map-plan"><i class="fa fa-times"></i></span>';
2373 $html .= '<img loading="lazy" src="' . $floor_map_image . '">';
2374
2375 foreach ($floor_map_pointer as $key => $pointer_position) {
2376 $html .= '<div class="floor-plan-pointer ui-draggable ui-draggable-handle" scene_id = "' . esc_attr( $floor_map_scene_id[$key]->value ) . '" id="' . esc_attr( $pointer_position->id ) . '" data-top="' . esc_attr( $pointer_position->data_top ) . '" data-left="' . esc_attr( $pointer_position->data_left ) . '" style="' . esc_attr( $pointer_position->style ) . '">
2377
2378 <svg class="floor-pointer-circle" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2379 <circle cx="12" cy="12" r="11.5" stroke="' . esc_attr( $floor_plan_custom_color ) . '"/>
2380 <circle cx="12" cy="12" r="5" fill="' . esc_attr( $foreground_color_pointer ) . '"/>
2381 </svg>';
2382
2383 // Only add the floor pointer flash SVG if floor_plan_direction_indicator is "on"
2384 if ($floor_plan_direction_indicator === "on") {
2385 $html .= '<svg class="floor-pointer-flash" width="54" height="35" viewBox="0 0 54 35" fill="none" xmlns="http://www.w3.org/2000/svg">
2386 <path d="M0.454054 1.32433L11.7683 34.3243C11.9069 34.7285 12.287 35 12.7143 35H41.2857C41.713 35 42.0931 34.7285 42.2317 34.3243L53.5459 1.32432C53.7685 0.675257 53.2862 0 52.6 0H1.4C0.713843 0 0.231517 0.675258 0.454054 1.32433Z" fill="url(#paint0_linear_1_10)"/>
2387 <defs>
2388 <linearGradient id="paint0_linear_1_10" x1="27" y1="4.59807e-08" x2="26.5" y2="28" gradientUnits="userSpaceOnUse">
2389 <stop stop-color="' . esc_attr( $floor_plan_custom_color ) . '" stop-opacity="0"/>
2390 <stop offset="1" stop-color="' . esc_attr( $floor_plan_custom_color ) . '"/>
2391 </linearGradient>
2392 </defs>
2393 </svg>';
2394 }
2395 $html .= '</div>';
2396 }
2397 $html .= '</div>';
2398 //===Floor plan section===//
2399
2400 $html .= '<div class="wpvr-hotspot-tweak-contents-wrapper" style="display: none">';
2401 $html .= '<i class="fa fa-times cross" data-id="' . esc_attr( $id ) . '"></i>';
2402 $html .= '<div class="wpvr-hotspot-tweak-contents-flex">';
2403 $html .= '<div class="wpvr-hotspot-tweak-contents">';
2404 ob_start();
2405 do_action('wpvr_hotspot_tweak_contents', $scene_data);
2406 $hotspot_content = ob_get_clean();
2407 $html .= $hotspot_content;
2408 $html .= '</div>';
2409 $html .= '</div>';
2410 $html .= '</div>';
2411
2412 $html .= '<div class="custom-ifram-wrapper" style="display: none;">';
2413 $html .= '<i class="fa fa-times cross" data-id="' . esc_attr( $id ) . '"></i>';
2414 $html .= '<div class="custom-ifram-flex">';
2415 $html .= '<div class="custom-ifram">';
2416 $html .= '</div>';
2417 $html .= '</div>';
2418 $html .= '</div>';
2419 $html .= '</div>';
2420 $html .= '</div>';
2421
2422
2423 if ("fullwidth" == $width) {
2424 $html .= '</div>';
2425 }
2426 if ($status !== false && 'valid' == $status && $is_pro) {
2427 $call_to_action = isset($postdata['calltoaction']) ? $postdata['calltoaction'] : 'off';
2428 if ('on' == $call_to_action) {
2429 $buttontext = isset($postdata['buttontext']) ? $postdata['buttontext'] : '';
2430 $buttonurl = isset($postdata['buttonurl']) ? $postdata['buttonurl'] : '';
2431 $cta_btn_style = isset($postdata['button_configuration']) ? $postdata['button_configuration'] : array();
2432
2433 $button_open_new_tab = isset($cta_btn_style['button_open_new_tab']) ? $cta_btn_style['button_open_new_tab'] : "off";
2434 $target = '_self';
2435 $button_position = isset($cta_btn_style['button_position']) ? $cta_btn_style['button_position'] : "";
2436 $background_color = isset($cta_btn_style['button_background_color']) ? $cta_btn_style['button_background_color'] : "";
2437 $color = isset($cta_btn_style['button_font_color']) ? $cta_btn_style['button_font_color'] : "";
2438 $font_size = isset($cta_btn_style['button_font_size']) ? $cta_btn_style['button_font_size'] : "";
2439 $font_weight = isset($cta_btn_style['button_font_weight']) ? $cta_btn_style['button_font_weight'] : "";
2440 $text_align = isset($cta_btn_style['button_alignment']) ? $cta_btn_style['button_alignment'] : "";
2441 $text_transform = isset($cta_btn_style['button_transform']) ? $cta_btn_style['button_transform'] : "";
2442 $font_style = isset($cta_btn_style['button_text_style']) ? $cta_btn_style['button_text_style'] : "";
2443 $text_decoration = isset($cta_btn_style['button_text_decoration']) ? $cta_btn_style['button_text_decoration'] : "";
2444 $line_height = isset($cta_btn_style['button_line_height']) ? $cta_btn_style['button_line_height'] : "";
2445 $letter_spacing = isset($cta_btn_style['button_letter_spacing']) ? $cta_btn_style['button_letter_spacing'] : "";
2446 $word_spacing = isset($cta_btn_style['button_word_spacing']) ? $cta_btn_style['button_word_spacing'] : "";
2447
2448 $border_width = isset($cta_btn_style['button_border_width']) ? $cta_btn_style['button_border_width'] : "";
2449 $border_style = isset($cta_btn_style['button_border_style']) ? $cta_btn_style['button_border_style'] : "";
2450 $border_color = isset($cta_btn_style['button_border_color']) ? $cta_btn_style['button_border_color'] : "";
2451 $border_radius = isset($cta_btn_style['button_border_radius']) ? $cta_btn_style['button_border_radius'] : "";
2452
2453 $button_pt = isset($cta_btn_style['button_pt']) ? $cta_btn_style['button_pt'] : "";
2454 $button_pr = isset($cta_btn_style['button_pr']) ? $cta_btn_style['button_pr'] : "";
2455 $button_pb = isset($cta_btn_style['button_pb']) ? $cta_btn_style['button_pb'] : "";
2456 $button_pl = isset($cta_btn_style['button_pl']) ? $cta_btn_style['button_pl'] : "";
2457
2458 if ($button_open_new_tab == 'on') {
2459 $target = '_blank';
2460 }
2461 $style = 'background-color: ' . esc_attr( $background_color ) . ';
2462 color: ' . esc_attr( $color ) . ';
2463 font-size: ' . esc_attr( $font_size ) . 'px;
2464 font-weight: ' . esc_attr( $font_weight ) . ';
2465 text-align: center;
2466 display: inline-block;
2467 text-transform: ' . esc_attr( $text_transform ) . ';
2468 font-style: ' . esc_attr( $font_style ) . ';
2469 text-decoration: ' . esc_attr( $text_decoration ) . ';
2470 line-height: ' . esc_attr( $line_height ) . ';
2471 letter-spacing: ' . esc_attr( $letter_spacing ) . 'px;
2472 word-spacing: ' . esc_attr( $word_spacing ) . 'px;
2473 border: ' . esc_attr( $border_width ) . 'px ' . esc_attr( $border_style ) . ' ' . esc_attr( $border_color ) . ';
2474 border-radius: ' . esc_attr( $border_radius ). 'px;
2475 padding: ' . esc_attr( $button_pt ) . 'px ' . esc_attr( $button_pr ) . 'px ' . esc_attr( $button_pb ) . 'px ' . esc_attr( $button_pl ) . 'px;
2476 ';
2477 $html .= '<div class="wpvr-call-to-action-button position-' . esc_attr( $text_align ) . '" style="max-width:' . esc_attr( $width ) . esc_attr( $width_unit ) . '">
2478 <a href="' . esc_url( $buttonurl ) . '" style="' . esc_attr( $style ) . '" target="' . esc_attr( $target ) . '">' . esc_attr( $buttontext ) . '</a>
2479 </div>';
2480 }
2481 }
2482
2483 //script started
2484
2485 $html .= '<script>';
2486 if (isset($postdata['bg_music']) && $bg_music == 'on' && 'valid' == $status && $is_pro) {
2487 $html .= '
2488 var x' . $id . ' = document.getElementById("vrAudio' . $id . '");
2489
2490 var playing' . $id . ' = false;
2491 var autoplaySupported' . $id . ' = false;
2492 var alertShown' . $id . ' = false;
2493 var autoplayChecked' . $id . ' = false;
2494
2495 function playPause' . $id . '() {
2496 if (playing' . $id . ') {
2497 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2498 x' . $id . '.pause();
2499 jQuery("#audio_control' . $id . '").attr("data-play", "off");
2500 playing' . $id . ' = false;
2501 } else {
2502 x' . $id . '.muted = false;
2503 x' . $id . '.play().then(function() {
2504 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2505 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2506 playing' . $id . ' = true;
2507 }).catch(function(e) {
2508 console.log("Play failed:", e);
2509 });
2510 }
2511 }
2512
2513 function audionEnd' . $id . '() {
2514 playing' . $id . ' = false;
2515 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2516 jQuery("#audio_control' . $id . '").attr("data-play", "off");
2517 }
2518
2519 x' . $id . '.addEventListener("ended", audionEnd' . $id . ');';
2520
2521 if ($autoplay_bg_music == 'on') {
2522 $html .= '
2523
2524 x' . $id . '.addEventListener("loadeddata", function() {
2525 if (!autoplayChecked' . $id . ') {
2526 checkAutoplayStatus' . $id . '();
2527 }
2528 });
2529
2530 x' . $id . '.addEventListener("canplay", function() {
2531 if (!autoplayChecked' . $id . ') {
2532 checkAutoplayStatus' . $id . '();
2533 }
2534 });
2535
2536 x' . $id . '.addEventListener("canplaythrough", function() {
2537 if (!autoplayChecked' . $id . ') {
2538 checkAutoplayStatus' . $id . '();
2539 }
2540 });
2541
2542 setTimeout(function() {
2543 if (!autoplayChecked' . $id . ') {
2544 checkAutoplayStatus' . $id . '();
2545 }
2546 }, 1000);
2547
2548 x' . $id . '.addEventListener("play", function() {
2549 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2550 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2551 playing' . $id . ' = true;
2552 });
2553
2554 x' . $id . '.addEventListener("pause", function() {
2555 if (!playing' . $id . ') {
2556 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2557 jQuery("#audio_control' . $id . '").attr("data-play", "off");
2558 }
2559 });
2560
2561 function checkAutoplayStatus' . $id . '() {
2562 autoplayChecked' . $id . ' = true;
2563
2564 x' . $id . '.muted = true;
2565 var playPromise = x' . $id . '.play();
2566
2567 if (playPromise !== undefined) {
2568 playPromise.then(function () {
2569 if (x' . $id . '.muted || x' . $id . '.volume === 0) {
2570 handleAutoplayBlocked' . $id . '();
2571 } else {
2572 autoplaySupported' . $id . ' = true;
2573 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2574 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2575 playing' . $id . ' = true;
2576 }
2577 }).catch(function () {
2578 handleAutoplayBlocked' . $id . '();
2579 });
2580 } else {
2581 setTimeout(function () {
2582 if (x' . $id . '.paused || x' . $id . '.currentTime === 0) {
2583 handleAutoplayBlocked' . $id . '();
2584 } else {
2585 autoplaySupported' . $id . ' = true;
2586 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2587 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2588 playing' . $id . ' = true;
2589 }
2590 }, 300);
2591 }
2592 }
2593
2594 function handleAutoplayBlocked' . $id . '() {
2595 autoplaySupported' . $id . ' = false;
2596 if (!alertShown' . $id . ') {
2597 alert("Autoplay is not supported in your browser. Please click the audio button to play music.");
2598 alertShown' . $id . ' = true;
2599 }
2600
2601 x' . $id . '.pause();
2602 x' . $id . '.currentTime = 0;
2603 x' . $id . '.muted = true;
2604
2605 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2606 jQuery("#audio_control' . $id . '").attr("data-play", "off");
2607
2608 document.getElementById("pano' . $id . '").addEventListener("click", musicPlay' . $id . ');
2609 document.addEventListener("touchstart", musicPlay' . $id . ', { once: true });
2610 document.addEventListener("click", musicPlay' . $id . ', { once: true });
2611 }
2612
2613 function musicPlay' . $id . '() {
2614 x' . $id . '.muted = false;
2615 var playPromise = x' . $id . '.play();
2616
2617 if (playPromise !== undefined) {
2618 playPromise.then(function () {
2619 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2620 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2621 playing' . $id . ' = true;
2622 }).catch(function(e) {
2623 console.log("Play failed:", e);
2624 });
2625 } else {
2626 setTimeout(function () {
2627 if (!x' . $id . '.paused) {
2628 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2629 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2630 playing' . $id . ' = true;
2631 }
2632 }, 100);
2633 }
2634
2635 document.getElementById("pano' . $id . '").removeEventListener("click", musicPlay' . $id . ');
2636 document.removeEventListener("touchstart", musicPlay' . $id . ');
2637 document.removeEventListener("click", musicPlay' . $id . ');
2638 }
2639 ';
2640 }
2641 }
2642 $html .= 'jQuery(document).ready(function() {';
2643 $html .= 'var response = ' . $response . ';';
2644 $html .= 'var scenes = response[1];';
2645 $html .= 'if(scenes) {';
2646 $html .= 'var scenedata = scenes.scenes;';
2647 $html .= 'for(var i in scenedata) {';
2648 $html .= 'var scenehotspot = scenedata[i].hotSpots;';
2649 $html .= 'for(var i = 0; i < scenehotspot.length; i++) {';
2650 $html .= 'if(scenehotspot[i].type === "info") {';
2651 $html .= ' scenehotspot[i]["clickHandlerFunc"] = function(div, args) { if (typeof window.wpvrhotspot === "function") { window.wpvrhotspot(div, args); } };';
2652 $html .= '} else if(scenehotspot[i].type === "scene") {';
2653 $html .= ' scenehotspot[i]["clickHandlerArgs"] = scenehotspot[i]["text"];';
2654 $status = get_option('wpvr_edd_license_status');
2655 if ($status !== false && $status == 'valid') {
2656 $html .='if(typeof wpvr_public !== "undefined" && wpvr_public.is_pro_active) {';
2657 $html .= ' scenehotspot[i]["clickHandlerFunc"] = function(div, args) { if (typeof wpvrhotspotscene === "function") { wpvrhotspotscene(div, args); } else if (typeof window.wpvrhotspotscene === "function") { window.wpvrhotspotscene(div, args); } };';
2658 $html .='}';
2659 }
2660 $html .= '}';
2661 if (wpvr_isMobileDevice() && get_option('dis_on_hover') == "true") {
2662 } else {
2663 $html .= 'if(scenehotspot[i]["createTooltipArgs"] != "") {';
2664 $html .= 'scenehotspot[i]["createTooltipFunc"] = function(div, args) { if (typeof window.wpvrtooltip === "function") { window.wpvrtooltip(div, args); } };';
2665 $html .= '}';
2666 }
2667 $html .= '}';
2668 $html .= '}';
2669 $html .= '}';
2670 $html .= 'var panoshow' . $id . ';';
2671 $html .= 'var panoshow2' . $id . ';';
2672 $html .= 'function initWPVRViewer' . $id . '() {';
2673 $html .= 'if (typeof pannellum === "undefined" || typeof jQuery === "undefined") { setTimeout(initWPVRViewer' . $id . ', 50); return; }';
2674 $html .= 'panoshow' . $id . ' = pannellum.viewer(response[0]["panoid"], scenes);';
2675 $html .= '
2676 window.wpvrViewers = window.wpvrViewers || {};
2677 window.wpvrViewers[response[0]["panoid"]] = panoshow' . $id . ';
2678 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
2679 detail: { containerId: response[0]["panoid"], viewer: panoshow' . $id . ' }
2680 }));
2681 ';
2682 if ( (float) $scene_fade_duration > 0 ) {
2683 $html .= '
2684 panoshow' . $id . '.on("scenechange", function() {
2685 var fadeImage = document.querySelector("#pano' . $id . ' .pnlm-render-container > .pnlm-fade-img");
2686 if (fadeImage) {
2687 fadeImage.style.opacity = "1";
2688 void fadeImage.offsetWidth;
2689 }
2690 });';
2691 }
2692 $html .= '
2693 if(typeof wpvr_public === "undefined" || !wpvr_public.is_pro_active || !wpvr_public.is_license_active) {
2694 panoshow' . $id . '.on("load", function() {
2695 jQuery(".pnlm-panorama-info").hide();
2696 jQuery(".pnlm-compass").hide();
2697 });
2698
2699 panoshow' . $id . '.on("scenechange", function() {
2700 jQuery(".pnlm-panorama-info").hide();
2701 jQuery(".pnlm-compass").hide();
2702 });
2703 }';
2704 $html .= '}';
2705 $html .= 'initWPVRViewer' . $id . '();';
2706
2707 //===Dplicate mode only for vr mode===//
2708 $response2 = json_decode($response);
2709 $response2[1]->compass = false;
2710 $response2[1]->autoRotate = false;
2711 $response = json_encode($response2);
2712 $html .= 'var response_duplicate = ' . $response . ';';
2713 $html .= 'var scenes_duplicate = response_duplicate[1];';
2714
2715 $html .= 'if(scenes_duplicate) {';
2716 $html .= 'var scenedata = scenes_duplicate.scenes;';
2717 $html .= 'for(var i in scenedata) {';
2718 $html .= 'var scenehotspot = scenedata[i].hotSpots;';
2719 $html .= 'for(var i = 0; i < scenehotspot.length; i++) {';
2720 $html .= 'if(scenehotspot[i]["clickHandlerArgs"] != "") {';
2721 $html .= 'scenehotspot[i]["clickHandlerFunc"] = function(div, args) { if (typeof window.wpvrhotspot === "function") { window.wpvrhotspot(div, args); } };';
2722 $html .= '}';
2723 if (wpvr_isMobileDevice() && get_option('dis_on_hover') == "true") {
2724 } else {
2725 $html .= 'if(scenehotspot[i]["createTooltipArgs"] != "") {';
2726 $html .= 'scenehotspot[i]["createTooltipFunc"] = function(div, args) { if (typeof window.wpvrtooltip === "function") { window.wpvrtooltip(div, args); } };';
2727 $html .= '}';
2728 }
2729 $html .= '}';
2730 $html .= '}';
2731 $html .= '}';
2732 $html .= 'var vr_mode = "off";';
2733 $status = get_option('wpvr_edd_license_status');
2734 if ($status !== false && 'valid' == $status && $is_pro) {
2735 $html .= 'function initWPVRViewer2' . $id . '() {';
2736 $html .= 'if (typeof pannellum === "undefined" || typeof jQuery === "undefined") { setTimeout(initWPVRViewer2' . $id . ', 50); return; }';
2737 $html .= 'panoshow2' . $id . ' = pannellum.viewer("pano2' . $id . '", scenes_duplicate);';
2738 $html .= '
2739 window.wpvrViewers = window.wpvrViewers || {};
2740 window.wpvrViewers["pano2' . $id . '"] = panoshow2' . $id . ';
2741 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
2742 detail: { containerId: "pano2' . $id . '", viewer: panoshow2' . $id . ' }
2743 }));
2744 ';
2745 $html .= '}';
2746 $html .= 'initWPVRViewer2' . $id . '();';
2747
2748 // Show Cardboard Mode in Tour
2749 $html .= '
2750 var tim;
2751 var im = 0;
2752 var active_scene = "' . $default_scene . '";
2753 var c_time;
2754 c_time = new Date();
2755 var timer = c_time.getTime() + 2000;
2756 function panoShowCardBoardOnTrigger(data){
2757 if(scenes_duplicate) {
2758 var scenedata = scenes_duplicate.scenes;
2759 for(var i in scenedata) {
2760 if(active_scene === i) {
2761 var scenehotspot = scenedata[i].hotSpots;
2762 for(var j in scenehotspot) {
2763 var plusFiveYaw = Math.round(scenehotspot[j].yaw) + 5;
2764 var minusFiveYaw = Math.round(scenehotspot[j].yaw) - 5;
2765 var plusFivePitch = Math.round(scenehotspot[j].pitch) + 5;
2766 var minusFivePitch = Math.round(scenehotspot[j].pitch) - 5;
2767 var firstCondition = ( Math.round(data.pitch) > minusFivePitch) && (Math.round(data.pitch) < plusFivePitch) ;
2768 var secCondition = (Math.round(data.yaw) > minusFiveYaw) && (Math.round(data.yaw) < plusFiveYaw);
2769 if(( Math.round(data.pitch) > minusFivePitch) && (Math.round(data.pitch) < plusFivePitch) ){
2770 if((Math.round(data.yaw) > minusFiveYaw) && (Math.round(data.yaw) < plusFiveYaw)){
2771 jQuery(".center-pointer").addClass("wpvr-pluse-effect")
2772 var getScene = scenehotspot[j].sceneId;
2773 if(scenehotspot[j].type == "scene"){
2774 panoshow' . $id . '.loadScene(getScene);
2775 panoshow2' . $id . '.loadScene(getScene);
2776 // var inside_current_time_object = new Date();
2777 // var inside_timer = inside_current_time_object.getTime();
2778 // if(inside_timer > timer) {
2779 // panoshow' . $id . '.loadScene(getScene);
2780 // panoshow2' . $id . '.loadScene(getScene);
2781 // jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2782 // }
2783 }else{
2784 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2785 }
2786 }
2787 else {
2788 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2789 c_time = new Date();
2790 timer = c_time.getTime() + 2000;
2791 }
2792 }
2793 else {
2794 c_time = new Date();
2795 timer = c_time.getTime() + 2000;
2796 }
2797 }
2798 }
2799 }
2800 }
2801 };
2802
2803 function vrDeviseOrientation(){
2804 var data = {
2805 pitch: panoshow' . $id . '.getPitch(),
2806 yaw: panoshow' . $id . '.getYaw(),
2807 };
2808 panoShowCardBoardOnTrigger(data);
2809 }
2810 ';
2811 $html .= '
2812
2813 function requestFullScreen(){
2814 var elem = document.getElementById("master-container");
2815 if (elem.requestFullscreen) {
2816 elem.requestFullscreen();
2817 } else if (elem.webkitRequestFullscreen) { /* Safari */
2818 elem.webkitRequestFullscreen();
2819 } else if (elem.msRequestFullscreen) { /* IE11 */
2820 elem.msRequestFullscreen();
2821 }
2822 }
2823 function requestExitFullscreen(){
2824 var elem = document.getElementById("master-container");
2825 if (document.exitFullscreen) {
2826 document.exitFullscreen();
2827 } else if (document.webkitExitFullscreen) { /* Safari */
2828 document.webkitExitFullscreen();
2829 } else if (document.msExitFullscreen) { /* IE11 */
2830 document.msExitFullscreen();
2831 }
2832 }
2833 jQuery(document).on("click",".fullscreen-button .expand",function() {
2834 jQuery(this).hide()
2835 jQuery(this).parent().find(".compress").show()
2836 requestFullScreen()
2837 screen.orientation.lock("landscape-primary")
2838 .then(function() {
2839 })
2840 .catch(function(error) {
2841 alert("Not Supported for this devise");
2842 });
2843
2844 });
2845 jQuery(document).on("click",".fullscreen-button .compress",function() {
2846 jQuery(this).hide()
2847 jQuery(this).parent().find(".expand").show()
2848 requestExitFullscreen()
2849 screen.orientation.unlock();
2850
2851 });
2852
2853 let onLoadAnalytics = false;
2854 let sceneLoadAnalytics = false;
2855 function storeAnalyticsData(data) {
2856 if(typeof wpvr_public !== "undefined" && wpvr_public.is_pro_active) {
2857 jQuery.ajax({
2858 url: wpvrAnalyticsObj.ajaxUrl,
2859 type: "POST",
2860 data: {
2861 action: "store_scene_hotspot_data",
2862 scene_id: data.scene_id,
2863 tour_id: data.tour_id,
2864 type: data.type,
2865 hotspot_id: data.hotspot_id || "",
2866 user_agent: navigator.userAgent,
2867 device_type: getDeviceType() || "desktop",
2868 nonce: wpvrAnalyticsObj.nonce,
2869 },
2870 success: function (response) {
2871 console.log("Data stored successfully");
2872 },
2873 error: function (error) {
2874 console.log("Error in storing data");
2875 }
2876 });
2877 }
2878 }
2879
2880 function getDeviceType() {
2881 const userAgent = navigator.userAgent.toLowerCase();
2882
2883 if (/mobile|android|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent)) {
2884 return "mobile";
2885 } else if (/tablet|ipad/i.test(userAgent)) {
2886 return "tablet";
2887 } else {
2888 return "desktop";
2889 }
2890 }
2891
2892 panoshow' . $id . '.on("scenechange", function(scene) {
2893 onLoadAnalytics = true;
2894 sceneLoadAnalytics = true;
2895 let scene_id = scene;
2896 let tour_id = ' . $id . ';
2897 let type = "scene";
2898 let hotspot_id = "";
2899 let user_agent = navigator.userAgent;
2900 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2901 storeAnalyticsData({
2902 scene_id: scene_id,
2903 tour_id: tour_id,
2904 type: type,
2905 hotspot_id: hotspot_id,
2906 user_agent: user_agent,
2907 device_type: device_type,
2908 });
2909 if(typeof wpvr_public === "undefined" || !wpvr_public.is_pro_active) {
2910 jQuery(".pnlm-panorama-info").hide();
2911 setTimeout(function() {
2912 jQuery(".pnlm-panorama-info").each(function() {
2913 jQuery(this).hide();
2914 });
2915 }, 500);
2916 }
2917 });
2918
2919 panoshow' . $id . '.on("load", function() {
2920 let scene_id = panoshow' . $id . '.getScene();
2921 let tour_id = ' . $id . ';
2922 let type = "scene";
2923 let hotspot_id = "";
2924 let user_agent = navigator.userAgent;
2925 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2926 if(!onLoadAnalytics && !sceneLoadAnalytics){
2927 storeAnalyticsData({
2928 scene_id: scene_id,
2929 tour_id: tour_id,
2930 type: type,
2931 hotspot_id: hotspot_id,
2932 user_agent: user_agent,
2933 device_type: device_type,
2934 });
2935 }
2936 if(typeof wpvr_public === "undefined" || !wpvr_public.is_pro_active) {
2937 jQuery(".pnlm-panorama-info").hide();
2938 setTimeout(function() {
2939 jQuery(".pnlm-panorama-info").each(function() {
2940 jQuery(this).hide();
2941 });
2942 }, 500);
2943 }
2944 })
2945
2946 function wpvrhotspotscene(hotSpotDiv, args) {
2947 onLoadAnalytics = true;
2948 let scene_id = panoshow' . $id . '.getScene();
2949 let tour_id = ' . $id . ';
2950 let type = "hotspot";
2951 let hotspot_id = args;
2952 let user_agent = navigator.userAgent;
2953 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2954 storeAnalyticsData({
2955 scene_id: scene_id,
2956 tour_id: tour_id,
2957 type: type,
2958 hotspot_id: hotspot_id,
2959 user_agent: user_agent,
2960 device_type: device_type
2961 });
2962 }';
2963
2964 $html .= '
2965 panoshow' . $id . '.on("scenechange", function (scene){
2966 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2967 active_scene = scene;
2968 });
2969 var compassBlock = "";
2970 var infoBlock = "";
2971 var getValue = "";
2972 jQuery(document).on("click",".vr_mode_change' . $id . '",function (){
2973
2974 jQuery("#pano2' . $id . ' .pnlm-load-button").trigger("click");
2975 jQuery("#pano' . $id . ' .pnlm-load-button").trigger("click");
2976
2977 getValue = jQuery(this).val();
2978 var getParent = jQuery(this).parent().parent();
2979 var fullWidthParent = getParent.parent();
2980 var compass = getParent.find("#pano2' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display");
2981 var panoInfo = getParent.find("#pano' . $id . ' .pnlm-panorama-info").css("display");
2982 if(compass == "block"){
2983 compassBlock = "block";
2984 }
2985 if(panoInfo == "block"){
2986 infoBlock = "block";
2987 }
2988 if (getValue == "off") {
2989 requestFullScreen()
2990 screen.orientation.lock("landscape-primary")
2991 .then(function() {
2992 })
2993 .catch(function(error) {
2994 alert("VR Glass Mode not supported in this device");
2995 });
2996 getParent.find(".pano-wrap").addClass("wpvr-cardboard-disable-event");
2997 // localStorage.setItem("vr_mode", "on");
2998 vr_mode = "on";
2999 jQuery(".vr-mode-title").show();
3000 jQuery(this).val("on");
3001 getParent.find("#pano2' . $id . '").css({
3002 "opacity": "1",
3003 "visibility": "visible",
3004 "position": "relative",
3005 });
3006 gyroSwitch = true;
3007 panoshow' . $id . '.startOrientation();
3008 panoshow2' . $id . '.startOrientation();
3009 panoshow2' . $id . '.setPitch(panoshow' . $id . '.getPitch(), 0);
3010 panoshow2' . $id . '.setYaw(panoshow' . $id . '.getYaw(), 0);
3011 getParent.find("#pano' . $id . ' #zoom-in-out-controls' . $id . '").hide();
3012 getParent.find("#pano' . $id . ' #controls' . $id . '").hide();
3013 getParent.find("#pano' . $id . ' #explainer_button_' . $id . '").hide();
3014 getParent.find("#pano' . $id . ' #generic_form_button_' . $id . '").hide();
3015 getParent.find("#pano' . $id . ' #floor_map_button_' . $id . '").hide();
3016 getParent.find("#pano' . $id . ' #vrgcontrols' . $id . '").hide();
3017 getParent.find("#pano' . $id . ' #sccontrols' . $id . '").hide();
3018 getParent.find("#pano' . $id . ' #adcontrol' . $id . '").hide();
3019 getParent.find("#pano' . $id . ' .owl-nav.wpvr_slider_nav").hide();
3020 getParent.find("#pano' . $id . ' #cp-logo-controls").hide();
3021
3022 getParent.find("#pano' . $id . ' #custom-scene-navigation' . $id . '").hide();
3023
3024 getParent.find("#pano2' . $id . ' .pnlm-controls-container").hide();
3025 getParent.find("#pano' . $id . ' .pnlm-controls-container").hide();
3026
3027 getParent.find("#pano2' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").hide();
3028 getParent.find("#pano' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").hide();
3029
3030 getParent.find("#pano2' . $id . ' .pnlm-panorama-info").hide();
3031 getParent.find("#pano' . $id . ' .pnlm-panorama-info").hide();
3032 getParent.find("#pano' . $id . '").addClass("cardboard-half");
3033
3034 getParent.find("#center-pointer' . $id . '").show();
3035 getParent.find(".fullscreen-button").hide();
3036
3037
3038 if (window.DeviceOrientationEvent) {
3039 window.addEventListener("deviceorientation", vrDeviseOrientation);
3040 }
3041
3042 panoshow' . $id . '.on("mousemove", function (data){
3043 panoshow2' . $id . '.setPitch(data.pitch, 0);
3044 panoshow2' . $id . '.setYaw(data.yaw, 0);
3045 panoShowCardBoardOnTrigger(data);
3046
3047 });
3048 panoshow2' . $id . '.on("mousemove", function (data){
3049 panoshow2' . $id . '.setPitch(data.pitch, 0);
3050 panoshow' . $id . '.setYaw(data.yaw, 0);
3051 panoShowCardBoardOnTrigger(data);
3052
3053 });
3054
3055 panoshow' . $id . '.on("zoomchange", function (data){
3056 panoshow2' . $id . '.setHfov(data, 0);
3057 });
3058
3059 panoshow2' . $id . '.on("zoomchange", function (data){
3060 panoshow' . $id . '.setHfov(data, 0);
3061 });
3062
3063 panoshow' . $id . '.on("touchmove", function (data){
3064 panoshow' . $id . '.stopOrientation();
3065 panoshow2' . $id . '.stopOrientation();
3066 panoshow2' . $id . '.setPitch(data.pitch, 0);
3067 panoshow2' . $id . '.setYaw(data.yaw, 0);
3068 panoShowCardBoardOnTrigger(data);
3069
3070 });
3071
3072 panoshow2' . $id . '.on("touchmove", function (data){
3073 panoshow' . $id . '.stopOrientation();
3074 panoshow2' . $id . '.stopOrientation();
3075 panoshow' . $id . '.setPitch(data.pitch, 0);
3076 panoshow' . $id . '.setYaw(data.yaw, 0);
3077 panoShowCardBoardOnTrigger(data);
3078
3079 });
3080
3081 }
3082 else if(getValue == "on") {
3083 screen.orientation.unlock();
3084 requestExitFullscreen();
3085 // localStorage.setItem("vr_mode", "off");
3086 vr_mode = "off";
3087 jQuery(".vr-mode-title").hide();
3088 jQuery(this).val("off");
3089 getParent.find("#pano2' . $id . '").css({
3090 "opacity": "0",
3091 "visibility": "hidden",
3092 "position": "absolute",
3093 });
3094 panoshow' . $id . '.stopOrientation();
3095 panoshow2' . $id . '.stopOrientation();
3096 getParent.find(".pano-wrap").removeClass("wpvr-cardboard-disable-event");
3097 getParent.find("#pano' . $id . ' #zoom-in-out-controls' . $id . '").show();
3098 getParent.find("#pano' . $id . ' #controls' . $id . '").show();
3099 getParent.find("#pano' . $id . ' #explainer_button_' . $id . '").show();
3100 getParent.find("#pano' . $id . ' #generic_form_button_' . $id . '").show();
3101 getParent.find("#pano' . $id . ' #floor_map_button_' . $id . '").show();
3102
3103 getParent.find("#pano2' . $id . ' .pnlm-controls-container").show();
3104 getParent.find("#pano' . $id . ' .pnlm-controls-container").show();
3105 getParent.find("#pano' . $id . ' #vrgcontrols' . $id . '").show();
3106 getParent.find("#pano' . $id . ' #sccontrols' . $id . '").hide();
3107 getParent.find("#pano' . $id . ' #adcontrol' . $id . '").show();
3108 getParent.find("#pano' . $id . ' .owl-nav.wpvr_slider_nav").hide();
3109 getParent.find("#pano' . $id . ' #cp-logo-controls").show();
3110 getParent.find("#pano' . $id . ' #custom-scene-navigation' . $id . '").show();
3111
3112 if(compassBlock == "block"){
3113 getParent.find("#pano2' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").show();
3114 getParent.find("#pano' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").show();
3115 }
3116 if(infoBlock == "block"){
3117 getParent.find("#pano2' . $id . ' .pnlm-panorama-info").show();
3118 getParent.find("#pano' . $id . ' .pnlm-panorama-info").show();
3119 }
3120
3121 getParent.find("#pano' . $id . '").removeClass("cardboard-half");
3122 getParent.find("#center-pointer' . $id . '").hide();
3123 getParent.find(".fullscreen-button").hide();
3124 panoshow' . $id . '.off("mousemove");
3125 panoshow' . $id . '.off("touchmove");
3126 panoshow2' . $id . '.off("mousemove");
3127 panoshow2' . $id . '.off("touchmove");
3128 if (window.DeviceOrientationEvent) {
3129 window.removeEventListener("deviceorientation", vrDeviseOrientation);
3130 }
3131 }
3132 });';
3133
3134 $html .= 'panoshow2' . $id . '.on("load", function (){
3135 // if(localStorage.getItem("vr_mode") == "off") {
3136 if( vr_mode == "off") {
3137 jQuery(".vr-mode-title").hide();
3138 }
3139 else {
3140 jQuery("#pano2' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
3141 jQuery("#pano' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
3142 jQuery("#pano2' . $id . ' .pnlm-panorama-info").hide();
3143 jQuery("#pano' . $id . ' .pnlm-panorama-info").hide();
3144 jQuery(".vr-mode-title").show();
3145 }
3146 });';
3147 }
3148
3149 $html .= 'jQuery("#pano' . $id . ' .wpvr-floor-map .floor-plan-pointer").on("click",function(){
3150 var scene_id = jQuery(this).attr("scene_id");
3151 panoshow' . $id . '.loadScene(scene_id)
3152 jQuery(".floor-plan-pointer").removeClass("add-pulse")
3153 jQuery(this).addClass("add-pulse")
3154 });';
3155
3156 if ($scene_animation_enabled && is_plugin_active('wpvr-pro/wpvr-pro.php') ) {
3157 $animation_js = apply_filters('wpvr_scene_animation_js', $id, $animation_type, $animationDuration, $animationDelay);
3158 if (!empty($animation_js)) {
3159 $html .= $animation_js;
3160 $html .= 'panoshow' . $id . '.on("load", function (scene){
3161 if (typeof changeScene === "function") {
3162 changeScene();
3163 } else {
3164 console.warn("changeScene function is not defined.");
3165 }
3166 });';
3167 }
3168 }
3169
3170
3171 $html .= '
3172 panoshow' . $id . '.on("mousemove", function (data){
3173 jQuery(".add-pulse").css({"transform":"rotate("+data.yaw+"deg)"});
3174 });
3175 ';
3176
3177
3178
3179 $status = get_option('wpvr_edd_license_status');
3180 if ($status !== false && 'valid' == $status && $is_pro) {
3181 $html .= 'panoshow' . $id . '.on("scenechange", function (scene){
3182 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
3183 jQuery(".floor-plan-pointer").each(function(index ,element){
3184 var scene_id = jQuery(this).attr("scene_id");
3185 if( active_scene == scene_id ){
3186 jQuery(".floor-plan-pointer").removeClass("add-pulse")
3187 jQuery(this).addClass("add-pulse")
3188 }
3189 });
3190
3191 });';
3192 $html .= 'panoshow' . $id . '.on("load", function (){
3193 if(jQuery(".floor-plan-pointer").length > 0){
3194 jQuery(".floor-plan-pointer").each(function(index ,element){
3195 var scene_id = jQuery(this).attr("scene_id");
3196 if( active_scene == scene_id ){
3197 jQuery(".floor-plan-pointer").removeClass("add-pulse")
3198 jQuery(this).addClass("add-pulse")
3199 }
3200 });
3201 }
3202 });';
3203 }
3204
3205 if ($status !== false && 'valid' == $status && $is_pro) {
3206 $scene_navigation_content_type = isset($postdata['scene_navigation_content_type']) ? $postdata['scene_navigation_content_type'] : 'scene_id';
3207 $html .= '
3208 jQuery("#pano' . $id . ' .custom-scene-navigation").on("click",function(){
3209 jQuery("#custom-scene-navigation-nav' . $id . ' ul").empty()
3210 if(scenes){
3211 var scene_navigation_content_type = ' . "'" . $scene_navigation_content_type . "'" . ';
3212 var sceneList = scenes.scenes;
3213 var getScene = panoshow' . $id . '.getScene();
3214 for (const key in sceneList) {
3215 let title;
3216 if (scene_navigation_content_type === "scene_title") {
3217 if (sceneList[key].title) {
3218 title = sceneList[key].title;
3219
3220 }else{
3221 if(title == "" || title == undefined){
3222 if (sceneList[key].panorama) {
3223 title = getImageNameWithoutExtension(sceneList[key].panorama);
3224 }
3225 }
3226 }
3227 } else if (scene_navigation_content_type === "scene_image_name") {
3228 if (sceneList[key].panorama) {
3229 title = getImageNameWithoutExtension(sceneList[key].panorama);
3230 }
3231 } else {
3232 title = key;
3233 }
3234 if (sceneList.hasOwnProperty(key)) {
3235 if( key === getScene){
3236 jQuery("#custom-scene-navigation-nav' . $id . ' ul").append("<li class=\"scene-navigation-list active\" scene_id= " + key + " >" + title + "</li>");
3237 }else{
3238 jQuery("#custom-scene-navigation-nav' . $id . ' ul").append("<li class=\"scene-navigation-list\" scene_id= " + key + " >" + title + "</li>");
3239 }
3240 }
3241 }
3242 }
3243 jQuery("#custom-scene-navigation-nav' . $id . '").toggleClass("visible");
3244 });
3245 ';
3246
3247 $html .= 'function getImageNameWithoutExtension(imageUrl) {
3248 // Split the URL by "/"
3249 var parts = imageUrl.split("/");
3250
3251 // Get the last part which contains the image name
3252 var imageNameWithExtension = parts[parts.length - 1];
3253
3254 // Split the image name by period (.)
3255 var imageNameParts = imageNameWithExtension.split(".");
3256
3257 // Remove the last part (which is the extension) and join the remaining parts
3258 var imageNameWithoutExtension = imageNameParts.slice(0, -1).join(".");
3259
3260 // Return the image name without extension
3261 return imageNameWithoutExtension;
3262 }';
3263
3264
3265 $html .= '
3266 jQuery("#pano' . $id . ' #custom-scene-navigation-nav' . $id . ' ul").on("click", "li.scene-navigation-list", function() {
3267 if (scenes) {
3268 jQuery(this).siblings("li").removeClass("active");
3269 jQuery(this).addClass("active");
3270
3271 var scene_key = jQuery(this).attr("scene_id");
3272 panoshow' . $id . '.loadScene(scene_key);
3273 }
3274 });
3275 ';
3276 }
3277
3278 //Duplicate mode only for vr mode end===//
3279 $html .= 'panoshow' . $id . '.on("load", function (){
3280
3281 // if(localStorage.getItem("vr_mode") == "off") {
3282 if( vr_mode == "off") {
3283 jQuery(".vr-mode-title").hide();
3284 }
3285 else {
3286 jQuery("#pano2' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
3287 jQuery("#pano' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
3288 jQuery("#pano2' . $id . ' .pnlm-panorama-info").hide();
3289 jQuery("#pano' . $id . ' .pnlm-panorama-info").hide();
3290 jQuery(".vr-mode-title").show();
3291 }
3292
3293
3294 if (jQuery("#pano' . $id . '").children().children(".pnlm-panorama-info:visible").length > 0) {
3295 jQuery("#controls' . $id . '").css("bottom", "80px");
3296 }
3297 else {
3298 jQuery("#controls' . $id . '").css("bottom", "5px");
3299 }
3300 });';
3301
3302
3303 $html .= '
3304 if (scenes.autoRotate) {
3305 var wpvrAutoRotateTimer' . $id . ' = null;
3306 var wpvrAutoRotateStopDelay' . $id . ' = parseInt(scenes.autoRotateStopDelay, 10) || 0;
3307 var wpvrScheduleAutoRotate' . $id . ' = function () {
3308 clearTimeout(wpvrAutoRotateTimer' . $id . ');
3309 if (wpvrAutoRotateStopDelay' . $id . ' > 0) {
3310 wpvrAutoRotateTimer' . $id . ' = setTimeout(function () {
3311 panoshow' . $id . '.stopAutoRotate();
3312 }, wpvrAutoRotateStopDelay' . $id . ');
3313 } else {
3314 wpvrAutoRotateTimer' . $id . ' = setTimeout(function () {
3315 panoshow' . $id . '.startAutoRotate(scenes.autoRotate, 0);
3316 }, 3000);
3317 }
3318 };
3319 panoshow' . $id . '.on("load", wpvrScheduleAutoRotate' . $id . ');
3320 panoshow' . $id . '.on("scenechange", wpvrScheduleAutoRotate' . $id . ');
3321 }
3322 ';
3323 $html .= 'var touchtime = 0;';
3324 if ($vrgallery) {
3325 if (isset($panodata["scene-list"])) {
3326 foreach ($panodata["scene-list"] as $panoscenes) {
3327 $scene_key = $panoscenes['scene-id'];
3328 $scene_key_gallery = $panoscenes['scene-id'] . '_gallery_' . $id;
3329 $img_src_url = $panoscenes['scene-attachment-url'];
3330 // $html .= 'document.getElementById("' . $scene_key_gallery . '").addEventListener("click", function(e) { ';
3331 // $html .= 'if (touchtime == 0) {';
3332 // $html .= 'touchtime = new Date().getTime();';
3333 // $html .= '} else {';
3334 // $html .= 'if (((new Date().getTime()) - touchtime) < 800) {';
3335 // $html .= 'panoshow' . $id . '.loadScene("' . $scene_key . '");';
3336 // $html .= 'touchtime = 0;';
3337 // $html .= '} else {';
3338 // $html .= 'touchtime = new Date().getTime();';
3339 // $html .= '}';
3340 // $html .= '}';
3341 // $html .= '});';
3342 $html .= '
3343 jQuery(document).on("click","#' . $scene_key_gallery . '",function() {
3344 panoshow' . $id . '.loadScene("' . $scene_key . '");
3345 });
3346 ';
3347 }
3348 }
3349
3350 $html .= '
3351 var owlGallery' . $id . ' = jQuery("#sccontrols' . $id . '").owlCarousel({
3352 items: 1,
3353 loop: true,
3354 nav: false,
3355 dots: false,
3356 margin: 5,
3357 stagePadding: 30
3358 });
3359 jQuery("#pano' . $id . '").on("click", ".wpvr_owl_prev", function() {
3360 owlGallery' . $id . '.trigger("prev.owl.carousel");
3361 });
3362 jQuery("#pano' . $id . '").on("click", ".wpvr_owl_next", function() {
3363 owlGallery' . $id . '.trigger("next.owl.carousel");
3364 });
3365 ';
3366 }
3367
3368
3369
3370 //===Custom Control===//
3371 if (isset($custom_control)) {
3372 if ($custom_control['panupSwitch'] == "on" && $status == 'valid' && $is_pro) {
3373 $html .= 'document.getElementById("pan-up' . $id . '").addEventListener("click", function(e) {';
3374 $html .= 'panoshow' . $id . '.setPitch(panoshow' . $id . '.getPitch() + 10);';
3375 $html .= '});';
3376 }
3377
3378 if ($custom_control['panDownSwitch'] == "on" && $status == 'valid' && $is_pro) {
3379 $html .= 'document.getElementById("pan-down' . $id . '").addEventListener("click", function(e) {';
3380 $html .= 'panoshow' . $id . '.setPitch(panoshow' . $id . '.getPitch() - 10);';
3381 $html .= '});';
3382 }
3383
3384 if ($custom_control['panLeftSwitch'] == "on" && $status == 'valid' && $is_pro) {
3385 $html .= 'document.getElementById("pan-left' . $id . '").addEventListener("click", function(e) {';
3386 $html .= 'panoshow' . $id . '.setYaw(panoshow' . $id . '.getYaw() - 10);';
3387 $html .= '});';
3388 }
3389
3390 if ($custom_control['panRightSwitch'] == "on" && $status == 'valid' && $is_pro) {
3391 $html .= 'document.getElementById("pan-right' . $id . '").addEventListener("click", function(e) {';
3392 $html .= 'panoshow' . $id . '.setYaw(panoshow' . $id . '.getYaw() + 10);';
3393 $html .= '});';
3394 }
3395
3396 if ($custom_control['panZoomInSwitch'] == "on") {
3397 $html .= 'document.getElementById("zoom-in' . $id . '").addEventListener("click", function(e) {';
3398 $html .= 'panoshow' . $id . '.setHfov(panoshow' . $id . '.getHfov() - 10);';
3399 $html .= '});';
3400 }
3401
3402 if ($custom_control['panZoomOutSwitch'] == "on") {
3403 $html .= 'document.getElementById("zoom-out' . $id . '").addEventListener("click", function(e) {';
3404 $html .= 'panoshow' . $id . '.setHfov(panoshow' . $id . '.getHfov() + 10);';
3405 $html .= '});';
3406 }
3407
3408 if ($custom_control['panFullscreenSwitch'] == "on" && $status == 'valid' && $is_pro) {
3409 $html .= 'document.getElementById("fullscreen' . $id . '").addEventListener("click", function(e) {';
3410 $html .= 'panoshow' . $id . '.toggleFullscreen();';
3411 $html .= '});';
3412 $html .= '(function() {';
3413 $html .= 'function wpvrFsChange' . $id . '() {';
3414 $html .= 'var fsIcon = document.querySelector("#fullscreen' . $id . ' i");';
3415 $html .= 'if (!fsIcon) return;';
3416 $html .= 'if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) {';
3417 $html .= 'fsIcon.classList.remove("fa-expand"); fsIcon.classList.add("fa-minimize");';
3418 $html .= '} else {';
3419 $html .= 'fsIcon.classList.remove("fa-minimize"); fsIcon.classList.add("fa-expand");';
3420 $html .= '}';
3421 $html .= '}';
3422 $html .= 'document.addEventListener("fullscreenchange", wpvrFsChange' . $id . ');';
3423 $html .= 'document.addEventListener("webkitfullscreenchange", wpvrFsChange' . $id . ');';
3424 $html .= 'document.addEventListener("mozfullscreenchange", wpvrFsChange' . $id . ');';
3425 $html .= 'document.addEventListener("MSFullscreenChange", wpvrFsChange' . $id . ');';
3426 $html .= '})();';
3427 }
3428
3429 if ($custom_control['backToHomeSwitch'] == "on" && $status == 'valid' && $is_pro) {
3430 $html .= 'document.getElementById("backToHome' . $id . '").addEventListener("click", function(e) {';
3431 $html .= 'panoshow' . $id . '.loadScene("' . $default_scene . '");';
3432 $html .= '});';
3433 }
3434
3435 if ($gyro_button_enabled && 'valid' == $status && $is_pro) {
3436 $html .= '
3437 (function() {
3438 var gyroButton = document.getElementById("gyroscope' . $id . '");
3439 var gyroIcon = gyroButton ? gyroButton.querySelector("i") : null;
3440 var activeColor = ' . wp_json_encode($custom_control['gyroscopeColor']) . ';
3441 var permissionGranted = false;
3442
3443 if (!gyroButton || !gyroIcon) {
3444 return;
3445 }
3446
3447 function updateGyroscopeState() {
3448 gyroIcon.style.color = panoshow' . $id . '.isOrientationActive()
3449 ? activeColor
3450 : "red";
3451 }
3452
3453 function startGyroscope() {
3454 if (!panoshow' . $id . '.isOrientationSupported()) {
3455 updateGyroscopeState();
3456 return;
3457 }
3458
3459 panoshow' . $id . '.startOrientation();
3460 window.setTimeout(updateGyroscopeState, 0);
3461 }
3462
3463 function requestGyroscopePermission() {
3464 var orientationEvent = window.DeviceOrientationEvent;
3465 if (orientationEvent) {
3466 if (typeof orientationEvent.requestPermission === "function") {
3467 if (!permissionGranted) {
3468 orientationEvent.requestPermission()
3469 .then(function(state) {
3470 permissionGranted = state === "granted";
3471 if (permissionGranted) {
3472 startGyroscope();
3473 } else {
3474 updateGyroscopeState();
3475 }
3476 })
3477 .catch(updateGyroscopeState);
3478 return;
3479 }
3480 }
3481 }
3482
3483 startGyroscope();
3484 }
3485
3486 panoshow' . $id . '.on("load", updateGyroscopeState);
3487 panoshow' . $id . '.on("scenechange", updateGyroscopeState);
3488
3489 gyroButton.addEventListener("click", function() {
3490 if (panoshow' . $id . '.isOrientationActive()) {
3491 panoshow' . $id . '.stopOrientation();
3492 updateGyroscopeState();
3493 return;
3494 }
3495
3496 requestGyroscopePermission();
3497 });
3498 })();';
3499 }
3500 }
3501
3502 $angle_up = '<i class="fa fa-angle-up"></i>';
3503 $angle_down = '<i class="fa fa-angle-down"></i>';
3504 $sin_qout = "'";
3505
3506 //===Explainer Script===//
3507 $html .= '
3508 jQuery(document).on("click","#explainer_button_' . $id . '",function() {
3509 jQuery("#explainer' . $id . '").slideToggle(function(){
3510 var $explainerVideoId = jQuery("#explainer' . $id . '");
3511 var $explainerVideoIframe = $explainerVideoId.find("iframe");
3512 var explainerVideoIframSrc = $explainerVideoIframe.attr("src");
3513 $explainerVideoIframe.attr("src", "");
3514 $explainerVideoIframe.attr("src", explainerVideoIframSrc);
3515 });
3516 });
3517
3518 jQuery(document).on("click", ".close-explainer-video", function() {
3519 var $explainer = jQuery(this).parent(".explainer");
3520 var $iframe = $explainer.find("iframe");
3521 var src = $iframe.attr("src");
3522 $iframe.attr("src", "");
3523 $explainer.hide();
3524 $iframe.attr("src", src);
3525 });
3526
3527 jQuery(document).on("click","#pano' . $id . '",function(event) {
3528 var isActiveModal = event.target.closest(".custom-ifram-wrapper");
3529 var isForm = event.target.closest(".wpvr-hotspot-tweak-contents");
3530 var isHotspot = event.target.closest(".pnlm-hotspot-base");
3531 if( isActiveModal == null && isForm == null && isHotspot == null){
3532 jQuery(".custom-ifram-wrapper .custom-ifram").empty();
3533 jQuery(".custom-ifram-wrapper").hide();
3534 jQuery(this).removeClass("show-modal");
3535 jQuery(".wpvr-hotspot-tweak-contents-wrapper").hide("show-modal");
3536 }else if(isForm != null){
3537 jQuery(this).addClass("show-modal");
3538 }
3539 });
3540
3541 ';
3542 //===Explainer Script End===//
3543
3544 //===generic form script===//
3545 if (isset($postdata["genericform"]) && $postdata["genericform"] === 'on') {
3546 $html .= '
3547 jQuery(document).on("click","#generic_form_button_' . $id . '",function() {
3548 jQuery("#wpvr-generic-form' . $id . '").fadeToggle();
3549 });
3550
3551 jQuery(document).on("click",".close-generic-form",function() {
3552 jQuery(this).parent(".wpvr-generic-form").fadeOut()
3553 });
3554 ';
3555 }
3556
3557 //===generic from script===//
3558
3559 //===Floor map Script===//
3560 $html .= '
3561 jQuery(document).on("click","#floor_map_button_' . $id . '",function() {
3562 jQuery("#wpvr-floor-map' . $id . '").toggle().removeClass("fullwindow");
3563 });
3564
3565 jQuery(document).on("dblclick","#wpvr-floor-map' . $id . '",function(){
3566 jQuery(this).addClass("fullwindow");
3567 jQuery(this).parents(".pano-wrap").addClass("show-modal");
3568 });
3569
3570 jQuery(document).on("click",".close-floor-map-plan",function() {
3571 jQuery(this).parent(".wpvr-floor-map").hide();
3572 jQuery(this).parent(".wpvr-floor-map").removeClass("fullwindow");
3573 jQuery(this).parents(".pano-wrap").removeClass("show-modal");
3574 });
3575
3576 ';
3577 //===Floor map Script End===//
3578
3579 if ($vrgallery_display) {
3580 if (!$autoload) {
3581 $html .= '
3582 jQuery(document).ready(function($){
3583 jQuery("#sccontrols' . $id . '").hide();
3584 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3585 jQuery("#sccontrols' . $id . '").hide();
3586 jQuery("#pano' . $id . ' .wpvr_slider_nav").hide();
3587 });
3588 ';
3589
3590 $html .= '
3591 var slide' . $id . ' = "down";
3592 jQuery(document).on("click","#vrgcontrols' . $id . '",function() {
3593
3594 if (slide' . $id . ' == "up") {
3595 jQuery(".vrgctrl' . $id . '").empty();
3596 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3597 slide' . $id . ' = "down";
3598 jQuery("#pano' . $id . ' .wpvr_slider_nav").slideToggle();
3599 jQuery("#sccontrols' . $id . '").slideToggle(function(){
3600 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3601 if (jQuery(this).is(":visible")) {
3602 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3603 "display": "flex",
3604 "justify-content": "center",
3605 "align-items": "center",
3606 "gap": "15px"
3607 });
3608 }
3609 }
3610 if (jQuery(".bricks-is-frontend").length) {
3611 if (jQuery(this).is(":visible")) {
3612 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3613 "display": "flex",
3614 "justify-content": "center",
3615 "align-items": "center"
3616 });
3617 }
3618 }
3619 });
3620 }
3621 else {
3622 jQuery(".vrgctrl' . $id . '").empty();
3623 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3624 slide' . $id . ' = "up";
3625 jQuery("#pano' . $id . ' .wpvr_slider_nav").slideToggle();
3626 jQuery("#sccontrols' . $id . '").slideToggle(function(){
3627 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3628 if (jQuery(this).is(":visible")) {
3629 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3630 "display": "flex",
3631 "justify-content": "center",
3632 "align-items": "center",
3633 "gap": "15px"
3634 });
3635 }
3636 }
3637 if (jQuery(".bricks-is-frontend").length) {
3638 if (jQuery(this).is(":visible")) {
3639 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3640 "display": "flex",
3641 "justify-content": "center",
3642 "align-items": "center"
3643 });
3644 }
3645 }
3646 });
3647 }
3648 });
3649 ';
3650 } else {
3651 $html .= '
3652 jQuery(document).ready(function($){
3653 jQuery("#sccontrols' . $id . '").show();
3654 jQuery("#pano' . $id . ' .wpvr_slider_nav").show();
3655 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3656 });
3657 ';
3658
3659 $html .= '
3660 var slide' . $id . ' = "down";
3661 jQuery(document).on("click","#vrgcontrols' . $id . '",function() {
3662
3663 if (slide' . $id . ' == "up") {
3664 jQuery(".vrgctrl' . $id . '").empty();
3665 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3666 slide' . $id . ' = "down";
3667 }
3668 else {
3669 jQuery(".vrgctrl' . $id . '").empty();
3670 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3671 slide' . $id . ' = "up";
3672 }
3673 jQuery("#pano' . $id . ' .wpvr_slider_nav").slideToggle();
3674 jQuery("#sccontrols' . $id . '").slideToggle(function(){
3675 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3676 if (jQuery(this).is(":visible")) {
3677 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3678 "display": "flex",
3679 "justify-content": "center",
3680 "align-items": "center",
3681 "gap": "15px"
3682 });
3683 }
3684 }
3685 if (jQuery(".bricks-is-frontend").length) {
3686 if (jQuery(this).is(":visible")) {
3687 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3688 "display": "flex",
3689 "justify-content": "center",
3690 "align-items": "center"
3691 });
3692 }
3693 }
3694 });
3695 });
3696 ';
3697 }
3698 } else {
3699 $html .= '
3700 jQuery(document).ready(function($){
3701 jQuery("#sccontrols' . $id . '").hide();
3702 jQuery("#pano' . $id . ' .wpvr_slider_nav").hide();
3703 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3704 });
3705 ';
3706
3707 $html .= '
3708 var slide' . $id . ' = "down";
3709 jQuery(document).on("click","#vrgcontrols' . $id . '",function() {
3710
3711 if (slide' . $id . ' == "up") {
3712 jQuery(".vrgctrl' . $id . '").empty();
3713 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3714 slide' . $id . ' = "down";
3715 }
3716 else {
3717 jQuery(".vrgctrl' . $id . '").empty();
3718 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3719 slide' . $id . ' = "up";
3720 }
3721 jQuery("#pano' . $id . ' .wpvr_slider_nav").slideToggle();
3722 jQuery("#sccontrols' . $id . '").slideToggle(function(){
3723 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3724 if (jQuery(this).is(":visible")) {
3725 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3726 "display": "flex",
3727 "justify-content": "center",
3728 "align-items": "center",
3729 "gap": "15px"
3730 });
3731 }
3732 }
3733 if (jQuery(".bricks-is-frontend").length) {
3734 if (jQuery(this).is(":visible")) {
3735 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3736 "display": "flex",
3737 "justify-content": "center",
3738 "align-items": "center"
3739 });
3740 }
3741 }
3742 });
3743 });
3744 ';
3745 }
3746
3747 if (!$autoload) {
3748 $html .= '
3749
3750 jQuery(document).ready(function(){
3751 jQuery("#controls' . $id . '").hide();
3752 jQuery("#zoom-in-out-controls' . $id . '").hide();
3753 jQuery("#adcontrol' . $id . '").hide();
3754 jQuery("#explainer_button_' . $id . '").hide();
3755 jQuery("#generic_form_button_' . $id . '").hide();
3756 jQuery("#floor_map_button_' . $id . '").hide();
3757 jQuery("#vrgcontrols' . $id . '").hide();
3758 jQuery("#cp-logo-controls").hide();
3759 jQuery(".custom-scene-navigation").hide();
3760 jQuery("#pano' . $id . '").find(".pnlm-panorama-info").hide();
3761 });
3762
3763 ';
3764
3765 if ($vrgallery_display) {
3766 $html .= 'var load_once = "true";';
3767 $html .= 'panoshow' . $id . '.on("load", function (){
3768 if (load_once == "true") {
3769 load_once = "false";
3770 jQuery("#sccontrols' . $id . '").slideToggle(function(){
3771 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3772 if (jQuery(this).is(":visible")) {
3773 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css("display", "flex");
3774 }
3775 }
3776 if (jQuery(".bricks-is-frontend").length) {
3777 if (jQuery(this).is(":visible")) {
3778 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3779 "display": "flex",
3780 "justify-content": "center",
3781 "align-items": "center"
3782 });
3783 }
3784 }
3785 });
3786 jQuery("#pano' . $id . ' .wpvr_slider_nav").slideToggle();
3787 }
3788 });';
3789 }
3790
3791 $html .= 'panoshow' . $id . '.on("load", function (){
3792 jQuery("#controls' . $id . '").show();
3793 jQuery("#zoom-in-out-controls' . $id . '").show();
3794 jQuery("#adcontrol' . $id . '").show();
3795 jQuery("#explainer_button_' . $id . '").show();
3796 jQuery("#generic_form_button_' . $id . '").show();
3797 jQuery("#floor_map_button_' . $id . '").show();
3798 jQuery("#vrgcontrols' . $id . '").show();
3799 jQuery("#cp-logo-controls").show();
3800 jQuery(".custom-scene-navigation").show();
3801 jQuery("#pano' . $id . '").find(".pnlm-panorama-info").show();
3802 });';
3803 }
3804
3805 $previewText = $postdata['previewtext'] ?? 'Click To Load Panorama';
3806 if ($previewText) {
3807 $html .= '
3808 jQuery("#pano' . $id . '").children(".pnlm-ui").find(".pnlm-load-button p").text("' . $previewText. '")
3809 ';
3810 } else {
3811 $html .= '
3812 jQuery("#pano' . $id . '").children(".pnlm-ui").find(".pnlm-load-button p").text("Click To Load Panorama")
3813 ';
3814 }
3815
3816 $html .= 'jQuery("#pano' . $id . ' .pnlm-title-box").on("mouseenter", function(){
3817 jQuery(this).attr("title", jQuery(this).text());
3818 });
3819 jQuery("#pano' . $id . ' .pnlm-title-box").on("mouseleave", function(){
3820 jQuery(this).removeAttr("title");
3821 });';
3822 $html .= '});';
3823 $html .= '</script>';
3824
3825 $tour_data = [];
3826 if(defined("WPVR_PRO_VERSION")){
3827 $tour_data = array(
3828 'explainerControlSwitch' => (
3829 isset( $postdata['explainerSwitch'] )
3830 && in_array( $postdata['explainerSwitch'], array( true, 1, '1', 'on' ), true )
3831 ) ? 'on' : 'off',
3832 'floor_plan_enable' => $floor_plan_enable ?? false,
3833 'floor_plan_image' => $floor_plan_image ?? '',
3834 'custom_control' => $custom_control ?? [],
3835 );
3836 }
3837 return apply_filters('wpvr_generate_tour_layout_html', $html ,$postdata ,$id, $tour_data);
3838 }
3839
3840 function sanitize_content_preserve_styles($content) {
3841 // Decode HTML entities first (in case content was encoded in database)
3842 $content = html_entity_decode($content, ENT_QUOTES | ENT_HTML5, 'UTF-8');
3843
3844 // Escape <script> blocks to display as text instead of removing them
3845 $content = preg_replace_callback('/<script\b[^>]*>(.*?)<\/script>/si', function($matches) {
3846 return esc_html($matches[0]); // Convert to plain text
3847 }, $content);
3848
3849 // Strip dangerous URL-based attributes
3850 $content = preg_replace('/(href|action|formaction)\s*=\s*["\']?\s*(javascript|vbscript|data|about):/i', '$1=""', $content);
3851
3852 // Escape inline event handlers (onclick, onhover, etc.) to display as text
3853 $content = preg_replace_callback('/\s*(on\w+)\s*=\s*(["\'])([^"\']*)\2/i', function($matches) {
3854 // Escape the attribute value but keep the attribute name visible as text
3855 return ' ' . esc_html($matches[1]) . '=' . $matches[2] . esc_html($matches[3]) . $matches[2];
3856 }, $content);
3857 $content = preg_replace_callback('/\s*(on\w+)\s*=\s*([^>\s]+)/i', function($matches) {
3858 // Handle unquoted event handlers
3859 return ' ' . esc_html($matches[1]) . '=' . esc_html($matches[2]);
3860 }, $content);
3861
3862 // Remove all unsafe embedded/interactive elements except iframe
3863 $content = preg_replace('/<(object|embed|applet|frame|frameset|meta|link|base|form|input|button|textarea|select|option)\b[^>]*>/i', '', $content);
3864 $content = preg_replace('/<\/(object|embed|applet|frame|frameset|meta|link|base|form|input|button|textarea|select|option)>/i', '', $content);
3865
3866 // Clean style attributes safely
3867 $content = preg_replace_callback('/style\s*=\s*["\']([^"\']*)["\']/', function($matches) {
3868 $style = $matches[1];
3869 $style = preg_replace('/expression\s*\(/i', '', $style);
3870 $style = preg_replace('/(javascript|vbscript|data|about)\s*:/i', '', $style);
3871 $style = preg_replace('/url\s*\(\s*["\']?\s*(javascript|vbscript|data):/i', '', $style);
3872 $style = preg_replace('/behavior\s*:/i', '', $style);
3873 $style = preg_replace('/-moz-binding\s*:/i', '', $style);
3874 return 'style="' . esc_attr($style) . '"';
3875 }, $content);
3876
3877 // Sanitize <style> blocks
3878 $content = preg_replace_callback('/<style\b[^>]*>(.*?)<\/style>/si', function($matches) {
3879 $css = $matches[1];
3880 $css = preg_replace('/(expression|javascript|vbscript|data|about)\s*:/i', '', $css);
3881 $css = preg_replace('/url\s*\(\s*["\']?\s*(javascript|vbscript|data):/i', '', $css);
3882 $css = preg_replace('/behavior\s*:/i', '', $css);
3883 $css = preg_replace('/-moz-binding\s*:/i', '', $css);
3884 return '<style>' . esc_html($css) . '</style>';
3885 }, $content);
3886
3887 // Allow iframes from safe sources only (e.g., YouTube, Vimeo)
3888 $allowed_tags = wp_kses_allowed_html('post');
3889 $allowed_tags['iframe'] = [
3890 'src' => true,
3891 'width' => true,
3892 'height' => true,
3893 'frameborder' => true,
3894 'allowfullscreen' => true,
3895 'class' => true,
3896 'style' => true,
3897 'title' => true,
3898 'allow' => true,
3899 'name' => true,
3900 'referrerpolicy' => true,
3901 'loading' => true,
3902 'sandbox' => true,
3903 ];
3904 $allowed_tags['img'] = [
3905 'src' => true,
3906 'alt' => true,
3907 'title' => true,
3908 'width' => true,
3909 'height' => true,
3910 'class' => true,
3911 'id' => true,
3912 'style' => true,
3913 'loading' => true,
3914 'srcset' => true,
3915 'sizes' => true,
3916 ];
3917
3918 // Apply wp_kses() to keep only allowed tags/attributes
3919 $content = wp_kses($content, $allowed_tags);
3920
3921 // Finally, validate iframe src for security (allow https only, block javascript: etc.)
3922 $content = preg_replace_callback('/<iframe[^>]+src=["\']([^"\']+)["\'][^>]*>(?:<\/iframe>)?/i', function($matches) {
3923 $src = $matches[1];
3924 // Allow any https:// or http:// URL, but block javascript:, data:, vbscript:, etc.
3925 if (preg_match('/^(https?:)?\/\//i', $src) && !preg_match('/^(javascript|data|vbscript|about):/i', $src)) {
3926 return $matches[0]; // keep safe iframe
3927 }
3928 // Strip unsafe iframe
3929 return '';
3930 }, $content);
3931
3932 return $content;
3933 }
3934 function wpvr_hex2rgb($colour)
3935 {
3936 if (isset($colour[0]) && $colour[0] == '#') {
3937 $colour = substr($colour, 1);
3938 }
3939 if (strlen($colour) == 6) {
3940 list($r, $g, $b) = array($colour[0] . $colour[1], $colour[2] . $colour[3], $colour[4] . $colour[5]);
3941 } elseif (strlen($colour) == 3) {
3942 list($r, $g, $b) = array($colour[0] . $colour[0], $colour[1] . $colour[1], $colour[2] . $colour[2]);
3943 } else {
3944 return false;
3945 }
3946 $r = hexdec($r);
3947 $g = hexdec($g);
3948 $b = hexdec($b);
3949 return array($r . ', ' . $g . ', ' . $b);
3950 }
3951
3952 function wpvr_HTMLToRGB($htmlCode)
3953 {
3954 $r = 0;
3955 $g = 0;
3956 $b = 0;
3957 if (isset($htmlCode[0]) && $htmlCode[0] == '#') {
3958 $htmlCode = substr($htmlCode, 1);
3959 }
3960
3961 if (strlen($htmlCode) == 3) {
3962 $htmlCode = $htmlCode[0] . $htmlCode[0] . $htmlCode[1] . $htmlCode[1] . $htmlCode[2] . $htmlCode[2];
3963 }
3964
3965 if (isset($htmlCode[0]) && isset($htmlCode[1])) {
3966 $r = hexdec($htmlCode[0] . $htmlCode[1]);
3967 }
3968 if (isset($htmlCode[2]) && isset($htmlCode[3])) {
3969 $g = hexdec($htmlCode[2] . $htmlCode[3]);
3970 }
3971 if (isset($htmlCode[4]) && isset($htmlCode[5])) {
3972 $b = hexdec($htmlCode[4] . $htmlCode[5]);
3973 }
3974
3975 return $b + ($g << 0x8) + ($r << 0x10);
3976 }
3977
3978 function wpvr_RGBToHSL($RGB)
3979 {
3980 $r = 0xFF & ($RGB >> 0x10);
3981 $g = 0xFF & ($RGB >> 0x8);
3982 $b = 0xFF & $RGB;
3983
3984 $r = ((float)$r) / 255.0;
3985 $g = ((float)$g) / 255.0;
3986 $b = ((float)$b) / 255.0;
3987
3988 $maxC = max($r, $g, $b);
3989 $minC = min($r, $g, $b);
3990
3991 $l = ($maxC + $minC) / 2.0;
3992
3993 if ($maxC == $minC) {
3994 $s = 0;
3995 $h = 0;
3996 } else {
3997 if ($l < .5) {
3998 $s = ($maxC - $minC) / ($maxC + $minC);
3999 } else {
4000 $s = ($maxC - $minC) / (2.0 - $maxC - $minC);
4001 }
4002 if ($r == $maxC) {
4003 $h = ($g - $b) / ($maxC - $minC);
4004 }
4005 if ($g == $maxC) {
4006 $h = 2.0 + ($b - $r) / ($maxC - $minC);
4007 }
4008 if ($b == $maxC) {
4009 $h = 4.0 + ($r - $g) / ($maxC - $minC);
4010 }
4011
4012 $h = $h / 6.0;
4013 }
4014
4015 $h = (int)round(255.0 * $h);
4016 $s = (int)round(255.0 * $s);
4017 $l = (int)round(255.0 * $l);
4018
4019 return (object) array('hue' => $h, 'saturation' => $s, 'lightness' => $l);
4020 }
4021
4022 add_action('rest_api_init', 'wpvr_rest_data_route');
4023 function wpvr_rest_data_route()
4024 {
4025 register_rest_route('wpvr/v1', '/panodata/', array(
4026 'methods' => 'GET',
4027 'callback' => 'wpvr_rest_data_set',
4028 'permission_callback' => 'wpvr_rest_route_permission'
4029 ));
4030 }
4031
4032 function wpvr_rest_route_permission()
4033 {
4034 return true;
4035 }
4036
4037 function wpvr_rest_data_set()
4038 {
4039 $query = new WP_Query(array(
4040 'post_type' => 'wpvr_item',
4041 'posts_per_page' => -1,
4042 ));
4043
4044 $wpvr_list = array();
4045 $list_none = array('value' => 0, 'label' => 'None');
4046 array_push($wpvr_list, $list_none);
4047 while ($query->have_posts()) {
4048 $query->the_post();
4049 $title = mb_convert_encoding(get_the_title(), 'UTF-8', 'HTML-ENTITIES');
4050 $post_id = get_the_ID();
4051 $title = $post_id . ' : ' . $title;
4052 $list_ob = array('value' => $post_id, 'label' => $title);
4053 array_push($wpvr_list, $list_ob);
4054 }
4055
4056 return $wpvr_list;
4057 }
4058
4059 function wpvr_isMobileDevice()
4060 {
4061 return preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i", $_SERVER["HTTP_USER_AGENT"]);
4062 }
4063
4064 function wpvr_directory()
4065 {
4066 $upload = wp_upload_dir();
4067 $upload_dir = $upload['basedir'];
4068 $upload_dir_temp = $upload_dir . '/wpvr/temp/';
4069 if (!is_dir($upload_dir_temp)) {
4070 wp_mkdir_p($upload_dir_temp, 0700);
4071 }
4072 }
4073
4074 add_action('admin_init', 'wpvr_directory');
4075
4076
4077 function wpvr_add_role_cap()
4078 {
4079 $editor_active = get_option('wpvr_editor_active');
4080
4081 $author_active = get_option('wpvr_author_active');
4082
4083 $admin = get_role('administrator');
4084 $admin->add_cap('publish_wpvr_tour');
4085 $admin->add_cap('edit_wpvr_tours');
4086 $admin->add_cap('read_wpvr_tour');
4087 $admin->add_cap('edit_wpvr_tour');
4088 $admin->add_cap('edit_wpvr_tours');
4089 $admin->add_cap('publish_wpvr_tours');
4090 $admin->add_cap('publish_wpvr_tour');
4091 $admin->add_cap('delete_wpvr_tour');
4092 $admin->add_cap('edit_other_wpvr_tours');
4093 $admin->add_cap('delete_other_wpvr_tours');
4094
4095 if ($editor_active == "true") {
4096 $editor = get_role('editor');
4097 if ($editor) {
4098 $editor->add_cap('publish_wpvr_tour');
4099 $editor->add_cap('edit_wpvr_tours');
4100 $editor->add_cap('read_wpvr_tour');
4101 $editor->add_cap('edit_wpvr_tour');
4102 $editor->add_cap('edit_wpvr_tours');
4103 $editor->add_cap('publish_wpvr_tours');
4104 $editor->add_cap('publish_wpvr_tour');
4105 $editor->add_cap('delete_wpvr_tour');
4106 $editor->add_cap('edit_other_wpvr_tours');
4107 $editor->add_cap('delete_other_wpvr_tours');
4108 }
4109 } else {
4110 $editor = get_role('editor');
4111 if ($editor) {
4112 $editor->remove_cap('publish_wpvr_tour');
4113 $editor->remove_cap('edit_wpvr_tours');
4114 $editor->remove_cap('read_wpvr_tour');
4115 $editor->remove_cap('edit_wpvr_tour');
4116 $editor->remove_cap('edit_wpvr_tours');
4117 $editor->remove_cap('publish_wpvr_tours');
4118 $editor->remove_cap('publish_wpvr_tour');
4119 $editor->remove_cap('delete_wpvr_tour');
4120 $editor->remove_cap('edit_other_wpvr_tours');
4121 $editor->remove_cap('delete_other_wpvr_tours');
4122 }
4123 }
4124
4125 if ($author_active == "true") {
4126 $author = get_role('author');
4127 if ($author) {
4128 $author->add_cap('read_wpvr_tour');
4129 $author->add_cap('edit_wpvr_tour');
4130 $author->add_cap('edit_wpvr_tours');
4131 $author->add_cap('publish_wpvr_tours');
4132 $author->add_cap('publish_wpvr_tour');
4133 $author->add_cap('delete_wpvr_tour');
4134 }
4135 } else {
4136 $author = get_role('author');
4137 if ($author) {
4138 $author->remove_cap('read_wpvr_tour');
4139 $author->remove_cap('edit_wpvr_tour');
4140 $author->remove_cap('edit_wpvr_tours');
4141 $author->remove_cap('publish_wpvr_tours');
4142 $author->remove_cap('publish_wpvr_tour');
4143 $author->remove_cap('delete_wpvr_tour');
4144 }
4145 }
4146
4147 if(is_plugin_active( 'dokan-lite/dokan.php' ) || is_plugin_active( 'dokan-pro/dokan.php' )){
4148 $dokan_vendor_active = get_option('dokan_vendor_active');
4149
4150 if( 'true' === $dokan_vendor_active){
4151 $seller = get_role('seller');
4152 if ($seller) {
4153 $seller->add_cap('read_wpvr_tour');
4154 $seller->add_cap('edit_wpvr_tour');
4155 $seller->add_cap('edit_wpvr_tours');
4156 $seller->add_cap('publish_wpvr_tours');
4157 $seller->add_cap('publish_wpvr_tour');
4158 $seller->add_cap('delete_wpvr_tour');
4159 }
4160 } else{
4161 $seller = get_role('seller');
4162 if ($seller) {
4163 $seller->remove_cap('read_wpvr_tour');
4164 $seller->remove_cap('edit_wpvr_tour');
4165 $seller->remove_cap('edit_wpvr_tours');
4166 $seller->remove_cap('publish_wpvr_tours');
4167 $seller->remove_cap('publish_wpvr_tour');
4168 $seller->remove_cap('delete_wpvr_tour');
4169 }
4170 }
4171 }
4172
4173
4174 }
4175
4176 add_action('admin_init', 'wpvr_add_role_cap', 999);
4177
4178 function wpvr_role_management_from_post_type($args, $post_type)
4179 {
4180 if ('wpvr_item' !== $post_type) {
4181 return $args;
4182 }
4183
4184 $editor_active = get_option('wpvr_editor_active');
4185 $author_active = get_option('wpvr_author_active');
4186 $user = wp_get_current_user();
4187
4188 if ($editor_active == "true") {
4189 if (in_array('editor', (array) $user->roles)) {
4190 $args['show_in_menu'] = true;
4191 }
4192 }
4193
4194 if ($author_active == "true") {
4195 if (in_array('author', (array) $user->roles)) {
4196 $args['show_in_menu'] = true;
4197 }
4198 }
4199
4200 if(is_plugin_active( 'dokan-lite/dokan.php' ) || is_plugin_active( 'dokan-pro/dokan.php' )){
4201 $dokan_vendor_active = get_option('dokan_vendor_active');
4202 if( 'true' === $dokan_vendor_active){
4203 if (in_array('seller', (array) $user->roles)) {
4204 $args['show_in_menu'] = true;
4205 }
4206 }
4207
4208 }
4209
4210 return $args;
4211 }
4212 add_filter('register_post_type_args', 'wpvr_role_management_from_post_type', 10, 2);
4213
4214 function wpvr_cache_admin_notice()
4215 {
4216 $option = get_option('wpvr_warning');
4217 if (!$option) {
4218 ?>
4219 <div class="notice notice-warning" id="wpvr-warning" style="position: relative;">
4220 <p><?php _e('Since you have updated the plugin, please clear the browser cache for smooth functioning. Follow these steps if you are using <a href="https://support.google.com/accounts/answer/32050?co=GENIE.Platform%3DDesktop&hl=en" target="_blank">Google Chrome</a>, <a href="https://support.mozilla.org/en-US/kb/how-clear-firefox-cache" target="_blank">Mozilla Firefox</a>, <a href="https://clear-my-cache.com/en/apple-mac-os/safari.html" target="_blank">Safai</a> or <a href="https://support.microsoft.com/en-us/help/10607/microsoft-edge-view-delete-browser-history" target="_blank">Microsoft Edge</a>', 'wpvr'); ?></p>
4221 <button type="button" id="wpvr-dismissible" class="notice-dismiss"><span class="screen-reader-text">Dismiss this notice.</span></button>
4222 </div>
4223 <?php
4224 }
4225 }
4226 // add_action('admin_notices', 'wpvr_cache_admin_notice');
4227
4228 //===Oxygen widget===//
4229 add_action('plugins_loaded', function () {
4230 if (!class_exists('OxyEl')) {
4231 return;
4232 }
4233 require_once __DIR__ . '/oxygen/oxy-manager.php';
4234 });
4235
4236 add_action('init', 'wpvr_mobile_media_handle');
4237 function wpvr_mobile_media_handle()
4238 {
4239 add_image_size('wpvr_mobile', 4096, 2048); //mobile
4240 }
4241
4242
4243 add_action(
4244 /**
4245 * @param $api \VisualComposer\Modules\Api\Factory
4246 */
4247 'vcv:api',
4248 function ($api) {
4249 $elementsToRegister = [
4250 'wpvrelement',
4251 ];
4252 $pluginBaseUrl = rtrim(plugins_url(basename(__DIR__)), '\\/');
4253 /** @var \VisualComposer\Modules\Elements\ApiController $elementsApi */
4254 $elementsApi = $api->elements;
4255 foreach ($elementsToRegister as $tag) {
4256 $manifestPath = __DIR__ . '/vc/' . $tag . '/manifest.json';
4257 $elementBaseUrl = $pluginBaseUrl . '/vc/' . $tag;
4258 $elementsApi->add($manifestPath, $elementBaseUrl);
4259 }
4260 }
4261 );
4262
4263 function wpvr_redirect_after_activation($plugin)
4264 {
4265 if ($plugin == plugin_basename(__FILE__)) {
4266 $url = admin_url('admin.php?page=rex-wpvr-setup-wizard');
4267 $url = esc_url($url, FILTER_SANITIZE_URL);
4268 exit(wp_safe_redirect($url));
4269 }
4270 }
4271 //add_action('activated_plugin', 'wpvr_redirect_after_activation');
4272
4273 function replace_callback($matches)
4274 {
4275 foreach ($matches as $match) {
4276 return str_replace('<img', '<img decoding="async" ', $match);
4277 }
4278 }
4279
4280
4281 function wpvr_get_explainer_embed_url( $input ) {
4282 $url = esc_url_raw( trim( (string) $input ), array( 'http', 'https' ) );
4283
4284 if ( empty( $url ) || ! preg_match( '#^https?://#i', $url ) ) {
4285 return '';
4286 }
4287
4288 $host = strtolower( (string) wp_parse_url( $url, PHP_URL_HOST ) );
4289 $host = preg_replace( '/^www\./', '', $host );
4290 $path = trim( (string) wp_parse_url( $url, PHP_URL_PATH ), '/' );
4291
4292 if ( 'youtu.be' === $host ) {
4293 $segments = explode( '/', $path );
4294 $video_id = isset( $segments[0] ) ? preg_replace( '/[^A-Za-z0-9_-]/', '', $segments[0] ) : '';
4295
4296 return $video_id ? 'https://www.youtube.com/embed/' . $video_id : '';
4297 }
4298
4299 if ( in_array( $host, array( 'youtube.com', 'm.youtube.com', 'music.youtube.com', 'youtube-nocookie.com' ), true ) ) {
4300 $video_id = '';
4301 $segments = explode( '/', $path );
4302
4303 if ( 'watch' === $path ) {
4304 $query = array();
4305 wp_parse_str( (string) wp_parse_url( $url, PHP_URL_QUERY ), $query );
4306 $video_id = isset( $query['v'] ) ? $query['v'] : '';
4307 } elseif ( isset( $segments[0], $segments[1] ) && in_array( $segments[0], array( 'embed', 'shorts', 'live' ), true ) ) {
4308 $video_id = $segments[1];
4309 }
4310
4311 $video_id = preg_replace( '/[^A-Za-z0-9_-]/', '', (string) $video_id );
4312
4313 return $video_id ? 'https://www.youtube.com/embed/' . $video_id : '';
4314 }
4315
4316 if ( 'vimeo.com' === $host || 'player.vimeo.com' === $host ) {
4317 $segments = array_reverse( array_filter( explode( '/', $path ) ) );
4318
4319 foreach ( $segments as $segment ) {
4320 if ( ctype_digit( $segment ) ) {
4321 return 'https://player.vimeo.com/video/' . $segment;
4322 }
4323 }
4324
4325 return '';
4326 }
4327
4328 return $url;
4329 }
4330
4331 function wpvr_sanitize_iframe_only( $input ) {
4332 // Start with standard allowed post HTML (p, a, strong, etc.)
4333 $allowed_tags = wp_kses_allowed_html( 'post' );
4334
4335 // Explicitly allow <iframe> with specific safe attributes
4336 $allowed_tags['iframe'] = array(
4337 'src' => true,
4338 'width' => true,
4339 'height' => true,
4340 'title' => true,
4341 'frameborder' => true,
4342 'allow' => true,
4343 'allowfullscreen' => true,
4344 'referrerpolicy' => true,
4345 );
4346
4347 $content = trim( (string) $input );
4348
4349 if ( '' === $content ) {
4350 return '';
4351 }
4352
4353 if ( false === stripos( $content, '<iframe' ) ) {
4354 $embed_url = wpvr_get_explainer_embed_url( $content );
4355
4356 if ( $embed_url ) {
4357 $content = sprintf(
4358 '<iframe src="%s" width="100%%" height="100%%" title="Explainer video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen referrerpolicy="strict-origin-when-cross-origin"></iframe>',
4359 esc_url( $embed_url )
4360 );
4361 }
4362 }
4363
4364 return wp_kses( $content, $allowed_tags );
4365 }
4366