Selaa lähdekoodia

更换1.2.1-kr

gemercheung 1 vuosi sitten
vanhempi
commit
5d25471e16
44 muutettua tiedostoa jossa 4670 lisäystä ja 1435 poistoa
  1. 1 1
      packages/qjkankan-view/.env.testprod
  2. 12 0
      packages/qjkankan-view/public/showviewer/lib/krpano/js/tour-1.20.js
  3. 5 10
      packages/qjkankan-view/public/showviewer/lib/krpano/js/tour.js
  4. 5 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/bingmaps.js
  5. 493 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/combobox.xml
  6. 5 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/googlemaps.js
  7. 5 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/gyro2.js
  8. 19 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/scrollarea.js
  9. 5 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/soundinterface.js
  10. 5 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/videoplayer.js
  11. 5 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/webvr.js
  12. 881 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/webvr.xml
  13. 0 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/webvr_cursor_80x80_17f.png
  14. 5 5
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/bingmaps.js
  15. 516 493
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/combobox.xml
  16. 99 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/contextmenu.xml
  17. 12 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/copy_to_clipboard.xml
  18. 439 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/depthmap_measure3d.xml
  19. 564 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/depthmap_navigation.xml
  20. 48 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/doubleclick_style.xml
  21. 28 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/fps.xml
  22. 5 5
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/googlemaps.js
  23. 5 5
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/gyro2.js
  24. 58 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/ios_iframe_fullscreen.xml
  25. 32 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/iphone_fullscreen_swipe.xml
  26. 94 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/minimap_zoomrect.xml
  27. 5 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/pp_blur.js
  28. 5 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/pp_light.js
  29. 5 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/pp_sharpen.js
  30. 13 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/radar.js
  31. 19 19
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/scrollarea.js
  32. 212 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/showtext.xml
  33. 12 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/snow.js
  34. 5 5
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/soundinterface.js
  35. 5 5
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/videoplayer.js
  36. 5 5
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr.js
  37. 942 881
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr.xml
  38. 89 0
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_autozoom.xml
  39. BIN
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_handcursor.png
  40. BIN
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_laser.png
  41. BIN
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_light.png
  42. BIN
      packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_vrcursor.png
  43. 4 1
      packages/qjkankan-view/src/pages/show.vue
  44. 3 0
      packages/qjkankan-view/src/pages/showMobile.vue

+ 1 - 1
packages/qjkankan-view/.env.testprod

@@ -8,6 +8,6 @@ VUE_APP_URL_FILL=/qjkankan
 # 接口请求地址
 VUE_APP_APIS_URL=https://test.4dkankan.com/
 VUE_APP_DEBBUG_FLAG=0830-01
-VUE_APP_DEBBUG_NOTIFY=0
+VUE_APP_DEBBUG_NOTIFY=1
 VUE_APP_DEBBUG_V4=0
 VUE_APP_DEBBUG_V4_URL="http://192.168.0.186:8081"

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 12 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/js/tour-1.20.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 10
packages/qjkankan-view/public/showviewer/lib/krpano/js/tour.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/bingmaps.js


+ 493 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/combobox.xml

@@ -0,0 +1,493 @@
+<krpano>
+
+	<!--
+		combobox.xml Plugin - krpano 1.19-pr13
+
+		- This plugin converts <combobox> elements in the current xml
+		  into <layer> container, scrollarea and textfield elements.
+		- Additionally it's also possible to add and remove combobox
+		  elements also dynamically.
+		- The full xml implementation allows many ways of customizing
+		  for own needs - custom designs/styles, custom functionality.
+		- The plugin works automatically the same for HTML5 and Flash.
+		- It's possible to use this plugin as replacement for the old
+		  combobox.swf/combobox.js plugins, the action interfaces are
+		  the same.
+
+
+		Syntax for Static XML Code:
+
+			<combobox name="..." design="..." ...any layer settings...>
+				<item name="..." caption="..." onclick="..." />
+				<item name="..." caption="..." onclick="..." />
+			</combobox>
+
+		Syntax for Dynamic XML Code:
+
+		 - Global Actions:
+
+			addComboboxLayer(cbname, design*)
+			removeComboboxLayer(cbname);
+
+		 - Combobox Layer Actions:
+
+			layer[cbname].addItem(caption, onclick)
+			layer[cbname].addNamedItem(name, caption, onclick)
+			layer[cbname].addIdItem(name, caption, onclick);       same as addNamedItem (for combobox.js compatibility)
+			layer[cbname].selectItem(caption)
+			layer[cbname].selectItemByName(name_or_index)
+			layer[cbname].selectIdItem(name_or_index)              same as selectItemByName (for combobox.js compatibility)
+			layer[cbname].removeAll()
+			layer[cbname].openList()
+			layer[cbname].closeList()
+
+		 - Events/Callbacks:
+
+			layer[cbname].onChange
+
+		- Combobox Layer Attributes:
+
+			layer[cbname].item              - krpano Array of the items
+			layer[cbname].selecteditemindex - current selected item index
+	-->
+
+	<!-- path to the scrollarea plugin -->
+	<combobox_scrollareaplugin
+		url.html5="%SWFPATH%/plugins/scrollarea.js"
+		url.flash="%SWFPATH%/plugins/scrollarea.swf"
+		/>
+
+	<!-- core internal layer styles -->
+	<style name="combobox_container_style" type="container" maskchildren="true" bgcapture="true" visible="false" onclick="combobox_onclick_event();" mergedalpha="false" alpha="1.0" />
+	<style name="combobox_marker_style" type="text" align="righttop" edge="center" html="▼" havemarkersize="false" onautosized="set(havemarkersize,true);" mergedalpha="false" alpha="1.0" />
+	<style name="combobox_item_style" type="text" wordwrap="false" vcenter="true" align="lefttop" onover="if(!combbox_item_pressed,onoveritem());asyncloop(hovering,,if(!combbox_item_pressed,onoutitem()));" ondown="onoveritem(); set(combbox_item_pressed,true);" onup="onoutitem(); set(combbox_item_pressed,false);" onoveritem="set(bg,true);" onoutitem="set(bg,false);" mergedalpha="false" alpha="1.0" />
+
+	<!-- several pre-defined designs -->
+	<combobox_design name="default" margin="2" open_close_speed="0.25">
+		<!-- default design - white box with black text and blue selection -->
+		<style name="combobox_container_style" bgalpha="1.0" bgcolor="0xFFFFFF" bgborder="1 0xFFFFFF 0.5" bgroundedge="1" bgshadow="0 1 3 0x000000 1.0" />
+		<style name="combobox_marker_style" css="color:#FFFFFF;" bg="false" txtshadow="0 0 2 0x000000 1" />
+		<style name="combobox_item_style" css="color:#222222;" padding="4 4" bg="false" bgcolor="0xC7E4FC" bgalpha="1.0" bgroundedge="1" txtshadow="0 0 1 0xFFFFFF 1.0" />
+	</combobox_design>
+
+	<combobox_design name="vtour" margin="4" open_close_speed="0.25">
+		<!-- default vtourskin.xml design -->
+		<style name="combobox_container_style" bgalpha="0.8" bgcolor="0x2D3E50" bgborder="0" bgroundedge="1" bgshadow="0 4 10 0x000000 0.3" />
+		<style name="combobox_marker_style" css="color:#FFFFFF;" bg="false" txtshadow="0 0 2 0x000000 1" />
+		<style name="combobox_item_style" css="color:#FFFFFF;" padding="4 4" bg="false" bgcolor="0xFFFFFF" bgalpha="0.5" bgroundedge="0" txtshadow="0 0 2 0x000000 1" />
+	</combobox_design>
+
+
+	<!-- internal events -->
+	<events name="combobox_xml_plugin_events" keep="true"
+	        onxmlcomplete="combobox_parse_xml_elements();"
+	        onresize="combobox_closelist();"
+	        />
+
+
+	<!-- krpano version check -->
+	<action name="combobox_versioncheck" autorun="preinit">
+		if(build LT '2017-09-13',
+			error('combobox.xml - too old krpano version!');
+			set(events[combobox_xml_plugin_events].name, null);
+			set(action[addComboboxLayer].content, '');
+			set(action[removeComboboxLayer].content, '');
+		);
+	</action>
+
+
+	<!-- convert all <combobox> elements to layers -->
+	<action name="combobox_parse_xml_elements" scope="local">
+		if(global.combobox,
+			def(i, integer, 0);
+			def(cnt, integer, get(global.combobox.count));
+			copy(combobox_src, global.combobox);
+			delete(global.combobox);
+			if(cnt GT 0, loop(i LT cnt,
+				copy(cb, combobox_src[get(i)]);
+				if(cb AND cb.name AND cb.parsed != true,
+					set(cb.parsed, true);
+					addComboboxLayer(get(cb.name), get(cb.design));
+					copy(ly, layer[get(cb.name)]);
+					copyattributes(get(ly), get(cb));
+					set(ly.keep, true);
+					def(item_cnt, integer, get(cb.item.count));
+					if(item_cnt GT 0,
+						def(item_i, integer, 0);
+						loop(item_i LT  item_cnt,
+							combobox_additem(get(ly.name), get(cb.item[get(item_i)].name), get(cb.item[get(item_i)].caption), get(cb.item[get(item_i)].onclick));
+							inc(item_i);
+						);
+					);
+				);
+				inc(i);
+			));
+		);
+	</action>
+
+
+	<!-- dynamically add a combobox layer -->
+	<action name="addComboboxLayer" scope="local" args="cbname, design">
+		<!-- create the layer -->
+		addlayer(get(cbname));
+		copy(cb, layer[get(cbname)]);
+		set(cb.keep, true);
+		
+		<!-- copy the design settings (or set defaults) -->
+		if(!combobox_design[get(design)].name, set(design,'default'));
+		copy(cb.cbdesign, combobox_design[get(design)]);
+		calc(cb.margin, cb.cbdesign.margin !== null ? cb.cbdesign.margin : 2);
+		calc(cb.open_close_speed, cb.cbdesign.open_close_speed !== null ? cb.cbdesign.open_close_speed : 0.25);
+		<!-- load the styles and copy the design style settings -->
+		cb.loadstyle(combobox_container_style);
+		copyattributes(get(cb), get(cb.cbdesign.style[combobox_container_style]));
+
+		<!-- add/build/map actions -->
+		calc(cb.addItem,          'combobox_additem(' + cbname + ', null, "%%1", "%%2");');
+		calc(cb.addNamedItem,     'combobox_additem(' + cbname + ', "%%1", "%%2", "%%3");');
+		calc(cb.addIdItem,        'combobox_additem(' + cbname + ', "%%1", "%%2", "%%3");');
+		calc(cb.selectItem,       'combobox_finditem(' + cbname + ', "%%1", __cb_fi); if(__cb_fi GE 0, combobox_selectitem(' + cbname + ', get(__cb_fi))); delete(__cb_fi);');
+		calc(cb.selectItemByName, 'combobox_selectitem(' + cbname + ', "%%1");');
+		calc(cb.selectIdItem,     'combobox_selectitem(' + cbname + ', "%%1");');
+		calc(cb.removeAll,        'combobox_removeitems(' + cbname + ');');
+		calc(cb.openList,         'combobox_openlist(' + cbname + ');');
+		calc(cb.closeList,        'combobox_closelist(' + cbname + ');');
+
+		<!-- create sub-layers -->
+		def(saname, string, 'combobox_%1_scrollarea');
+		addlayer(get(saname));
+		copy(sa, layer[get(saname)]);
+		copy(sa.parent, cbname);
+		copy(sa.url, combobox_scrollareaplugin.url);
+		copy(sa.keep, true);
+		copy(sa.align, lefttop);
+		set(sa.direction, v);
+		set(sa.enabled, false);
+		set(sa.width, 100%);
+		set(sa.height, 100%);
+		copy(cb.scrollarea, sa);
+
+		def(mkname, string, 'combobox_%1_marker');
+		addlayer(get(mkname));
+		copy(mk, layer[get(mkname)]);
+		copy(mk.parent, saname);
+		copy(mk.keep, true);
+		mk.loadstyle(combobox_marker_style);
+		copyattributes(get(mk), get(cb.cbdesign.style[combobox_marker_style]));
+		copy(cb.marker, mk);
+
+		<!-- item data array -->
+		cb.createarray('item');
+
+		<!-- item autosizing information -->
+		set(cb.autosize_i, 0);
+		set(cb.autosize_cnt, 0);
+		set(cb.autosize_max_w, 0);
+		set(cb.autosize_max_h, 0);
+
+		set(cb.lastselecteditemindex, 0);
+		set(cb.selecteditemindex, 0);
+	</action>
+
+
+	<!-- dynamically remove a combobox element -->
+	<action name="removeComboboxLayer" scope="local" args="cbname">
+		if(layer[get(cbname)],
+			copy(cb, layer[get(cbname)]);
+			if(cb === global.openedcombobox, delete(global.openedcombobox));
+			if(cb,
+				removelayer(get(cbname), true);
+			);
+		);
+	</action>
+
+
+	<!-- default onclick event for combobox elements: open the list -->
+	<action name="combobox_onclick_event">
+		combobox_openlist(get(name));
+	</action>
+
+
+	<!-- dynamically add items -->
+	<action name="combobox_additem" scope="local" args="cbname, itemname, itemcaption, itemonclick">
+		copy(cb, layer[get(cbname)]);
+
+		<!-- when no item name is set, generate an automatic one -->
+		if(itemname === null, calc(itemname, 'autoname_' + cb.item.count); );
+
+		<!-- save the item caption and onclick event -->
+		copy(cb.item[get(itemname)].caption, itemcaption);
+		copy(cb.item[get(itemname)].onclick, itemonclick);
+
+		inc(cb.autosize_cnt);
+
+		<!-- create the item layer/textfield -->
+		calc(itemlayername, 'comboboxitem_' + cbname + '_' + itemname);
+		addlayer(get(itemlayername));
+		copy(li, layer[get(itemlayername)]);
+		li.loadstyle(combobox_item_style);
+		copyattributes(get(li), get(cb.cbdesign.style[combobox_item_style]));
+		copy(li.parent, cb.scrollarea.name);
+		copy(li.keep, true);
+		copy(li.cblayername, cb.name);
+		copy(li.itemname, itemname);
+		copy(li.html, itemcaption);
+		set(li.onautosized, delayedcall(0,combobox_item_autosize_update()) );
+		set(li.onclick, combobox_item_onclick() );
+
+		copy(cb.item[get(itemname)].itemlayername, itemlayername);
+	</action>
+
+
+	<!-- onautosized callback from the item textfield -->
+	<action name="combobox_item_autosize_update" scope="local">
+		copy(cb, layer[get(caller.cblayername)]);
+		inc(cb.autosize_i);
+		Math.max(cb.autosize_max_w, caller.width);
+		Math.max(cb.autosize_max_h, caller.height);
+		if(cb.autosize_i == cb.autosize_cnt, combobox_align_items(get(cb.name)); );
+	</action>
+
+
+	<!-- align the image and set the combobox size -->
+	<action name="combobox_align_items" scope="local" args="cbname">
+		copy(cb, layer[get(cbname)]);
+		if(cb.marker.havemarkersize == false OR cb.scrollarea.loaded == false,
+			<!-- wait until everything is ready -->
+			delayedcall(calc(cb.name + '_waitformarkersize'), 0.01, combobox_align_items(get(cbname)) );
+		  ,
+			<!-- set the item positions and the combobox size -->
+			if(global.openedcombobox === cb, combobox_closelist() );
+			copy(sa, cb.scrollarea);
+			calc(itemwidth, cb.margin GT 0 ? -2 * cb.margin : '100%');
+			copy(mk_w, cb.marker.width);
+			copy(item_cnt, cb.autosize_cnt);
+
+			for(def(item_i, integer, 0), item_i LT item_cnt, inc(item_i),
+				copy(li, layer[get(cb.item[get(item_i)].itemlayername)]);
+				set(li.x, get(cb.margin));
+				copy(li.width, itemwidth);
+				copy(li.height, cb.autosize_max_h);
+				calc(li.y, cb.margin + item_i * (cb.autosize_max_h + cb.margin));
+			);
+
+			if(cb.width == null OR cb.width == cb.lastautosizedwidth,
+				<!-- no combobox width (or an autosized width) set - set the largest item width -->
+				calc(cb.width, cb.margin + cb.autosize_max_w + 2 + mk_w + cb.margin);
+				copy(cb.lastautosizedwidth, cb.width);
+			);
+
+			calc(cb.height, 2*cb.margin + cb.autosize_max_h);
+			calc(sa.height, cb.margin + item_cnt*(cb.margin+cb.autosize_max_h));
+			calc(sa.y, -(cb.selecteditemindex * (cb.autosize_max_h + cb.margin)));
+			calc(cb.marker.x, cb.margin + mk_w/2);
+			tween(layer[get(cb.name)].marker.y, calc(cb.margin + cb.selecteditemindex*(cb.autosize_max_h + cb.margin) + cb.autosize_max_h/2), 0.1);
+
+			<!-- when all is done, show the combobox -->
+			delayedcall(0.1, set(layer[get(cb.name)].visible,true); );
+		);
+	</action>
+
+
+	<!-- default onclick event for items: select the current item, close the list and call the item onclick event -->
+	<action name="combobox_item_onclick" scope="local">
+		copy(cb, layer[get(caller.cblayername)]);
+		copy(itemname, caller.itemname);
+		combobox_selectitem(get(cb.name), get(itemname));
+
+		if(global.openedcombobox === cb, combobox_closelist() );
+
+		if(cb.item[get(itemname)].onclick,
+			<!-- call the onclick event after the combobox has closed -->
+			delayedcall(get(cb.open_close_speed),
+				copy(cb.curitem, cb.item[get(itemname)]);
+				callwith(cb,
+					cb.item[get(itemname)].onclick();
+				);
+			);
+		);
+	</action>
+
+
+	<!-- select an item -->
+	<action name="combobox_selectitem" scope="local" args="cbname, itemname">
+		if(global.combbox_item_pressed != true,
+			copy(cb, layer[get(cbname)]);
+			copy(cb.lastselecteditemindex, cb.selecteditemindex);
+			copy(cb.selecteditemindex, cb.item[get(itemname)].index);
+			<!-- call onchange event on selection change -->
+			if(cb.lastselecteditemindex != cb.selecteditemindex AND cb.onchange,
+				callwith(cb, onchange() );
+			);
+			if(global.openedcombobox === cb,
+				<!-- when opened, just close to the selected item -->
+				combobox_closelist();
+			  ,
+				if(layer[get(cbname)].scrollarea.loaded,
+					layer[get(cbname)].scrollarea.stopscrolling();
+					calc(offset, cb.selecteditemindex*(cb.autosize_max_h + cb.margin));
+					tween(layer[get(cbname)].marker.y, calc(cb.margin + offset + cb.autosize_max_h/2), 0);
+					tween(layer[get(cbname)].scrollarea.y, calc(-offset), 0, default, layer[get(cbname)].scrollarea.update(); );
+				);
+			);
+		);
+	</action>
+
+
+	<!-- find an item by its caption, the global variable defined in 'returnvariable' will contain the index  -->
+	<action name="combobox_finditem" scope="local" args="cbname, itemcaption, returnvariable">
+		copy(cb, layer[get(cbname)]);
+		copy(item_cnt, cb.item.count);
+		set(calc('global.' + returnvariable), -1);
+		for(def(item_i, integer, 0), item_i LT  item_cnt, inc(item_i),
+			if(cb.item[get(item_i)].caption == itemcaption,
+				copy(calc('global.' + returnvariable), item_i);
+				copy(item_i, item_cnt);
+			);
+		);
+	</action>
+
+
+	<!-- remove all items (to be able to add new ones) -->
+	<action name="combobox_removeitems" scope="local" args="cbname">
+		copy(cb, layer[get(cbname)]);
+		if(global.openedcombobox === cb, combobox_closelist() );
+
+		<!-- remove all item layers -->
+		calc(item_i, cb.item.count - 1);
+		loop(item_i GE 0,
+			removelayer(get(cb.item[get(item_i)].itemlayername));
+			dec(item_i);
+		);
+
+		<!-- reset the item information -->
+		set(cb.item.count, 0);
+		set(cb.autosize_i,0);
+		set(cb.autosize_cnt, 0);
+		set(cb.autosize_max_w, 0);
+		set(cb.autosize_max_h, 0);
+		set(cb.selecteditemindex, 0);
+		set(cb.lastselecteditemindex, 0);
+		if(cb.width == cb.lastautosizedwidth, set(cb.width, null));
+	</action>
+
+
+	<!-- open the combobox list -->
+	<action name="combobox_openlist" scope="local" args="cbname">
+		<!-- if another combobox is already open, close that one first -->
+		if(global.openedcombobox !== null, combobox_closelist() );
+
+		copy(cb, layer[get(cbname)]);
+		copy(global.openedcombobox, cb);
+
+		<!-- find the available screen space above or below the combobox -->
+		calc(cbheight, 2*cb.margin + cb.autosize_max_h);
+		set(lx1, 0);
+		set(ly1, 0);
+		copy(lx2, cb.pixelwidth);
+		copy(ly2, cbheight);
+		layertoscreen(get(cbname), lx1,ly1, lx1,ly1);
+		layertoscreen(get(cbname), lx2,ly2, lx2,ly2);
+		calc(space_above, ly1 - area.pixely);
+		calc(space_below, area.pixelheight - (ly2 - area.pixely));
+
+		<!-- the required space for full opening: -->
+		calc(openheight, cb.margin + cb.autosize_cnt*(cb.margin+cb.autosize_max_h) );
+
+		<!-- vertical centered alignment? -->
+		calc(cb_edge, cb.edge ? cb.edge : cb.align);
+		calc(iscentered, cb_edge == 'left' OR cb_edge == 'center' OR cb_edge == 'right');
+		if(iscentered,
+			calc(openheight_max, space_above + space_below);
+		  ,
+			Math.max(openheight_max, space_above, space_below);
+		);
+
+		<!-- limit the height to the available space (minus some margin) -->
+		Math.min(openheight, calc(openheight_max + cbheight - 20));
+
+		<!-- need vertical offset? (depending on the available space and the align/edge setting) -->
+		set(yoffset, null);
+		calc(top_overflow, -ly1 + area.pixely + openheight/2);
+		calc(bottom_overflow, ly2 - area.pixely + openheight/2 - area.pixelheight);
+		if(cb.parent,
+			<!-- no vertical offset inside other layers, do only a height clipping -->
+			Math.max(max_overflow, top_overflow, bottom_overflow, 0);
+			sub(openheight, max_overflow);
+		  ,
+			if(iscentered,
+				if(openheight GE (area.pixelheight - 20),
+					set(yoffset,0);
+				  ,
+					if(top_overflow GT 0, calc(yoffset, cb.y + top_overflow); );
+					if(bottom_overflow GT 0, calc(yoffset, cb.y - bottom_overflow); );
+				);
+			,
+				indexoftxt(isbottomalign, get(cb_edge), 'bottom');
+				if(space_above GT space_below,
+					if(isbottomalign LT 0, calc(yoffset, cb.y - openheight + cbheight); );
+				  ,
+					if(isbottomalign GE 0, calc(yoffset, cb.y - openheight + cbheight); );
+				);
+			);
+		);
+		if(yoffset != null,
+			copy(cb.ybackup, cb.y);
+			tween(layer[get(cbname)].y, calc(yoffset), get(cb.open_close_speed));
+		);
+
+		<!-- center the opened list at the selected item -->
+		calc(centeritem_y, -1 * (cb.margin + cb.selecteditemindex*(cb.margin+cb.autosize_max_h) + cb.autosize_max_h/2 - openheight/2));
+		clamp(centeritem_y, calc(openheight - cb.scrollarea.height), 0);
+
+		<!-- apply the changes now -->
+		tween(layer[get(cbname)].height, get(openheight), get(cb.open_close_speed));
+		tween(layer[get(cbname)].scrollarea.y, get(centeritem_y), get(cb.open_close_speed), default, layer[get(cbname)].scrollarea.update(); );
+
+		<!-- special html5/flash case:
+			 rotating textfields (the marker symbol here) are not possible in
+			 flash (a flashplayer limitation), so use a rotated symbol instead.
+		-->
+		if(device.html5,
+			tween(layer[get(cbname)].marker.rotate, 90, get(cb.open_close_speed));
+		  ,
+			set(layer[get(cbname)].marker.html, '◀');
+		);
+
+		<!-- enable the scrollarea to allow the user to drag it -->
+		set(cb.scrollarea.enabled, true);
+
+		<!-- install a global onmousedown event to close the list when clicking at the pano -->
+		set(events[combobox_xml_plugin_events].onmousedown, combobox_closelist() );
+	</action>
+
+
+	<!-- close the current open list -->
+	<action name="combobox_closelist" scope="local">
+		if(global.openedcombobox !== null,
+			copy(cb, global.openedcombobox);
+			delete(global.openedcombobox);
+			
+			<!-- clear the global onmousedown event -->
+			set(events[combobox_xml_plugin_events].onmousedown, null);
+
+			<!-- disable the dragging -->
+			set(cb.scrollarea.enabled, false);
+
+			<!-- closing animations -->
+			calc(offset, cb.selecteditemindex*(cb.autosize_max_h + cb.margin));
+			if(cb.ybackup !== null, tween(cb.y, get(cb.ybackup), get(cb.open_close_speed)));
+			layer[get(cb.name)].scrollarea.stopscrolling();
+			tween(layer[get(cb.name)].height, calc(2*cb.margin + cb.autosize_max_h), get(cb.open_close_speed));
+			tween(layer[get(cb.name)].scrollarea.y, calc(-offset), get(cb.open_close_speed), default, layer[get(cb.name)].scrollarea.update(); );
+			tween(layer[get(cb.name)].marker.y, calc(cb.margin + offset + cb.autosize_max_h/2), get(cb.open_close_speed));
+			<!-- special html5/flash case: rotate marker or change symbol -->
+			if(device.html5,
+				tween(layer[get(cb.name)].marker.rotate, 0, get(cb.open_close_speed));
+			  ,
+				set(layer[get(cb.name)].marker.html, '▼');
+			);
+		);
+	</action>
+
+</krpano>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/googlemaps.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/gyro2.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 19 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/scrollarea.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/soundinterface.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/videoplayer.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/webvr.js


+ 881 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/webvr.xml

@@ -0,0 +1,881 @@
+<krpano>
+
+	<!-- load the WebVR plugin and assign it to a 'webvr' variable for easier usage -->
+	<plugin name="WebVR" devices="html5" keep="true"
+	        url="webvr.js"
+	        onloaded="copy(webvr, plugin[WebVR]);"
+	        mousespeed="0.00125"
+	        multireslock="true"
+	        mobilevr_support="true"
+	        mobilevr_ipd="63.5"
+	        mobilevr_screensize="auto"
+	        mobilevr_lens_overlap="1.0"
+	        mobilevr_lens_fov="96"
+	        mobilevr_lens_dist="0.6"
+	        mobilevr_lens_dist2="1|0|0|0"
+	        mobilevr_lens_ca="0.0"
+	        mobilevr_lens_vign="100"
+	        mobilevr_webvr_dist="false"
+	        mobilevr_wakelock="true"
+	        mobilevr_sensor_mode="3"
+	        mobilevr_autocalibration="false"
+	        mobilevr_touch_support="false"
+	        mobilevr_fake_support="false"
+	        vr_cursor="hotspot[vr_cursor]"
+	        vr_cursor_enabled="true"
+	        vr_cursor_onover="if(handcursor, tween(hotspot[vr_cursor].scale,0.4,0.1); vr_auto_click(get(vr_timeout)); );"
+	        vr_cursor_onout="tween(hotspot[vr_cursor].scale,0.3,0.1);"
+	        onavailable="webvr_onavailable();"
+	        onunavailable=""
+	        onunknowndevice="set(ask_user_for_screensize,true);"
+	        onentervr="webvr_onentervr();"
+	        onexitvr="webvr_onexitvr();"
+	        />
+
+	
+	<!-- a custom xml data structure with the supported VR headsets -->
+	<vrheadsets>
+		<headset name="cb1" caption="Cardboard A"   overlap="1.10" fov="96.0"  dist="1.00" dist2="1|0|0|0" ca="0.000" vig="100" />
+		<headset name="cb2" caption="Cardboard B"   overlap="1.00" fov="96.0"  dist="0.60" dist2="1|0|0|0" ca="0.000" vig="100" />
+		<headset name="gvr" caption="GearVR"        overlap="1.00" fov="112.0" dist="0.95" dist2="1|0|0|0" ca="0.090" vig="100" />
+		<headset name="hom" caption="HOMiDO"        overlap="1.00" fov="101.0" dist="1.10" dist2="1|0|0|0" ca="0.075" vig="100" />
+		<headset name="one" caption="VR ONE"        overlap="1.00" fov="109.9" dist="0.00" dist2="1.139|0.093|0.018|0.207" ca="0.090" vig="35" />
+		<headset name="ccr" caption="ColorCross VR" overlap="1.00" fov="70.0"  dist="0.65" dist2="1|0|0|0" ca="0.000" vig="100" />
+		<headset name="nod" caption="No Distortion" overlap="1.00" fov="96.0"  dist="0.00" dist2="1|0|0|0" ca="0.000" vig="100" />
+	</vrheadsets>
+
+
+	<!-- the VR cursor hotspot -->
+	<hotspot name="vr_cursor" keep="true"
+	         url="webvr_cursor_80x80_17f.png"
+	         visible="false"
+	         enabled="false"
+	         distorted="true"
+	         crop="0|0|80|80"
+	         scale="0.3"
+	         depth="1000"
+	         />
+
+
+	<!-- vr_auto_click() - call this action in the onover event of a
+	     hotspot to trigger automatically a click after some time.  -->
+	<action name="vr_auto_click">
+		if(webvr.isenabled,
+			if(%1 != null, set(vr_aclk_timeout, %1), set(vr_aclk_timeout, 2000));
+			copy(vr_aclk_t1, timertick);
+			set(vr_aclk_waiting, true);
+			set(hotspot[vr_cursor].crop,'0|0|80|80');
+
+			asyncloop(vr_aclk_waiting,
+				sub(dt, timertick,vr_aclk_t1);
+
+				if(!hovering,
+					set(vr_aclk_waiting, false);
+					set(hotspot[vr_cursor].crop,'0|0|80|80');
+				  ,
+					div(f, dt, vr_aclk_timeout);
+					mul(f, 16);
+					roundval(f);
+					Math.min(f, 16);
+					mul(f, 80);
+
+					txtadd(hotspot[vr_cursor].crop,get(f),'|0|80|80');
+
+					<!-- wait another 100ms delay after finishing the animation before doing the click -->
+					sub(dt, 100);
+					if(dt GT vr_aclk_timeout,
+						set(vr_aclk_waiting,false);
+						set(hotspot[vr_cursor].crop,'0|0|80|80');
+						<!-- call onclick -->
+						onclick();
+					  );
+				  );
+				);
+		  );
+	</action>
+
+
+	<!-- by pressing SPACE the Oculus Rift could be re-centered -->
+	<events name="webvr_events" devices="html5" keep="true"
+	        onkeydown="if(keycode==32, webvr.resetSensor(0) );"
+	        onmousedown="if(webvr AND webvr.isenabled, webvr_showbuttons() );"
+	        />
+
+
+	<!-- when WebVR support is available show an EnterVR button -->
+	<action name="webvr_onavailable">
+
+		delayedcall(0.5, tween(layer[webvr_enterbutton].alpha,1.0); );
+	</action>
+
+
+	<action name="webvr_onentervr">
+		trace('vr-in');
+		tween(layer[webvr_enterbutton].alpha,0,0);
+
+		webvr_showbuttons();
+		webvr_hide_all_non_vr_layers();
+
+		<!-- when the screen size is unknown an no custom size is set, open the setup screen on entering the VR mode -->
+		if(webvr.ismobilevr == true AND !webvr.isfake AND ask_user_for_screensize == true AND webvr.mobilevr_screensize == 'auto',
+			set(ask_user_for_screensize, false);
+			<!-- vr_setup(); -->
+		  );
+		if(webvr.isfake,
+			webvr_show_fakemode_info(true);
+		  );
+	</action>
+
+
+	<action name="webvr_onexitvr">
+		trace('vr-out');
+		stopdelayedcall(vr_button_fadeout);
+
+		tween(layer[webvr_enterbutton].alpha,1);
+		tween(layer[webvr_exitbutton].alpha,0);
+		<!-- tween(layer[webvr_setupbutton].alpha,0); -->
+		
+		webvr_show_fakemode_info(false);
+		webvr_restore_layers();
+		js(window.onExitVrStatus);
+	</action>
+
+
+	<action name="webvr_hide_all_non_vr_layers">
+		for(set(i,0), i LT layer.count, inc(i),
+			copy(lr, layer[get(i)]);
+			if(lr.vr !== true,
+				copy(lr.vr_backup_visible, lr.visible);
+				set(lr.visible, false);
+			  );
+		  );
+		for(set(i,0), i LT hotspot.count, inc(i),
+			copy(lh, hotspot[get(i)]);
+			if(lh.vr !== true,
+				copy(lh.vr_backup_visible, lh.visible);
+				set(lh.visible, false);
+			  );
+		  );
+	</action>
+
+	<action name="webvr_restore_layers">
+		for(set(i,0), i LT layer.count, inc(i),
+			copy(lr, layer[get(i)]);
+			if(lr.vr_backup_visible,
+				copy(lr.visible, lr.vr_backup_visible);
+				delete(lr.vr_backup_visible);
+			  );
+		  );
+		for(set(i,0), i LT hotspot.count, inc(i),
+			copy(lh, hotspot[get(i)]);
+			if(lh.vr_backup_visible,
+				copy(lh.visible, lh.vr_backup_visible);
+				delete(lh.vr_backup_visible);
+			  );
+		  );
+	</action>
+	
+	<action name="webvr_show_fakemode_info">
+		if('%1' == 'true',
+			addlayer(webvr_fakemode_info);
+			set(layer[webvr_fakemode_info].url, '%SWFPATH%/plugins/textfield.swf');
+			set(layer[webvr_fakemode_info].keep, true);
+			set(layer[webvr_fakemode_info].align, 'bottom');
+			set(layer[webvr_fakemode_info].y, 80);
+			set(layer[webvr_fakemode_info].background, false);
+			set(layer[webvr_fakemode_info].css, 'color:#FFFFFF;text-align:center;');
+			set(layer[webvr_fakemode_info].html, '');
+		  ,
+			removelayer(webvr_fakemode_info);
+		  );
+	</action>
+	
+	
+	<!-- ensure the same scaling on mobiles (regardless if mobilescale is 0.5 or 1.0) -->
+	<krpano webvr_setup_scale="calc:(1.0 + 1.0*(device.mobile AND stagescale LT 1.0)) / (1.0 + 1.0*device.mobile)"
+	        webvr_button_scale.normal="1.0"
+	        webvr_button_scale.mobile="1.6"
+	        />
+
+	
+	<!-- the EnterVR/ExitVR and SetupVR buttons -->
+	<style name="webvr_button_style"
+	       url="%SWFPATH%/plugins/textfield.swf"
+	       backgroundcolor="0x000000"
+	       backgroundalpha="0.5"
+	       roundedge="calc:9*webvr_setup_scale*webvr_button_scale"
+	       css="calc:'color:#FFFFFF;font-size:' + 20*webvr_setup_scale*webvr_button_scale + 'px;'"
+	       padding="calc:6*webvr_setup_scale*webvr_button_scale + ' ' + 10*webvr_setup_scale*webvr_button_scale"
+	       />
+	
+	<layer name="webvr_enterbutton" keep="true" vr="true"
+	       style="webvr_button_style"
+	       html=""
+	       align="top" y="24"
+	       autoalpha="true" alpha="0.0"
+	       onclick="webvr.enterVR();"
+	       />
+
+	<layer name="webvr_exitbutton" keep="true" vr="true"
+	       style="webvr_button_style"
+	       html="退出VR模式"
+	       align="top" y="24"
+	       autoalpha="true" alpha="0.0"
+	       onclick="webvr.exitVR();"
+	       />
+
+	<layer name="webvr_setupbutton" keep="true" vr="true"
+	       autoalpha="true" alpha="0.0"
+	       />
+
+	<action name="webvr_showbuttons">
+		stopdelayedcall(vr_button_fadeout);
+		if(webvr.ismobilevr,
+			tween(layer[webvr_exitbutton].alpha|layer[webvr_setupbutton].alpha, 1.0|1.0, 0.25);
+			delayedcall(vr_button_fadeout, 0.5, tween(layer[webvr_exitbutton].alpha|layer[webvr_setupbutton].alpha, 0.0|0.0, 1.0); );
+		  ,
+			tween(layer[webvr_exitbutton].alpha, 1.0, 0.25);
+			delayedcall(vr_button_fadeout, 0.5, tween(layer[webvr_exitbutton].alpha, 0.0, 1.0); );
+		  );
+	</action>
+
+
+
+	<!--
+		VR Setup
+	-->
+
+	<action name="vr_setup">
+		<!-- disable cursor -->
+		set(webvr.vr_cursor_enabled, false);
+		
+		<!-- hide VR buttons -->
+		tween(layer[webvr_exitbutton].alpha,0);
+		tween(layer[webvr_setupbutton].alpha,0);
+		
+		<!-- create background layer -->
+		addlayer(vr_setup_bg);
+		set(layer[vr_setup_bg].type, container);
+		set(layer[vr_setup_bg].bgcolor, 0x000000);
+		set(layer[vr_setup_bg].bgalpha, 0.5);
+		set(layer[vr_setup_bg].bgcapture, true);
+		set(layer[vr_setup_bg].handcursor, false);
+		set(layer[vr_setup_bg].align, lefttop);
+		set(layer[vr_setup_bg].width, 100%);
+		set(layer[vr_setup_bg].height, 100%);
+		set(layer[vr_setup_bg].zorder, 99999);
+		
+		<!-- get and prepare device infos and settings -->
+		copy(i_screensize, webvr.mobilevr_screensize);
+		if(i_screensize == 'auto', copy(i_screensize, webvr.devicesize));
+		if(i_screensize LE 0, set(i_screensize, 5.0));
+		roundval(i_screensize, 1);
+		txtadd(i_screensize, ' inch');
+
+		copy(i_ipd, webvr.mobilevr_ipd);
+		roundval(i_ipd, 1);
+		txtadd(i_ipd, ' mm');
+
+		copy(i_fov, webvr.mobilevr_lens_fov);
+		roundval(i_fov, 1);
+
+		copy(i_dist, webvr.mobilevr_lens_dist);
+		roundval(i_dist, 2);
+		
+		copy(i_dist2, webvr.mobilevr_lens_dist2);
+		txtsplit(i_dist2, '|', i_dist2_k1, i_dist2_k2, i_dist2_k3, i_dist2_k4);
+		mul(i_dist2_k1,1);
+		mul(i_dist2_k2,10);
+		mul(i_dist2_k3,10);
+		mul(i_dist2_k4,10);
+		roundval(i_dist2_k1,2);
+		roundval(i_dist2_k2,2);
+		roundval(i_dist2_k3,2);
+		roundval(i_dist2_k4,2);
+
+		copy(i_vig, webvr.mobilevr_lens_vign);
+		roundval(i_vig, 0);
+		
+		copy(i_overlap, webvr.mobilevr_lens_overlap);
+		roundval(i_overlap, 2);
+		
+		copy(i_ca, webvr.mobilevr_lens_ca);
+		roundval(i_ca, 3);
+
+		set(i_headset, 'Custom');
+		for(set(i,0), i LT vrheadsets.headset.count, inc(i),
+			copy(hs, vrheadsets.headset[get(i)]);
+			if(i_overlap == hs.overlap AND i_fov == hs.fov AND i_dist == hs.dist AND i_dist2 == hs.dist2 AND i_ca == hs.ca AND i_vig == hs.vig , copy(i_headset, hs.caption));
+		   );
+
+		<!-- when the screen size is unknown, mark it red -->
+		set(known_size, true);
+		set(sizcol, #FFFFFF);
+		copy(i_devicename, webvr.devicename);
+		if(i_devicename == 'Unknown',
+			if(webvr.mobilevr_screensize == 'auto',
+				set(sizcol, #AA0000);
+				set(known_size, false);
+			  ,
+				set(i_devicename, 'Custom');
+			  );
+		  );
+
+		
+		<!-- create layer for the main menu -->
+		addlayer(vr_setup_m1);
+		set(layer[vr_setup_m1].type, container);
+		set(layer[vr_setup_m1].parent, vr_setup_bg);
+		set(layer[vr_setup_m1].align, lefttop);
+		set(layer[vr_setup_m1].width, 100%);
+		set(layer[vr_setup_m1].height, 100%);
+		
+		<!-- create layer for the headset customization menu -->
+		addlayer(vr_setup_m3);
+		set(layer[vr_setup_m3].type, container);
+		set(layer[vr_setup_m3].parent, vr_setup_bg);
+		set(layer[vr_setup_m3].align, lefttop);
+		set(layer[vr_setup_m3].width, 100%);
+		set(layer[vr_setup_m3].height, 100%);
+		set(layer[vr_setup_m3].visible, false);
+		
+		<!-- create layer for the calibration menu -->
+		addlayer(vr_setup_m2);
+		set(layer[vr_setup_m2].type, container);
+		set(layer[vr_setup_m2].parent, vr_setup_bg);
+		set(layer[vr_setup_m2].align, lefttop);
+		set(layer[vr_setup_m2].width, 100%);
+		set(layer[vr_setup_m2].height, 100%);
+		set(layer[vr_setup_m2].visible, false);
+		
+		<!-- create the text elements -->
+		set(vr_setup_text_parent, 'vr_setup_m1');
+		vr_setup_createtext(vr_setup_title, 'VR设置',       center, center, 0, -225, #FFFFFF,     false);
+
+		vr_setup_createtext(vr_setup_dvn1, '设备:',         center, right,  0, -145, #FFFFFF,     true, vr_setup_select('screen') );
+		vr_setup_createtext(vr_setup_dvn2, get(i_devicename), center, left,   0, -145, get(sizcol), true, vr_setup_select('screen') );
+		vr_setup_createtext(vr_setup_siz1, '屏幕尺寸:',     center, right,  0, -105, #FFFFFF,     true, vr_setup_select('screen') );
+		vr_setup_createtext(vr_setup_siz2, get(i_screensize), center, left,   0, -105, get(sizcol), true, vr_setup_select('screen') );
+
+		vr_setup_createtext(vr_setup_ipd1, '瞳距:',            center, right,  0,  -35, #FFFFFF,     true, vr_setup_select('ipd') );
+		vr_setup_createtext(vr_setup_ipd2, get(i_ipd),        center, left,   0,  -35, #FFFFFF,     true, vr_setup_select('ipd') );
+
+		vr_setup_createtext(vr_setup_hmd1, '设置头显:',     center, right,  0,  +35, #FFFFFF,     true, vr_setup_select('headset') );
+		vr_setup_createtext(vr_setup_hmd2, get(i_headset),    center, left,   0,  +35, #FFFFFF,     true, vr_setup_select('headset') );
+		
+		vr_setup_createtext(vr_setup_hmd3, '调节头显',       center, center, 0,  +75, #FFFFFF,     true, set(background,true), set(background,false), vr_setup_customize_headset() );
+
+		
+
+		if(webvr.iswebvr == false,
+			vr_setup_createtext(vr_setup_cal, '陀螺仪校准',   center, center,    0, +145, #FFFFFF,     true, set(background,true), set(background,false), vr_setup_calibration() );
+		  );
+
+		vr_setup_createtext(vr_setup_sav, '保存',          center, center, -200, +225, #FFFFFF,     true, set(background,true), set(background,false), vr_setup_save() );
+		vr_setup_createtext(vr_setup_rst, '重置',         center, center,    0, +225, #FFFFFF,     true, set(background,true), set(background,false), vr_setup_reset() );
+		vr_setup_createtext(vr_setup_cls, '关闭',         center, center, +200, +225, #FFFFFF,     true, set(background,true), set(background,false), vr_setup_close() );
+		
+		<!-- and the adjusting buttons -->
+		vr_setup_createbutton(vr_setup_btn1, '&#60;', left,  left,  5%, -35, #FFFFFF, true, null);
+		vr_setup_createbutton(vr_setup_btn2, '&#62;', right, right, 5%, -35, #FFFFFF, true, null);
+		
+		
+		<!-- create the customize_headset text elements -->
+		set(vr_setup_text_parent, 'vr_setup_m3');
+		vr_setup_createtext(vr_setup_m31, '头显设置', center, center, 0, -225, #FFFFFF, false);
+		
+		vr_setup_createtext(vr_setup_fov1,  'FOV:',           center, right,  0,  -80,  #FFFFFF,    true, vr_setup_select('fov') );
+		vr_setup_createtext(vr_setup_fov2, get(i_fov),        center, left,   0,  -80,  #FFFFFF,    true, vr_setup_select('fov') );
+		vr_setup_createtext(vr_setup_dst1, 'Distortion:',     center, right,  0,  -32,  #FFFFFF,    true, vr_setup_select('dist') );
+		vr_setup_createtext(vr_setup_dst2, get(i_dist),       center, left,   0,  -32,  #FFFFFF,    true, vr_setup_select('dist') );
+		vr_setup_createtext(vr_setup_d2tx, 'Dist2:',          center, right,  0,  +16,  #FFFFFF,    true, vr_setup_select('dist2k1') );
+		vr_setup_createtext(vr_setup_d2k1, get(i_dist2_k1),   center, left,   0,  +16,  #FFFFFF,    true, vr_setup_select('dist2k1') );
+		vr_setup_createtext(vr_setup_d2k2, get(i_dist2_k2),   center, left, +100, +16,  #FFFFFF,    true, vr_setup_select('dist2k2') );
+		vr_setup_createtext(vr_setup_d2k3, get(i_dist2_k3),   center, left, +200, +16,  #FFFFFF,    true, vr_setup_select('dist2k3') );
+		vr_setup_createtext(vr_setup_d2k4, get(i_dist2_k4),   center, left, +300, +16,  #FFFFFF,    true, vr_setup_select('dist2k4') );
+		
+		
+		vr_setup_createtext(vr_setup_cac1, 'CA Corr:',        center, right,  0,  +64,  #FFFFFF,    true, vr_setup_select('ca') );
+		vr_setup_createtext(vr_setup_cac2, get(i_ca),         center, left,   0,  +64,  #FFFFFF,    true, vr_setup_select('ca') );
+		vr_setup_createtext(vr_setup_vig1, 'Vignette:',       center, right,  0, +112,  #FFFFFF,    true, vr_setup_select('vignette') );
+		vr_setup_createtext(vr_setup_vig2, get(i_vig),        center, left,   0, +112,  #FFFFFF,    true, vr_setup_select('vignette') );
+		vr_setup_createtext(vr_setup_olp1, 'Overlap:',        center, right,  0, +160,  #FFFFFF,    true, vr_setup_select('overlap') );
+		vr_setup_createtext(vr_setup_olp2, get(i_overlap),    center, left,   0, +160,  #FFFFFF,    true, vr_setup_select('overlap') );
+				
+		vr_setup_createtext(vr_setup_m35, '关闭',       center, center, 0, +225, #FFFFFF, true, set(background,true), set(background,false), vr_setup_close_sub_menus() );
+		
+		
+		<!-- create the calibration text elements -->
+		set(vr_setup_text_parent, 'vr_setup_m2');
+		vr_setup_createtext(vr_setup_cb1, '陀螺仪', center, center, 0, -225, #FFFFFF, false);
+		vr_setup_createtext(vr_setup_cb2, '水平放置后校准', center, center, 0, -95, #FFFFFF, false, vr_setup_select('screen') );
+		vr_setup_createtext(vr_setup_cb3, '校准',   center, center, 0,  +55, #FFFFFF, true, set(background,true), set(background,false), vr_setup_do_calibration() );
+		vr_setup_createtext(vr_setup_cb4, '重置',       center, center, 0, +125, #FFFFFF, true, set(background,true), set(background,false), webvr.resetcalibration() );
+		vr_setup_createtext(vr_setup_cb5, '关闭',       center, center, 0, +225, #FFFFFF, true, set(background,true), set(background,false), vr_setup_close_sub_menus() );
+		
+		vr_setup_createtext(vr_setup_cb6, 'Calibrating...',      bottom, center, 0, 40, #FFFFFF, false, null );
+		vr_setup_createtext(vr_setup_cb7, 'Calibration okay.',   bottom, center, 0, 40, #FFFFFF, false, null );
+		vr_setup_createtext(vr_setup_cb8, 'Calibration failed!', bottom, center, 0, 40, #FFFFFF, false, null );
+		set(layer[vr_setup_cb6].autoalpha, true);
+		set(layer[vr_setup_cb7].autoalpha, true);
+		set(layer[vr_setup_cb8].autoalpha, true);
+		set(layer[vr_setup_cb6].alpha, 0.0);
+		set(layer[vr_setup_cb7].alpha, 0.0);
+		set(layer[vr_setup_cb8].alpha, 0.0);
+		
+		
+		<!-- pre-select the screen size for adjusting when it is unknown, otherwise the IPD -->
+		if(known_size == false,
+			vr_setup_select('screen', true);
+		  ,
+			vr_setup_select('ipd', true);
+		  );
+	</action>
+
+
+
+	<action name="vr_setup_createtext">
+		<!--
+			%1 = name
+			%2 = text
+			%3 = align
+			%4 = edge
+			%5 = x
+			%6 = y
+			%7 = color
+			%8 = enabled
+			%9 = ondown
+			%10 = onup
+			%11 = onclick
+		-->
+		addlayer(%1);
+		set(layer[%1].parent, get(vr_setup_text_parent));
+		set(layer[%1].url, '%SWFPATH%/plugins/textfield.swf');
+		set(layer[%1].css, calc('text-align:%3;color:%7;font-size:'+40*webvr_setup_scale+'px;font-weight:bold;'));
+		set(layer[%1].padding, calc(0 + ' ' + 8*webvr_setup_scale));
+		set(layer[%1].roundedge, calc(8*webvr_setup_scale));
+		set(layer[%1].background, false);
+		set(layer[%1].backgroundcolor, 0xFFFFFF);
+		set(layer[%1].backgroundalpha, 0.25);
+		set(layer[%1].align, %3);
+		set(layer[%1].edge, %4);
+		set(layer[%1].x, calc(%5 * webvr_setup_scale));
+		set(layer[%1].y, calc(%6 * webvr_setup_scale));
+		set(layer[%1].html, %2);
+		set(layer[%1].enabled, %8);
+		set(layer[%1].ondown, %9);
+		set(layer[%1].onup, %10);
+		set(layer[%1].onclick, %11);
+	</action>
+
+
+	<action name="vr_setup_createbutton">
+		vr_setup_createtext(%1,%2,%3,%4,%5,%6,%7,%8,%9);
+		set(layer[%1].css, calc('vertical-align:middle;text-align:center;color:%7;font-size:'+60*webvr_setup_scale+'px;font-weight:bold;'));
+		set(layer[%1].background, true);
+		set(layer[%1].padding, 0);
+		set(layer[%1].roundedge, calc(40 * webvr_setup_scale));
+		set(layer[%1].width, calc(70 * webvr_setup_scale));
+		set(layer[%1].height, calc(70 * webvr_setup_scale));
+		set(layer[%1].vcenter, true);
+	</action>
+
+
+	<action name="vr_setup_reset">
+		<!-- reset to the defaults -->
+		set(webvr.mobilevr_screensize, 'auto');
+		copy(i_screensize, webvr.devicesize);
+		if(i_screensize LE 0, set(i_screensize, 5.0));
+		roundval(i_screensize, 1);
+		set(layer[vr_setup_dvn2].html, get(webvr.devicename));
+		txtadd(layer[vr_setup_siz2].html, get(i_screensize), ' inch');
+
+		set(webvr.mobilevr_ipd, 63.5);
+		copy(i_ipd, webvr.mobilevr_ipd);
+		roundval(i_ipd, 1);
+		txtadd(layer[vr_setup_ipd2].html, get(i_ipd), ' mm');
+
+		<!-- set fake custom lens settings and call 'next' headset to switch to the default 'Cardboard' settings -->
+		set(webvr.mobilevr_lens_fov, 100);
+		set(webvr.mobilevr_lens_dist, 0.5);
+		set(webvr.mobilevr_lens_vign, 100);
+		set(webvr.mobilevr_lens_overlap, 1.0);
+		set(webvr.mobilevr_lens_ca, 0.0);
+		vr_setup_change_headset(+1);
+
+		vr_setup_select(get(selected_var));
+	</action>
+
+
+	<action name="vr_setup_close">
+		<!-- 2. parameter == true => remove children elements too -->
+		removelayer(vr_setup_bg, true);
+		
+		<!-- enable cursor -->
+		set(webvr.vr_cursor_enabled, true);
+	</action>
+
+
+	<action name="vr_setup_save">
+		webvr.saveSettings();
+		vr_setup_close();
+	</action>
+	
+	
+	<action name="vr_setup_customize_headset">
+		set(layer[vr_setup_bg].bgalpha, 0.1);
+		
+		set(layer[vr_setup_m1].visible,false);
+		set(layer[vr_setup_m2].visible,false);
+		set(layer[vr_setup_m3].visible,true);
+		
+		set(layer[vr_setup_hmd1].parent, vr_setup_m3);
+		set(layer[vr_setup_hmd2].parent, vr_setup_m3);
+		set(layer[vr_setup_btn1].parent, vr_setup_m3);
+		set(layer[vr_setup_btn2].parent, vr_setup_m3);
+		
+		set(layer[vr_setup_hmd1].y, calc(-145 * webvr_setup_scale));
+		set(layer[vr_setup_hmd2].y, calc(-145 * webvr_setup_scale));
+		
+		copy(old_selection, selected_var);
+		vr_setup_select('headset');
+	</action>
+	
+	
+
+	<action name="vr_setup_calibration">
+		set(layer[vr_setup_m1].visible,false);
+		set(layer[vr_setup_m2].visible,true);
+	</action>
+	
+	<action name="vr_setup_close_sub_menus">
+		set(layer[vr_setup_bg].bgalpha, 0.5);
+		
+		set(layer[vr_setup_m1].visible,true);
+		set(layer[vr_setup_m2].visible,false);
+		set(layer[vr_setup_m3].visible,false);
+		
+		set(layer[vr_setup_hmd1].parent, vr_setup_m1);
+		set(layer[vr_setup_hmd2].parent, vr_setup_m1);
+		set(layer[vr_setup_btn1].parent, vr_setup_m1);
+		set(layer[vr_setup_btn2].parent, vr_setup_m1);
+		
+		set(layer[vr_setup_hmd1].y, calc(+35 * webvr_setup_scale));
+		set(layer[vr_setup_hmd2].y, calc(+35 * webvr_setup_scale));
+		
+		if(old_selection,
+			vr_setup_select(get(old_selection));
+			delete(old_selection);
+		  );
+	</action>
+	
+	<action name="vr_setup_do_calibration">
+		if(!webvr.isfake,
+			tween(layer[vr_setup_cb6].alpha, 1.0, 0.1);
+			tween(layer[vr_setup_cb7].alpha, 0.0, 0.1);
+			tween(layer[vr_setup_cb8].alpha, 0.0, 0.1);
+			webvr.calibrate(
+				tween(layer[vr_setup_cb6].alpha, 0.0, 0.1);
+				tween(layer[vr_setup_cb7].alpha, 1.0, 0.1);
+				delayedcall(2.0, tween(layer[vr_setup_cb7].alpha, 0.0, 0.25) );
+			  ,
+				tween(layer[vr_setup_cb6].alpha, 0.0, 0.1);
+				tween(layer[vr_setup_cb8].alpha, 1.0, 0.1);
+				delayedcall(2.0, tween(layer[vr_setup_cb8].alpha, 0.0, 0.25) );
+			  );
+		  );
+	</action>
+
+	<action name="vr_setup_update_dist2">
+		txtadd(webvr.mobilevr_lens_dist2, get(i_dist2_k1), '|', calc(i_dist2_k2/10.0), '|', calc(i_dist2_k3/10.0), '|', calc(i_dist2_k4/10.0));
+		vr_setup_change_headset(0);
+	</action>
+
+	<action name="vr_setup_select">
+		<!-- select a setting for adjusting -->
+		set(layer[vr_setup_siz2].background, false);
+		set(layer[vr_setup_ipd2].background, false);
+		set(layer[vr_setup_hmd2].background, false);
+		set(layer[vr_setup_fov2].background, false);
+		set(layer[vr_setup_dst2].background, false);
+		set(layer[vr_setup_d2k1].background, false);
+		set(layer[vr_setup_d2k2].background, false);
+		set(layer[vr_setup_d2k3].background, false);
+		set(layer[vr_setup_d2k4].background, false);
+		set(layer[vr_setup_vig2].background, false);
+		set(layer[vr_setup_cac2].background, false);
+		set(layer[vr_setup_olp2].background, false);
+
+		set(selected_setting, null);
+		delete(selected_var_value);
+
+		set(layer[vr_setup_btn1].ondown, vr_setup_change_ondown(-1) );
+		set(layer[vr_setup_btn2].ondown, vr_setup_change_ondown(+1) );
+		set(selected_var_callback, null);
+
+		set(selected_var, %1);
+
+		if(selected_var == 'screen',
+			set(selected_setting,      vr_setup_siz2);
+			set(selected_var_name,     'webvr.mobilevr_screensize');
+			set(selected_var_postfix,  ' inch');
+			copy(selected_var_value,   get(selected_var_name));
+			if(selected_var_value == 'auto', copy(selected_var_value, webvr.devicesize));
+			if(selected_var_value LE 0, set(selected_var_value, 5.0));
+			set(selected_var_step,     0.1);
+			set(selected_var_min,      4);
+			set(selected_var_max,      10);
+			set(selected_var_round,    1);
+			set(selected_var_callback, vr_setup_change_screen() );
+		  );
+
+		if(selected_var == 'ipd',
+			set(selected_setting,      vr_setup_ipd2);
+			set(selected_var_name,     'webvr.mobilevr_ipd');
+			set(selected_var_postfix,  ' mm');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.1);
+			set(selected_var_min,      40);
+			set(selected_var_max,      80);
+			set(selected_var_round,    1);
+		  );
+
+		if(selected_var == 'headset',
+			set(selected_setting,      vr_setup_hmd2);
+			set(layer[vr_setup_btn1].ondown, vr_setup_change_headset(-1) );
+			set(layer[vr_setup_btn2].ondown, vr_setup_change_headset(+1) );
+		  );
+
+		if(selected_var == 'fov',
+			set(selected_setting,      vr_setup_fov2);
+			set(selected_var_name,     'webvr.mobilevr_lens_fov');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.1);
+			set(selected_var_min,      40);
+			set(selected_var_max,      179);
+			set(selected_var_round,    1);
+			set(selected_var_callback, vr_setup_change_headset(0) );
+		  );
+
+		if(selected_var == 'dist',
+			set(selected_setting,      vr_setup_dst2);
+			set(selected_var_name,     'webvr.mobilevr_lens_dist');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      0);
+			set(selected_var_max,      5);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_change_headset(0) );
+		  );
+		
+		if(selected_var == 'dist2k1',
+			set(selected_setting,      vr_setup_d2k1);
+			set(selected_var_name,     'i_dist2_k1');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      -9);
+			set(selected_var_max,      +9);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_update_dist2() );
+		  );
+		
+		if(selected_var == 'dist2k2',
+			set(selected_setting,      vr_setup_d2k2);
+			set(selected_var_name,     'i_dist2_k2');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      -9);
+			set(selected_var_max,      +9);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_update_dist2() );
+		  );
+		
+		if(selected_var == 'dist2k3',
+			set(selected_setting,      vr_setup_d2k3);
+			set(selected_var_name,     'i_dist2_k3');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      -9);
+			set(selected_var_max,      +9);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_update_dist2() );
+		  );
+
+		if(selected_var == 'dist2k4',
+			set(selected_setting,      vr_setup_d2k4);
+			set(selected_var_name,     'i_dist2_k4');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      -9);
+			set(selected_var_max,      +9);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_update_dist2() );
+		  );
+
+		if(selected_var == 'vignette',
+			set(selected_setting,      vr_setup_vig2);
+			set(selected_var_name,     'webvr.mobilevr_lens_vign');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     1);
+			set(selected_var_min,      10);
+			set(selected_var_max,      200);
+			set(selected_var_round,    0);
+			set(selected_var_callback, vr_setup_change_headset(0) );
+		  );
+
+		if(selected_var == 'ca',
+			set(selected_setting,      vr_setup_cac2);
+			set(selected_var_name,     'webvr.mobilevr_lens_ca');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      -1.0);
+			set(selected_var_max,      +1.0);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_change_headset(0) );
+		  );
+		  
+		if(selected_var == 'overlap',
+			set(selected_setting,      vr_setup_olp2);
+			set(selected_var_name,     'webvr.mobilevr_lens_overlap');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      0.5);
+			set(selected_var_max,      2.0);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_change_headset(0) );
+		  );
+
+		if(selected_setting != null,
+			set(layer[get(selected_setting)].background, true);
+			if(%2 == true,
+				set(layer[vr_setup_btn1].y, get(layer[get(selected_setting)].y));
+				set(layer[vr_setup_btn2].y, get(layer[get(selected_setting)].y));
+			  ,
+				tween(layer[vr_setup_btn1].y, get(layer[get(selected_setting)].y));
+				tween(layer[vr_setup_btn2].y, get(layer[get(selected_setting)].y));
+			  );
+		  );
+	</action>
+
+
+	<action name="vr_setup_change_screen">
+		set(layer[vr_setup_dvn2].html, 'Custom');
+		set(layer[vr_setup_dvn2].css, calc('color:#FFFFFF;font-size:'+40*webvr_setup_scale+'px;font-weight:bold;'));
+		set(layer[vr_setup_siz2].css, calc('color:#FFFFFF;font-size:'+40*webvr_setup_scale+'px;font-weight:bold;'));
+	</action>
+
+
+	<action name="vr_setup_change_ondown">
+		copy(t0,timertick);
+		set(t1,0);
+		asyncloop(pressed,
+			copy(t2,timertick);
+			sub(dt,t2,t1);
+			if(dt GT 100,
+				copy(t1,t2);
+				sub(dt,t1,t0);
+				div(dt,1000);
+				Math.max(dt,1);
+				mul(dt,%1);
+				vr_setup_adjust(get(dt));
+			  );
+		  );
+	</action>
+
+
+	<action name="vr_setup_adjust">
+		if(selected_setting != null,
+			mul(change, selected_var_step, %1);
+			add(selected_var_value, change);
+			Math.max(selected_var_value, selected_var_min);
+			Math.min(selected_var_value, selected_var_max);
+			roundval(selected_var_value, get(selected_var_round));
+			tween(get(selected_var_name), get(selected_var_value), 0.1);
+			txtadd(layer[get(selected_setting)].html, get(selected_var_value), get(selected_var_postfix));
+			if(selected_var_callback != null, selected_var_callback());
+		  );
+	</action>
+
+
+	<action name="vr_setup_change_headset">
+		set(i_headset, 'Custom');
+		if(%1 != 0,
+			copy(i_fov, webvr.mobilevr_lens_fov);
+			roundval(i_fov, 1);
+			copy(i_dist, webvr.mobilevr_lens_dist);
+			roundval(i_dist, 2);
+			copy(i_dist2, webvr.mobilevr_lens_dist2);
+			copy(i_vig, webvr.mobilevr_lens_vign);
+			roundval(i_vig, 0);
+			copy(i_ca, webvr.mobilevr_lens_ca);
+			roundval(i_ca, 3);
+			copy(i_overlap, webvr.mobilevr_lens_overlap);
+			roundval(i_overlap, 2);
+			set(i_hsindex, -1);
+			copy(i_hscount, vrheadsets.headset.count);
+			for(set(i,0), i LT i_hscount, inc(i),
+				copy(hs, vrheadsets.headset[get(i)]);
+				if(i_overlap == hs.overlap AND i_fov == hs.fov AND i_dist == hs.dist AND i_dist2 == hs.dist2 AND i_ca == hs.ca AND i_vig == hs.vig , copy(i_hsindex, i); copy(i_headset, hs.caption); );
+			   );
+
+			if(%1 GT 0,
+				<!-- loop right -->
+				add(i_hsindex, 1);
+				if(i_hsindex GE i_hscount, set(i_hsindex,0));
+			  ,
+				<!-- loop left -->
+				sub(i_hsindex, 1);
+				if(i_hsindex LT 0, sub(i_hsindex,i_hscount,1));
+			  );
+
+			copy(hs, vrheadsets.headset[get(i_hsindex)]);
+			copy(i_headset, hs.caption);
+			copy(i_overlap, hs.overlap);
+			copy(i_fov,     hs.fov);
+			copy(i_dist,    hs.dist);
+			copy(i_dist2,   hs.dist2);
+			copy(i_ca,      hs.ca);
+			copy(i_vig,     hs.vig);
+		  );
+
+		copy(layer[vr_setup_hmd2].html, i_headset);
+		if(%1 != 0,
+			copy(webvr.mobilevr_lens_overlap, i_overlap);
+			copy(webvr.mobilevr_lens_fov, i_fov);
+			copy(webvr.mobilevr_lens_dist, i_dist);
+			copy(webvr.mobilevr_lens_dist2, i_dist2);
+			copy(webvr.mobilevr_lens_ca, i_ca);
+			copy(webvr.mobilevr_lens_vign, i_vig);
+			copy(layer[vr_setup_olp2].html, i_overlap);
+			copy(layer[vr_setup_fov2].html, i_fov);
+			copy(layer[vr_setup_dst2].html, i_dist);
+			
+			txtsplit(i_dist2, '|', i_dist2_k1, i_dist2_k2, i_dist2_k3, i_dist2_k4);
+			mul(i_dist2_k1,1);
+			mul(i_dist2_k2,10);
+			mul(i_dist2_k3,10);
+			mul(i_dist2_k4,10);
+			roundval(i_dist2_k1,2);
+			roundval(i_dist2_k2,2);
+			roundval(i_dist2_k3,2);
+			roundval(i_dist2_k4,2);
+			copy(layer[vr_setup_d2k1].html, i_dist2_k1);
+			copy(layer[vr_setup_d2k2].html, i_dist2_k2);
+			copy(layer[vr_setup_d2k3].html, i_dist2_k3);
+			copy(layer[vr_setup_d2k4].html, i_dist2_k4);
+			
+			copy(layer[vr_setup_cac2].html, i_ca);
+			copy(layer[vr_setup_vig2].html, i_vig);
+		  );
+	</action>
+
+</krpano>

packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_cursor_80x80_17f.png → packages/qjkankan-view/public/showviewer/lib/krpano/plugins-1.2.0/webvr_cursor_80x80_17f.png


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 5
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/bingmaps.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 516 - 493
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/combobox.xml


+ 99 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/contextmenu.xml

@@ -0,0 +1,99 @@
+<krpano>
+	
+	<!--
+		contextmenu.xml
+		krpano 1.21
+		
+		A helper script for changing the control-mode and 
+		setting some viewing projections via the context-menu.
+	-->
+	
+	<contextmenu fullscreen="true" versioninfo="true">
+		<item name="kr" caption="KRPANO"     />
+		<item name="fs" caption="FULLSCREEN" />
+		<item name="cc" caption="Change Controlmode" onclick="cm_changecontrolmode();"  separator="above" />
+		<item name="nv" caption="Normal View"        onclick="cm_normal_view();"        showif="view.vlookatrange == 180" separator="above"      />
+		<item name="fv" caption="Fisheye View"       onclick="cm_fisheye_view();"       showif="view.vlookatrange == 180" devices="webgl" />
+		<item name="sv" caption="Stereographic View" onclick="cm_stereographic_view();" showif="view.vlookatrange == 180" devices="webgl" />
+		<item name="av" caption="Architectural View" onclick="cm_architectural_view();" showif="view.vlookatrange == 180"                       />
+		<item name="pv" caption="Pannini View"       onclick="cm_pannini_view();"       showif="view.vlookatrange == 180" devices="webgl" />
+		<item name="lp" caption="Little Planet View" onclick="cm_littleplanet_view();"  showif="view.vlookatrange == 180" devices="webgl" />
+	</contextmenu>
+
+
+	<action name="cm_changecontrolmode">
+		switch(control.mode, moveto, drag, follow);
+		cm_changecontrolmode_updatecaption();
+	</action>
+		
+	<action name="cm_changecontrolmode_updatecaption" autorun="onstart" devices="html5">
+		txtadd(contextmenu.item[cc].caption,
+			"Controlmode: ",
+			"[span style=[sq]", calc(control.mode == 'drag' ? "text-decoration:underline" :""), "[sq]]",
+			"Drag",
+			"[/span]",
+			" | ",
+			"[span style=[sq]", calc(control.mode == 'follow' ? "text-decoration:underline" :""), "[sq]]",
+			"Follow",
+			"[/span]",
+			" | ",
+			"[span style=[sq]", calc(control.mode == 'moveto' ? "text-decoration:underline" :""), "[sq]]",
+			"MoveTo",
+			"[/span]",
+			);
+	</action>
+
+	<action name="cm_look_straight">
+		if(view.vlookat LT -80 OR view.vlookat GT +80,
+			tween(view.vlookat, 0.0, 1.0, easeInOutSine);
+			tween(view.fov,     100, distance(150,0.8));
+		  );
+	</action>
+
+	<action name="cm_normal_view">
+		cm_look_straight();
+		tween(view.architectural, 0.0, distance(1.0,0.5));
+		tween(view.pannini,       0.0, distance(1.0,0.5));
+		tween(view.fisheye,       0.0, distance(1.0,0.5));
+	</action>
+
+	<action name="cm_architectural_view">
+		cm_look_straight();
+		tween(view.architectural, 1.0, distance(1.0,0.5));
+		tween(view.pannini,       0.0, distance(1.0,0.5));
+		tween(view.fisheye,       0.0, distance(1.0,0.5));
+	</action>
+
+	<action name="cm_fisheye_view">
+		cm_look_straight();
+		tween(view.architectural, 0.0,  distance(1.0,0.5));
+		tween(view.pannini,       0.0,  distance(1.0,0.5));
+		tween(view.fisheye,       0.35, distance(1.0,0.5));
+	</action>
+
+	<action name="cm_stereographic_view">
+		cm_look_straight();
+		tween(view.architectural, 0.0, distance(1.0,0.5));
+		tween(view.pannini,       0.0, distance(1.0,0.5));
+		tween(view.fisheye,       1.0, distance(1.0,0.8));
+	</action>
+
+	<action name="cm_pannini_view">
+		cm_look_straight();
+		tween(view.architectural, 0.0, distance(1.0,0.5));
+		tween(view.pannini,       1.0, distance(1.0,0.8));
+		if(view.fisheye LT 0.1,
+			tween(view.fisheye, 1.0, distance(1.0,0.8));
+		  );
+	</action>
+
+	<action name="cm_littleplanet_view">
+		tween(view.architectural, 0.0, distance(1.0,0.5));
+		tween(view.pannini,       0.0, distance(1.0,0.5));
+		tween(view.fisheye,       1.0, distance(1.0,0.8));
+		tween(view.fov,           150, distance(150,0.8));
+		tween(view.vlookat,        90, distance(100,0.8));
+		tween(view.hlookat, calc(view.hlookat + 123.0), distance(100,0.8));
+	</action>
+
+</krpano>

+ 12 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/copy_to_clipboard.xml

@@ -0,0 +1,12 @@
+<krpano>
+	
+	<action name="copy_to_clipboard" type="Javascript"><![CDATA[
+		var textarea = document.createElement('textarea');
+		textarea.value = args[1];
+		krpano.display.viewerlayer.appendChild(textarea);
+		textarea.select();
+		document.execCommand('copy');
+		krpano.display.viewerlayer.removeChild(textarea);
+	]]></action>
+	
+</krpano>

+ 439 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/depthmap_measure3d.xml

@@ -0,0 +1,439 @@
+<krpano>
+
+	<!--
+		depthmap_measure3d.xml
+		krpano 1.21
+
+		https://krpano.com/plugins/xmlextensions/#depthmap_measure3d
+
+		A little helper tool and example for doing measurements in Depthmap-Panos / 3D-Models.
+	-->
+
+	<include url="%VIEWER%/plugins/doubleclick_style.xml" />
+
+
+	<!-- settings -->
+	<depthmap_measure3d
+		ui.bool="true"
+		ui_pos.normal="left,10,0"
+		ui_pos.mobile="lefttop,10,10"
+		ui_dragable.bool="true"
+		gap.number="0.0"
+		showslope.bool="false"
+		unit_format="roundval(v,1) + ' cm'"
+		/>
+
+
+	<!-- css styles for the default user-interface -->
+	<cssstyles>
+		.dm3d_ui { font-size:12px; color:white; background:rgba(0,0,0,0.6); border:1px solid rgba(255,255,255,0.6); border-radius:3px; box-shadow:0 0 3px rgba(0,0,0,0.5); }
+		.dm3d_title { padding-bottom:3px }
+		div.dm3d_button a { color:white; text-decoration:none; }
+		div.dm3d_button a:hover { color:white; text-decoration:underline; }
+	</cssstyles>
+
+
+	<!-- the default user-interface -->
+	<data name="depthmap_measure3d_ui_html"><![CDATA[
+		<div class="dm3d_title">3D Measurements:</div>
+		<div class="dm3d_button">📏 <a href="event:start_measuring_between_points(true)">between two points</a></div>
+		<div class="dm3d_button">📐 <a href="event:start_measuring_between_surfaces(true)">between opposize surfaces</a></div>
+	]]></data>
+
+
+
+	<action autorun="onstart" scope="local" type="Javascript">
+		var depthmap_measure3d = krpano.depthmap_measure3d;
+
+		if(depthmap_measure3d.ui)
+		{
+			var ui = krpano.addlayer("depthmap_measure3d_ui");
+
+			var ui_pos = depthmap_measure3d.ui_pos.split(",");
+
+			ui.setvars({keep:true,
+				type:"text",
+				align:ui_pos[0], x:ui_pos[1], y:ui_pos[2],
+				html:"data:depthmap_measure3d_ui_html",
+				cssclass:"dm3d_ui",
+				cursor:"default",
+				padding:"4 6"
+			});
+
+			// make the layer dragable
+			if (depthmap_measure3d.ui_dragable)
+			{
+			 	ui.cursor = "move";
+				ui.ondown = "changealign(lefttop); asyncloop(pressed, x+=mouse.dx; y+=mouse.dy; clamp(x,0,calc(stagewidth-pixelwidth)); clamp(y,0,calc(stageheight-pixelheight)); );";
+			}
+		}
+	</action>
+
+
+
+	<!-- styles/designs for the measurement elements -->
+
+	<style name="depthmap_measure3d_cursor"
+		type="text"
+		width="9" height="9" scale="0.2"
+		oversampling="3"
+		mipmapping="true"
+		bgcolor="0x000000"
+		bgalpha="0.7"
+		bgroundedge="25"
+		bgborder="20 0xFFFFFF 0.25"
+		bgborderblend="false"
+		bgshadow="0 0 5 0x000000 0.5"
+		distorted="true"
+		depth="0"
+		depthbuffer="true"
+		depthoffset="-100"
+		depthwrite="false"
+		rotationorder="zxy"
+		enabled="false"
+		zorder="0"
+		/>
+
+	
+	<style name="depthmap_measure3d_marker"
+		type="text"
+		enabled="false"
+		width="9"
+		height="9"
+		bgroundedge="12"
+		oversampling="3"
+		mipmapping="true"
+		bgcolor="0x000000"
+		bgalpha="0.8"
+		bgborder="7 0xFFFFFF 0.5"
+		bgborderblend="false"
+		bgshadow="0 0 2 0x000000 0.8"
+		scale="0.25"
+		zoom="true"
+		distorted="true"
+		rotationorder="zxy"
+		twosided="true"
+		depth="0"
+		depthbuffer="true"
+		depthwrite="false"
+		depthoffset="-200"
+		zorder="1"
+		/>
+
+
+	<style name="depthmap_measure3d_line"
+		polyline="true"
+		borderwidth="3"
+		borderwidth3d="true"
+		bordercolor="0x00FF00"
+		bordergradient="0xFF000000|0x00FFFFFF|0xFF000000|4"
+		borderalpha="0.7"
+		depthbuffer="true"
+		depthwrite="false"
+		depthoffset="-200"
+		enabled="false"
+		zorder="1"
+		/>
+		
+
+	<style name="depthmap_measure3d_linetext"
+		type="text"
+		css="font-size:14px;"
+		textalign="center"
+		bgcolor="0xFFFFFF"
+		bgalpha="0.8"
+		bgborder="1 0x0000000 0.7"
+		bgroundedge="7"
+		padding="2 4"
+		depth="0"
+		depthbuffer="false"
+		depthoffset="-200"
+		zorder="2"
+		/>
+
+
+	<!-- API actions for starting/stopping the measurements -->
+
+	<action name="start_measuring_between_points" scope="local" args="showinfo">
+		if(showinfo, depthmap_measure3d_showinfo('double click to start/stop measuring'));
+		depthmap_measure3d_start(1);
+	</action>
+
+	<action name="start_measuring_between_surfaces" scope="local" args="showinfo">
+		if(showinfo, depthmap_measure3d_showinfo('double click to measure'));;
+		depthmap_measure3d_start(2);
+	</action>
+	
+	<action name="stop_measuring" scope="local">
+		global.depthmap_measure3d_loop = false;
+		events.ondoubleclick = null;
+	</action>
+
+
+	<!-- events: stop on ESC key -->
+	<events name="depthmap_measure3d" keep="true"
+		onkeydown="if(keycode == 27, stop_measuring(); );"
+		/>
+
+
+	<action name="depthmap_measure3d_showinfo" scope="local" args="infotext">
+		addlayer('depthmap_measure3d_infotext',l);
+		set(l, type=text, html=get(infotext), css='font-size:20px;font-weight:bold;color:white;text-align:center', bg=false, txtshadow='0 1 4 0x000000 1.0', align=center, enabled=false, alpha=0, width=50%);
+		tween(l.alpha, 1.0);
+		delayedcall(3.0,
+			tween(l.alpha, 0.0, 0.25, default, removelayer(get(l.name)); );
+		);
+	</action>
+
+	
+
+	<action name="depthmap_measure3d_start" type="Javascript"><![CDATA[
+		var depthmap_measure3d = krpano.depthmap_measure3d;
+		var gap = depthmap_measure3d.gap;
+		
+		var mode = 1*args[1];
+
+		var hs = krpano.addhotspot("auto", "webgl");
+		hs.loadstyle("depthmap_measure3d_cursor");
+
+		var line = null;
+		var line_p1 = null;
+		var line_p2 = null;
+		var p1marker = null;
+		var p2marker = null;
+
+		krpano.events.ondoubleclick = function()
+		{
+			var hit = null;
+
+			if (line == null)
+			{
+				line = krpano.addhotspot("auto", "webgl");
+				line.loadstyle("depthmap_measure3d_line");
+
+				line_p1 = line.point.createItem(0);
+				line_p2 = line.point.createItem(1);
+				line_p1.x = line_p2.x = hs.tx;
+				line_p1.y = line_p2.y = hs.ty;
+				line_p1.z = line_p2.z = hs.tz;
+				
+				p1marker = krpano.addhotspot("auto", "webgl");
+				p1marker.loadstyle("depthmap_measure3d_marker");
+				p1marker.tx = line_p1.x;
+				p1marker.ty = line_p1.y;
+				p1marker.tz = line_p1.z;
+				p1marker.rx = hs.rx;
+				p1marker.ry = hs.ry;
+				p1marker.rz = hs.rz;
+
+				if (mode == 2)
+				{
+					hit = krpano.actions.raycastdepth(hs.tx, hs.ty, hs.tz, hs.nx, hs.ny, hs.nz);
+					if (hit)
+					{
+						line_p2.x = hit.x;
+						line_p2.y = hit.y;
+						line_p2.z = hit.z;
+					}
+					else
+					{
+						krpano.call("depthmap_measure3d_showinfo('no hit')");
+						p1marker.remove();
+						line.remove();
+						return;
+					}
+				}
+				else
+				{
+					return;
+				}
+			}
+
+			// finish
+			var dx = line_p2.x - line_p1.x;
+			var dy = line_p2.y - line_p1.y;
+			var dz = line_p2.z - line_p1.z;
+			var length = Math.sqrt(dx*dx + dy*dy + dz*dz);
+
+			var lineinfo = krpano.addhotspot("auto", "webgl");
+			lineinfo.loadstyle("depthmap_measure3d_linetext");
+
+			krpano.v = length;
+			krpano.actions.calc("v_formated", depthmap_measure3d.unit_format);
+			lineinfo.html = krpano.v_formated;
+			
+			if (depthmap_measure3d.showslope)
+			{
+				var y_angle = Math.atan2(-dy, Math.sqrt(dx*dx + dz*dz) ) / Math.PI * 180.0;
+				
+				lineinfo.html += "[br]" + Math.abs(y_angle).toFixed(2) + "°";
+			}
+			
+
+			lineinfo.deletehtml = "[span style='font-size:18px;color:red;vertical-align:middle;']❌[/span] Delete";
+
+			// place between the points
+			lineinfo.tx = 0.5*line_p1.x + 0.5*line_p2.x;
+			lineinfo.ty = 0.5*line_p1.y + 0.5*line_p2.y;
+			lineinfo.tz = 0.5*line_p1.z + 0.5*line_p2.z;
+
+			lineinfo.onclick = function()
+			{
+				if (lineinfo.backuphtml)
+				{
+					lineinfo.hs_line.remove();
+					lineinfo.hs_p1marker.remove();
+					lineinfo.hs_p2marker.remove();
+					lineinfo.remove();
+				}
+				else
+				{
+					lineinfo.backuphtml = lineinfo.html;
+					lineinfo.html = lineinfo.deletehtml;
+
+					krpano.actions.delayedcall(1, function()
+					{
+						if (lineinfo.backuphtml)
+						{
+							lineinfo.html = lineinfo.backuphtml
+							lineinfo.backuphtml = null;
+						}
+					});
+				}
+			}
+
+			if (krpano.device.mouse)
+			{
+				lineinfo.onover = function()
+				{
+					if (!lineinfo.backuphtml)
+					{
+						lineinfo.backuphtml = lineinfo.html;
+						lineinfo.html = lineinfo.deletehtml;
+					}
+				}
+
+				lineinfo.onout = function()
+				{
+					if (lineinfo.backuphtml)
+					{
+						lineinfo.html = lineinfo.backuphtml;
+						lineinfo.backuphtml = null;
+					}
+				}
+			}
+
+			p2marker = krpano.addhotspot("auto", "webgl");
+			p2marker.loadstyle("depthmap_measure3d_marker");
+			p2marker.tx = line_p2.x;
+			p2marker.ty = line_p2.y;
+			p2marker.tz = line_p2.z;
+
+			p2marker.rx = (hit || hs).rx;
+			p2marker.ry = (hit || hs).ry;
+			p2marker.rz = (hit || hs).rz;
+
+			lineinfo.hs_line = line;
+			lineinfo.hs_p1marker = p1marker;
+			lineinfo.hs_p2marker = p2marker;
+
+			line = null;
+			line_p1 = null;
+			line_p2 = null;
+			p1marker = null;
+			p2marker = null;
+			
+			if (krpano.device.touch)
+			{
+				// stop after drawing one line on touch devices
+				krpano.call("stop_measuring();");
+			}
+		}
+
+		krpano.depthmap_measure3d_loop = true;
+
+		krpano.actions.asyncloop("depthmap_measure3d_loop",
+			function()
+			{
+				var hit = null;
+
+				if (krpano.hoveringelement == null || krpano.hoveringelement == hs)
+				{
+					if (krpano.webvr && krpano.webvr.isenabled)
+					{
+						var vrcontrollers = krpano.webvr.vrcontrollers;
+						if (vrcontrollers && vrcontrollers.length > 0)
+						{
+							var vrcontrollers_count = vrcontrollers.length;
+							for (var i=0; i < vrcontrollers_count; i++)
+							{
+								var vrcontroller = vrcontrollers[i];
+								if ( vrcontrollers_count == 1 || (vrcontrollers_count >= 2 && vrcontroller.hand == "right") )
+								{
+									hit = krpano.actions.raycastdepth(vrcontroller.tx, vrcontroller.ty, vrcontroller.tz, vrcontroller.dx, vrcontroller.dy, vrcontroller.dz);
+								}
+							}
+						}
+						else
+						{
+							hit = krpano.actions.raycastdepth(krpano.view.tx, krpano.view.ty, krpano.view.tz, krpano.view.dir.x, krpano.view.dir.y, krpano.view.dir.z);
+						}	
+					}
+					else
+					{
+						hit = krpano.actions.screentodepth(krpano.mouse.x, krpano.mouse.y);
+					}
+				}
+
+				if (hit)
+				{
+					// optionally add a small gap/offset to the hit surface to avoid depthbuffer rendering problems
+					hs.tx = hit.x + hit.nx*gap;
+					hs.ty = hit.y + hit.ny*gap;
+					hs.tz = hit.z + hit.nz*gap;
+
+					// hotspot rotation
+					hs.rx = hit.rx;
+					hs.ry = hit.ry;
+					hs.rz = hit.rz;
+
+					// store also the normal of the hit-surface for later usage
+					hs.nx = hit.nx;
+					hs.ny = hit.ny;
+					hs.nz = hit.nz;
+
+					hs.visible = true;
+
+					if (line)
+					{
+						line.visible = true;
+					}
+
+					if (line_p2)
+					{
+						line_p2.x = hs.tx;
+						line_p2.y = hs.ty;
+						line_p2.z = hs.tz;
+					}
+				}
+				else
+				{
+					if (line)
+					{
+						line.visible = false;
+					}
+
+					hs.visible = false;
+				}
+			},
+			function()
+			{
+				if(line) line.remove();
+				if(p1marker) p1marker.remove();
+				hs.remove();
+			}
+		);
+
+	]]></action>
+
+</krpano>

+ 564 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/depthmap_navigation.xml

@@ -0,0 +1,564 @@
+<krpano>
+	
+	<!--
+		depthmap_navigation.xml
+		krpano 1.21
+		
+		https://krpano.com/plugins/xmlextensions/#depthmap_navigation
+	
+		Depthmap Navigation Controls
+		- Arrow-keys or WASD-keys or Middle/Right-Mousebutton Navigation on Desktop
+		- On-Screen-Touchpad for Mobile Devices
+		- VR-Controller Joystick/Touchpad support for WebVR
+		- Optional Depthmap/3D-Model Hit/Collision-Detection
+		
+		Keyboard Keys:
+		- Arrow/WASD for forward/backward/left/right moving
+		- holding SHIFT for faster movement
+		- Q for moving up
+		- Y or Z for moving down
+		- F for toggling between walking and flying
+		- C for toggling collision / groundcollision on/off
+		
+		Mouse:
+		- Left-Mousebutton: normal looking around / rotating
+		- Left+SHIFT or Middle- and Right-Mousebutton: moving around
+		- Holding the ALT, CTRL or SHIFT-key: moving up and down
+		- In Dollhouse-mode the moving around/up-down controls are swapped
+		
+		Settings:
+		- movemode = "walking" or "flying"
+		- touchmode = "shift" or "move" - the onscreen-touchpad movement mode
+		- speed = movement speed
+		- friction = movement friction
+		- collision = collision-detection / stop on walls
+		- groundcollision = collision-detection with the ground, enables gravity
+		- usevrfloorlevel = use the real physical height in VR
+		- eyelevel - the distance in cm between the ground/floor and the eyes/camera
+		- collisionlevel - the height in cm where the collision checking should be done
+		- smoothlevelchanges - a factor for smoothing level/height changes
+		- stopdistance = keep this distance in cm to walls/surfaces
+		- moveback = when hitting a wall, move back x times
+		- bounceback = when hitting a wall, add a bounce movement
+	-->
+	
+	<depthmap_navigation
+			movemode="walking"
+			touchmode="shift"
+			speed.number="0.5"
+			friction.number="0.9"
+			collision.bool="true"
+			groundcollision.bool="false"
+			usevrfloorlevel.bool="false"
+			eyelevel.number="160.0"
+			collisionlevel.number="100.0"
+			smoothlevelchanges.number="0.15"
+			stopdistance.number="30.0"
+			moveback.number="1.2"
+			bounceback.number="1.6"
+			/>
+
+
+	<!-- remove the default keyboard controls -->
+	<control keycodesleft="" keycodesright="" keycodesup="" keycodesdown="" />
+
+	<!-- keyboard keycodes -->
+	<keyb up="38" down="40" left="37" right="39" w="87" a="65" s="83" d="68" shift="16" ctrl="17" space="32" pageup="33" pagedown="34" />
+	
+	<!-- state variables for walking/flying -->
+	<walkaround forward.int="0" backward.int="0" left.int="0" right.int="0" up.int="0" down.int="0" faster.int="0" jump.int="0" relativespeed.bool="false" />
+	
+	<!-- keyboard event handling -->
+	<events name="depthmap_navigation" keep="true"
+		onkeydown="depthmap_handlekey(1);"
+		onkeyup="depthmap_handlekey(0);"
+		/>
+	
+	<action name="depthmap_handlekey" args="keypressed" scope="local">
+		if( keycode == keyb.up    OR keycode == keyb.w, copy(walkaround.forward,  keypressed);
+		  , keycode == keyb.down  OR keycode == keyb.s, copy(walkaround.backward, keypressed);
+		  , keycode == keyb.left  OR keycode == keyb.a, copy(walkaround.left,     keypressed);
+		  , keycode == keyb.right OR keycode == keyb.d, copy(walkaround.right,    keypressed);
+		  , keycode == keyb.shift,                      copy(walkaround.faster,   keypressed);
+		  , keycode == keyb.space,                      copy(walkaround.jump,     keypressed);
+		  , keycode == charcode('F') AND keypressed == 0,         switch(depthmap_navigation.movemode, 'walking', 'flying'); depthmap_showinfo(('Mode: ' + capitalize(depthmap_navigation.movemode)));
+		  , keycode == charcode('C') AND keypressed == 0,         switch(depthmap_navigation.collision); depthmap_showinfo(('Collision: ' + (depthmap_navigation.collision ? 'On' : 'Off')));
+		  , keycode == charcode('Q'),                             copy(walkaround.up,       keypressed);
+		  , keycode == charcode('Y') OR keycode == charcode('Z'), copy(walkaround.down,     keypressed);
+		);
+	</action>
+	
+	
+	<!-- walking/flying controls -->
+	<action name="depthmap_walkaroundmovement" autorun="onstart" type="Javascript"><![CDATA[
+		
+		function CLAMP(v,vmin,vmax){ return v < vmin ? vmin : v > vmax ? vmax : v; };
+
+		var mouse = krpano.mouse;
+		var view = krpano.view;
+		var dir = view.dir;
+		var settings = krpano.depthmap_navigation
+		var walkaround = krpano.walkaround;
+		
+		var vx=0, vy=0, vz=0;
+		var rx=0;
+		var touchpad_last_axis = [[0,0],[0,0]];
+		var touchpad_move_speed = 5.0;
+		var touchpad_rotate_speed = 1.5;
+		var joystick_move_speed = 1.0;
+		var joystick_rotate_speed = 1.0;
+		var jumping = false;
+		var lasttick = krpano.timertick;
+		
+		
+		krpano.actions.renderloop( function()
+		{
+			var tick = krpano.timertick;
+			var dt = tick - lasttick;
+			lasttick = tick;
+			
+			var webvr = krpano.webvr;
+			var friction = settings.friction;
+			var acceleration = 1.0;
+			var inertia = 1.0;
+			var smoothlevelchanges = settings.smoothlevelchanges;
+			var ty_raycast_offset = 0.0;
+			
+			var do_ground_collision = (settings.collision && settings.groundcollision && settings.movemode == "walking" && view.oz < 200);
+				
+			if (do_ground_collision)
+			{
+				ty_raycast_offset = settings.eyelevel - settings.collisionlevel;
+			}
+			
+			// adjust the friction and acceleration depending on the framerate (an experimental API)
+			if (krpano.display.getAdaptiveFrictions)
+			{
+				var adjustedmovment = krpano.display.getAdaptiveFrictions(friction, acceleration/friction, inertia, "fast");
+				friction = adjustedmovment.friction;
+				acceleration = adjustedmovment.accel * friction;
+				inertia = adjustedmovment.inertia;
+			}
+			
+			vx *= friction;
+			vy *= friction;
+			vz *= friction;
+			rx *= friction;
+			
+			if (vx*vx + vy*vy + vz*vz < 0.001)
+				vx = vy = vz = 0;
+				
+			if (rx*rx < 0.01)
+				rx = 0;
+			
+			var h = view.hlookat * Math.PI / 180.0;
+			var v = view.vlookat * Math.PI / 180.0;
+			
+			// 2D direction vector (walking)
+			var lx2 = Math.sin(h);
+			var lz2 = Math.cos(h);
+			
+			// 3D direction vector (flying)
+			var lx3 = dir.x;
+			var ly3 = dir.y;
+			var lz3 = dir.z;
+			
+			var wx = walkaround.right - walkaround.left;
+			var wz = walkaround.forward - walkaround.backward;
+			var wy = walkaround.up - walkaround.down;
+			
+			// handle the touchpad or joystick input from the vr-controllers
+			var vrcontroller = (webvr && webvr.enabled) ? webvr.vrcontroller : null;
+			if (vrcontroller)
+			{
+				var vrcontroller_count = vrcontroller.length;
+				for (var i=0; i < vrcontroller_count; i++)
+				{
+					var controller = vrcontroller[i];
+					var axes = controller.axes;
+					
+					if (axes)
+					{
+						// when having a depthmap: move around (1), otherwise only rotate the pano (0)
+						var controlmode = (krpano.display.havedepthmap || krpano.display.depthbuffer) ? 1 : 0;
+					
+						// when having two controllers use the touchpad/joystick from the right one only for rotating
+						if (vrcontroller_count == 2 && controller.hand == "right")
+							controlmode = 0;
+						
+						// joystick or touchpad?
+						var y_axis_scale = +1.3;
+						var is_touchpad = false;
+						
+						if (controller.id == "Daydream Controller" || controller.id == "Oculus Go Controller")
+						{
+							is_touchpad = true;
+						}
+						else if(controller.id == "OpenVR Gamepad")	// HTC Vive Controller
+						{
+							is_touchpad = true;
+							y_axis_scale *= -1.0;
+						}
+						
+						if (webvr.iswebxr)
+						{
+							// WebXR: axes[0,1] = touchpad, axes[2,3] = thumbstick
+							if ( axes[0] != 0 || axes[1] != 0 )
+							{
+								is_touchpad = true;
+							}
+							else
+							{
+								// thumbstick - map axes for further processing
+								axes = [axes[2],axes[3]];
+							}
+						}
+						
+						if (do_ground_collision)
+						{
+							var buttons = controller.buttons;
+							
+							// use buttons on the VR controllers for running and jumping
+							if (controller.hand == "left")
+							{
+								walkaround.faster = buttons[0] && buttons[0].pressed ? +1 : 0;
+							}
+							else if (controller.hand == "right")
+							{
+								walkaround.jump = buttons[4] && buttons[4].pressed ? +1 : 0;
+							}
+						}
+						 
+						if (is_touchpad)
+						{
+							//  special touchpad control (swiping like)
+							
+							if (axes[0] != 0 && axes[1] != 0)
+							{
+								var dx = +(axes[0] - touchpad_last_axis[i][0]);
+								var dz = -(axes[1] - touchpad_last_axis[i][1]) * y_axis_scale;
+								touchpad_last_axis[i][0] = axes[0];
+								touchpad_last_axis[i][1] = axes[1];
+								
+								if (Math.abs(dx) > 0.3) dx = 0;		// too fast changes are probably no swipes
+								if (Math.abs(dz) > 0.3) dz = 0;
+								
+								if (controlmode == 0)	// rotate
+								{
+									rx += touchpad_rotate_speed * dx * acceleration;
+								}
+								else	// move
+								{
+									vx += touchpad_move_speed * ( dx*lz2 + dz*lx2) * acceleration;
+									vz += touchpad_move_speed * (-dx*lx2 + dz*lz2) * acceleration;
+								}
+							}
+						}
+						else
+						{
+							// joystick - direct control
+
+							if (controlmode == 0)	// rotate
+							{
+								if (Math.abs(axes[0]) > 0.2)
+								{
+									rx = joystick_rotate_speed * axes[0] * acceleration;
+								}
+							}
+							else	// move
+							{
+							 	// ignore too small values, some vr-controllers, e.g. Windows MR ones, are constantly reporting small wrong values
+								if ( Math.abs(axes[0]) > 0.2 ) wx += joystick_move_speed * axes[0] * acceleration;
+								if ( Math.abs(axes[1]) > 0.2 ) wz -= joystick_move_speed * axes[1] * acceleration;
+							}
+						}
+					}
+				}
+			}
+			
+			var wl = Math.sqrt(wx*wx + wz*wz);
+			if (wl > 0)
+			{
+				if (walkaround.relativespeed)
+				{
+					wl *= acceleration * settings.speed;
+				}
+				else
+				{
+					// normalize the moving speed
+					wl = acceleration * settings.speed / wl;
+				}
+				
+				if (walkaround.faster > 0)
+					wl *= 3.0;
+					
+				wx *= wl;
+				wz *= wl;
+				if (wx)
+				{
+					vx += wx*lz2;
+					vz -= wx*lx2;
+				}
+				if (wz)
+				{ 
+					if (settings.movemode == "flying")
+					{
+						vx += wz*lx3;
+						vz += wz*lz3; 
+						vy += wz*ly3;
+					}
+					else
+					{
+						vx += wz*lx2;  
+						vz += wz*lz2; 
+					}
+				}
+			}
+			
+			if (do_ground_collision == false)
+			{
+				// move up or down
+				vy -= 0.5 * acceleration * settings.speed * wy;
+			}
+			
+			if ((mouse.leftbutton && mouse.shiftkey) || mouse.middlebutton || mouse.rightbutton)
+			{
+				var is_dollhouse_view = (view.oz > 100);
+				var extrakey = mouse.ctrlkey | mouse.altkey;
+				
+				var dragspeed = (is_dollhouse_view ? 0.1 : 0.05) * acceleration;
+				var dx = -dragspeed * mouse.dx;
+				var dy = (extrakey ^ is_dollhouse_view) ? +dragspeed * mouse.dy : 0;
+				var dz = (extrakey ^ is_dollhouse_view) ? 0 : +dragspeed * mouse.dy;
+				
+				vx += dx*dir.rx + dy*dir.ux + dz*dir.x;
+				vy += dx*dir.ry + dy*dir.uy + dz*dir.y * (settings.movemode == "flying");
+				vz += dx*dir.rz + dy*dir.uz + dz*dir.z;
+			}
+			
+			var vspeed = Math.sqrt(vx*vx + vy*vy + vz*vz);
+			
+			if (vspeed > 0)
+			{
+				// simple collision testing
+				if (settings.collision && view.oz < 200)		// do collision testing only in non-dollhouse-view
+				{
+					var hit = krpano.actions.raycastdepth(view.tx, view.ty + ty_raycast_offset, view.tz, vx, vy, vz);
+					if (hit)
+					{
+						if (hit.d > 0 && hit.d < settings.stopdistance)
+						{
+							// slide along walls
+							var vlen = Math.sqrt(vx*vx + vy*vy + vz*vz);
+							if (vlen > 0)
+							{
+								var pushback = -(settings.stopdistance - hit.d) / vlen * settings.moveback;
+								
+								view.tx += pushback * vx;
+								view.ty += pushback * vy;
+								view.tz += pushback * vz;
+								
+								var hitscale = (vx*hit.nx + vy*hit.ny + vz*hit.nz) * settings.bounceback;
+								
+								vx -= hit.nx * hitscale;
+								vy -= hit.ny * hitscale;
+								vz -= hit.nz * hitscale;
+							}
+						}
+					}
+					
+					
+				}
+				
+				view.tx += vx;
+				view.ty += vy;
+				view.tz += vz;
+			}
+			
+			var groundlevel = 0;
+			
+			if (do_ground_collision)
+			{
+				var floorlevel = settings.eyelevel;
+				var jump_pressed = walkaround.jump || (wy > 0);
+				var crouch_pressed = (wy < 0);
+				
+				if (crouch_pressed)
+				{
+					floorlevel *= 0.6;
+				}
+				
+				if (webvr && webvr.enabled && settings.usevrfloorlevel && webvr.floorlevel > 0.0)
+				{
+					// take the real phyiscal floor level
+					floorlevel = settings.eyelevel = webvr.floorlevel;
+				}
+			
+				var floorhit = krpano.actions.raycastdepth(view.tx, view.ty, view.tz, 0, +1.0, 0);
+				
+				if (floorhit && floorhit.d > 0)
+				{
+					groundlevel = floorhit.y;
+					
+					
+				
+					var foot_floor_distance = floorhit.d - floorlevel;
+					
+					if (Math.abs(foot_floor_distance) < 1.0)
+					{
+						// on the floor, even out small differences
+						view.ty += foot_floor_distance;
+						jumping = false;
+						vy = 0;
+					}
+					else if (foot_floor_distance <= 30.0)	// 30.0 = smooth also walking stairs down
+					{
+						if (jumping == false || vy > 0)
+						{
+							// below the floor => push up (but smoothed for nicer stairwalks)
+							view.ty += foot_floor_distance * smoothlevelchanges;
+						}
+						
+						if (foot_floor_distance <= 1.0)
+						{
+							jumping = false;
+							vy = 0;
+						}
+					}
+					else if (foot_floor_distance > 1.0)
+					{
+						var gravity = 4.0;
+						 
+						// in the air => apply gravity
+						if (vy < 0.0 && jump_pressed)
+						{
+							gravity = 1.5;	// use a lower graviy as long as holding the jump key
+							jumping = true;
+						}
+						
+						vy += gravity * acceleration;
+					}
+					
+					if (vy == 0 && jump_pressed)
+					{
+						var jump_inertia = 30.0;
+						
+						vy -= jump_inertia / inertia;
+						
+						jumping = true;
+					}
+				}
+				else
+				{
+					// no floor? maybe below the floor?
+					
+					// trace a ray upward
+					var backup_cull = krpano.image.depthmap.cull;
+					krpano.image.depthmap.cull = "twosided";	// use the front- and back-face for hit-testing in this case
+					floorhit = krpano.actions.raycastdepth(view.tx, view.ty, view.tz, 0, -1.0, 0);
+					krpano.image.depthmap.cull = backup_cull;
+					
+					if (floorhit && floorhit.d > 0)
+					{
+						// shift up
+						view.ty = floorhit.y - floorlevel;
+					}
+				}
+			}
+			
+			if (rx != 0 && webvr)
+			{
+				webvr.hlookatoffset += rx;
+			}
+		});
+	]]></action>
+	
+	
+	
+	<!-- some buttons -->
+	
+	<style name="depthmap_button" type="text" css="text-align:center;" padding="4 8" bgborder="0 0xFFFFFF 1" bgroundedge="1" bgshadow="0 1 4 0x000000 1.0" ondown="set(bgcolor, 0xDDDDDD);" onup="set(bgcolor, 0xFFFFFF);" />
+	<style name="depthmap_info" type="text" css="color:#FFFFFF;text-align:center;" bgalpha="0.0" txtshadow="0 1 4 0x000000 1.0" enabled="false" />
+
+	<layer name="moveup" keep="true" style="depthmap_button" html="▲" align="rightbottom" x="20" y="50" ondown="set(walkaround.up,1);"   onup="set(walkaround.up,0);" />
+	<layer name="movedn" keep="true" style="depthmap_button" html="▼" align="rightbottom" x="20" y="20" ondown="set(walkaround.down,1);" onup="set(walkaround.down,0);" />
+
+	
+
+	<!-- info texts -->
+	<layer name="depthmap_info" keep="true" style="depthmap_info" align="center" y="+25%" html="Walk around using the[br]Keyboard Arrow- or W,A,S,D-keys" 
+		onloaded="delayedcall(depthmap_info, 3.0, tween(layer[depthmap_info].alpha,0.0,0.5); );"
+		devices="desktop" 
+		/>
+	
+	
+	<action name="depthmap_showinfo" scope="local" args="info, time">
+		tween(layer[depthmap_info].alpha,1.0,0.1);
+		layer[depthmap_info].text = info;
+		delayedcall(depthmap_info, 3.0, tween(layer[depthmap_info].alpha,0.0,0.5); );
+	</action>
+	
+
+	<!-- drag area for touch devices -->
+	<layer name="walkinfo_touch" keep="true" type="text" align="bottom"
+		y="85"
+		html="Hold down here[br]and drag around[br]for walking" bgalpha="0.3" devices="handheld"
+		css="color:#FFFFFF;text-align:center;" txtshadow="0 1 4 0x000000 1.0"
+		vcenter="true"
+		width="140" height="140" bgroundedge="180" bgblur="2"
+		ondown="dragcontrol();"
+		/>
+	
+	<events name="walkinfo_touch" keep="true" devices="mobile"
+		onresize="if(stagewidth GT stageheight,
+					set(layer[walkinfo_touch], align=rightbottom, x=80, y=40);
+				  ,
+					set(layer[walkinfo_touch], align=bottom, x=0, y=85);
+				);
+				" 
+		/>
+
+	<action name="dragcontrol" scope="local" type="Javascript"><![CDATA[
+		krpano.actions.tween(caller.path+".alpha",0.0);
+		krpano.actions.asyncloop( function()
+		{	
+			if (caller.pressed)
+			{
+				if(krpano.depthmap_navigation.touchmode == 'move')
+				{
+					krpano.walkaround.relativespeed = true;
+					var dx = (krpano.mouse.x - krpano.mouse.downx);
+					var dy = (krpano.mouse.y - krpano.mouse.downy);
+					var dl = Math.sqrt(dx*dx + dy*dy);
+					if (dl > 0)
+					{
+						dx /= dl;
+						dy /= dl;
+						dl = Math.min(dl,120) / 70;
+						dl = dl < 1.0 ? Math.pow(dl, 0.5) : Math.pow(dl, 1.1);
+					}
+					
+					krpano.walkaround.forward = -dy * dl;
+					krpano.walkaround.left    = -dx * dl;
+				}
+				else 
+				{
+					krpano.walkaround.relativespeed = false;
+					krpano.walkaround.forward = krpano.mouse.dy * -0.25;
+					krpano.walkaround.left    = krpano.mouse.dx * -0.25;
+				}
+				
+				return true;	// keep looping
+			}
+			else
+			{
+				krpano.walkaround.left = 0;
+				krpano.walkaround.forward = 0;
+				krpano.actions.tween(caller.path+".alpha",1);
+				
+				return false;	// stop the loop
+			}
+		});
+	]]></action>
+	
+</krpano>

+ 48 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/doubleclick_style.xml

@@ -0,0 +1,48 @@
+<krpano>
+	
+	<!--
+		doubleclick_style.xml
+		krpano 1.21
+	
+		A helper style for single/double-click detection for layer and hotspot elements.
+		
+		Example:
+		
+		<layer ...
+		       style="doubleclick"
+		       onsingleclick="trace('-single click-');"
+		       ondoubleclick="trace('-double click-');"
+		       />
+	-->
+	
+	<style name="doubleclick"
+	       downx="0"
+	       downy="0"
+	       clicks="0"
+	       onsingleclick=""
+	       ondoubleclick=""
+	       onclick.addevent="doubleclick_style_onclick();"
+	       />
+
+	<action name="doubleclick_style_onclick">
+	    inc(clicks);
+	    if(clicks == 2,
+	        set(clicks,0); 
+	        stopdelayedcall(doubleclickdetector);
+	        if((((mouse.x-downx)^2 + (mouse.y-downy)^2)^0.5) LT (device.touch ? 10 : 2),
+	            ondoubleclick();
+	          ,
+	            onsingleclick();
+	            onsingleclick();
+	        );
+	      ,
+	        copy(downx, mouse.x); 
+	        copy(downy, mouse.y);
+	        delayedcall(doubleclickdetector, 0.3, 
+	            set(clicks,0); 
+	            onsingleclick();
+	        );
+	    );
+	</action>
+	
+</krpano>

+ 28 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/fps.xml

@@ -0,0 +1,28 @@
+<krpano>
+
+	<!--
+		FPS (frames per second) performance measuring tool.
+		This tools shows the current average rendering frame-rate in the left-top corner.
+	-->
+
+	<action name="fps_install" autorun="preinit" scope="local">
+		delayedcall(0.5,
+			addlayer(fps_display);
+			set(layer[fps_display],
+				type=text,
+				keep=true,
+				align='lefttop',
+				css=calc('font-size:'+(device.mobile AND stagescale LT 1.0 ? 24 : 12)+'px; color:#FFFFFF;'),
+				txtshadow='0 0 1 0x000000 1.0',
+				bg=false,
+				parent=STAGE,
+				vr=true,
+				enabled=false
+			);
+			setinterval(fps_plugin, 0.5,
+				calc(layer[fps_display].html, 'FPS: ' + ((display.currentfps+0.5) BOR 0));
+			);
+		);
+	</action>
+
+</krpano>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 5
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/googlemaps.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 5
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/gyro2.js


+ 58 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/ios_iframe_fullscreen.xml

@@ -0,0 +1,58 @@
+<krpano>
+	
+	<!--
+		ios_iframe_fullscreen.xml
+		krpano 1.21
+		
+		https://krpano.com/plugins/xmlextensions/#ios_iframe_fullscreen
+		
+		A helper script for getting into a kind of 'fullscreen mode' on iOS 
+		from inside an iframe.
+		
+		iOS itself doesn't support the HTML5 Fullscreen API and so there is no
+		way to make the pano window larger than the iframe area itself.
+		This script therefore adds a fake-fullscreen-mode support and redirects
+		the browser window directly to the inner iframe page to make the iframe
+		itself beeing the full browser page.
+		
+		Note: this scripts only enables the fullscreen contextmenu item, 
+		custom xml elements that are depending on the 'device.fullscreensupport'
+		state would need to get enabled manually. That's because the xml parsing
+		and the xml element 'devices filtering' is happening before this script is
+		running. For 'manual enabling' e.g. remove the 'fullscreensupport' 
+		devices check from the related elements in the xml files.
+	-->
+	
+	<action name="ios_iframe_fullscreen_redirect" type="Javascript" autorun="preinit" if="device.ios AND device.iframe AND !device.fullscreensupport"><![CDATA[
+			
+		// fake the fullscreen support information
+		krpano.device.fullscreensupport = true;
+				
+		// enable the contextmenu fullscreen item
+		krpano.contextmenu.fullscreen = true;
+				
+		// define a custom 'fullscreen' attribute
+		delete krpano.fullscreen;
+		krpano.registerattribute("fullscreen", false, 
+			function(newstate)
+			{
+				if(newstate)
+				{
+					// when setting fullscreen to true, redirect the top frame to the iframe url
+					try
+					{
+						top.location = window.location;
+					}
+					catch(err)
+					{}
+				}
+			}
+			,
+			function()
+			{
+				return false;
+			});
+			
+	]]></action>
+
+</krpano>

+ 32 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/iphone_fullscreen_swipe.xml

@@ -0,0 +1,32 @@
+<krpano>
+	
+	<!--
+		iphone_fullscreen_swipe.xml
+		krpano 1.21
+		
+		https://krpano.com/plugins/xmlextensions/#iphone_fullscreen_swipe
+		
+		A helper script for getting into fullscreen mode on the iPhone.
+	-->
+	
+	<events name="iphone_fullscreen_swipe" keep="true" devices="iphone"
+			oniphonefullscreen="iphone_fullscreen_swipe();"
+			/>
+		
+	<action name="iphone_fullscreen_swipe" scope="localonly">
+		if(global.display.iphonefullscreen GT 0,
+			if(!global.layer[iphone_fullscreen_info],
+				addlayer('iphone_fullscreen_info', infolayer);
+				set(infolayer, type=text, css='color:#FFFFFF; font-size:26px; font-weight:bold; text-align:center;', txtshadow='0 0 8 0x000000 1', bgcolor=0x000000, bgalpha=0.7, bgcapture=true, align=lefttop, x=0, y=0, width=100%, height=100%, vcenter=true, keep=true, zorder=9999, safearea=false, parent=OVERLAY);
+				if(global.display.iphonefullscreen == 1,
+					set(infolayer.html, '[span style="font-size:60px;"]⇡[/span][br]Swipe Up');
+				  ,
+					set(infolayer.html, '[span style="font-size:60px;"]⇣ ⇡[/span][br]Swipe Down and Up');
+				);
+			);
+		  ,
+			removelayer('iphone_fullscreen_info');
+		);
+	</action>
+	
+</krpano>

+ 94 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/minimap_zoomrect.xml

@@ -0,0 +1,94 @@
+<krpano>
+	
+	<!--
+		minimap_zoomrect.xml
+		krpano 1.21
+		
+		https://krpano.com/plugins/xmlextensions/#minimap_zoomrect
+	
+		A helper script for adding a zooming-indicator for a mini-overview-map.
+		
+		A rectangle will be added within the image layer and the size and position
+		will automatically be updated depending on the zooming and panning.
+		Additionally the rectangle will be dragable to pan around and the map-image
+		will be clickable to pan to a certain position.
+		
+		Example:
+		
+		<layer name="minimap"
+		       url="map.jpg"
+		       bgborder="1 0xFFFFFF"
+		       align="lefttop" x="10" y="10"
+		       ...
+		       style="minimap_zoomrect"
+		       zoomrect_border="1 0x0000FF"
+		       zoomrect_dragable="true"
+		       zoomrect_movetoclick="true"
+		       />
+	-->
+
+	<style name="minimap_zoomrect"
+		maskchildren="true"
+		handcursor="false"
+		onloaded.addevent="minimap_zoomrect_init();"
+		onclick.addevent="minimap_zoomrect_onclick_moveto();"
+		/>
+	
+	<action name="minimap_zoomrect_init" scope="local">
+		addlayer(auto, zoomrect);
+		
+		if(!isvalue(caller.zoomrect_dragable),    def(caller.zoomrect_dragable,    boolean, true));
+		if(!isvalue(caller.zoomrect_movetoclick), def(caller.zoomrect_movetoclick, boolean, true));
+		
+		set(caller.scalechildren,false);
+		
+		set(zoomrect,
+			parent=get(caller.name),
+			type='container',
+			bgborder=calc(caller.zoomrect_border ? caller.zoomrect_border : '1 0x0000FF 1.0'),
+			bgcapture=true,
+			ondown='minimap_zoomrect_dragging();'
+		);
+		
+		calc(events[calc(caller.name+'_zoomrect')].onviewchanged, 'minimap_zoomrect_onviewchanged(' + zoomrect.name + ')');
+		copy(events[calc(caller.name+'_zoomrect')].keep, caller.keep);
+	</action>
+	
+	<action name="minimap_zoomrect_onclick_moveto" scope="local">
+		if(caller.zoomrect_movetoclick,
+			tween(view.hlookat, calc((caller.hitx-0.5) * image.hfov));
+			tween(view.vlookat, calc((caller.hity-0.5) * image.vfov));
+		);
+	</action>
+	
+	<action name="minimap_zoomrect_onviewchanged" scope="local" args="zoomrect_name">
+		copy(zoomrect, layer[get(zoomrect_name)]);
+		set(zoomrect.align, 'center');
+		calc(zoomrect.width, ((view.hfov / image.hfov) * 100) + '%');
+		calc(zoomrect.height, ((view.vfov / image.vfov) * 100) + '%');
+		calc(zoomrect.x, ((view.hlookat / image.hfov) * 100) + '%');
+		calc(zoomrect.y, ((view.vlookat / image.vfov) * 100) + '%');
+	</action>
+		
+	<action name="minimap_zoomrect_dragging" scope="local">
+		copy(parentlayer, layer[get(caller.parent)]);
+		if(parentlayer.zoomrect_dragable,
+			copy(sx, mouse.x);
+			copy(sy, mouse.y);
+			asyncloop(caller.pressed,
+				calc(dx, (mouse.x - sx));
+				calc(dy, (mouse.y - sy));
+				copy(sx, mouse.x);
+				copy(sy, mouse.y);
+				set(caller.align, 'lefttop');
+				calc(caller.x, caller.pixelx + dx);
+				calc(caller.y, caller.pixely + dy);
+				calc(h, (caller.x + caller.pixelwidth/2) / parentlayer.pixelwidth - 0.5);
+				calc(v, (caller.y + caller.pixelheight/2) / parentlayer.pixelheight - 0.5);
+				calc(view.hlookat, h * image.hfov);
+				calc(view.vlookat, v * image.vfov);
+			);
+		);
+	</action>
+
+</krpano>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/pp_blur.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/pp_light.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/pp_sharpen.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 13 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/radar.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 19 - 19
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/scrollarea.js


+ 212 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/showtext.xml

@@ -0,0 +1,212 @@
+<krpano>
+	<!--
+		showtext() xml plugin
+		- showtext() and <textstyle> support for HTML5
+		- docu: https://krpano.com/plugins/showtext/
+		- krpano 1.21
+	-->
+
+
+	<!-- predefine a DEFAULT textstyle element -->
+	<textstyle name="DEFAULT" />
+	
+	
+
+
+	<!-- the automatic running (autorun=preinit) install action -->
+	<action name="showtext_install" autorun="preinit" scope="private:showtext">
+		<!-- remove the built-in 'showtext' function to use the 'showtext' <action> instead: -->
+		delete(global.showtext);
+
+		<!-- initialize internal variables -->
+		set(showtext_style, DEFAULT);
+		set(showtext_prevstyle, null);
+		set(showtext_text, '');
+		set(showtext_prevtext, '');
+		set(showtext_timeout, 0.1);
+		set(showtext_fadeout, 0.0);
+		set(showtext_clipping, false);
+	</action>
+	
+
+	<action name="showtext" scope="private:showtext" args="text, style">
+		if(!style, set(style, DEFAULT));
+		
+		if(global.textstyle[get(style)], 
+			copy(showtext_style, style);
+		  ,
+			warning("showtext() - there is no textstyle '", style, "' defined!");
+			global.textstyle.createarrayitem(get(style));
+		);
+
+		copy(showtext_text, text);
+		
+		if(showtext_text != showtext_prevtext,
+			copy(showtext_prevtext, showtext_text);
+			showtext_createnewtext();
+		  ,
+			delayedcall(showtext_timer, get(showtext_timeout), showtext_hide() );
+		  );
+	</action>
+	
+
+	<action name="showtext_createnewtext" scope="private:showtext">
+		<!-- stop running mouse and alpha update calls -->
+		stopdelayedcall(showtext_mouseupdates);
+		stoptween(global.layer[showtext_tf].alpha);
+
+		<!-- remove the old textfield when the style has changed -->
+		if(showtext_style != showtext_prevstyle,
+			copy(showtext_prevstyle, showtext_style);
+			removelayer(showtext_tf);
+		  );
+		  
+		<!-- create a new textfield plugin layer -->
+		addlayer(showtext_tf);
+
+		<!-- create 'shortcut' variables (tf,ts) for faster access -->
+		copy(tf, global.layer[showtext_tf]);
+		copy(ts, global.textstyle[get(showtext_style)]);
+
+		<!-- get the position settings -->
+		if(ts.origin  !== null, copy(ts_origin,  ts.origin),  set(ts_origin, 'cursor'));
+		if(ts.edge    !== null, copy(ts_edge,    ts.edge),    set(ts_edge, 'bottom'));
+		if(ts.xoffset !== null, copy(ts_xoffset, ts.xoffset), set(ts_xoffset, 0));
+		if(ts.yoffset !== null, copy(ts_yoffset, ts.yoffset), set(ts_yoffset, -3));
+
+		<!-- set the position settings -->
+		if(ts_origin == 'cursor',
+			set(tf.align, 'lefttop');
+			showtext_movetomouse();
+		  ,
+			copy(tf.align, ts_origin);
+		  );
+		copy(tf.edge, ts_edge);
+		copy(tf.ox, ts_xoffset);
+		copy(tf.oy, ts_yoffset);
+
+		<!-- get the font settings -->
+		if(ts.font      !== null, copy(ts_font,      ts.font),      set(ts_font, 'Times'));
+		if(ts.fontsize  !== null, copy(ts_fontsize,  ts.fontsize),  set(ts_fontsize, 12.0));
+		if(ts.bold      !== null, copy(ts_bold,      ts.bold),      set(ts_bold, true));
+		if(ts.italic    !== null, copy(ts_italic,    ts.italic),    set(ts_italic, false));
+		if(ts.textcolor !== null, copy(ts_textcolor, ts.textcolor), set(ts_textcolor, 0x000000));
+		if(ts.textalign !== null, copy(ts_textalign, ts.textalign), set(ts_textalign, 'left'));
+
+		<!-- use the font settings to build the CSS style -->
+		set(tf_css, '');
+		tohex(ts_textcolor, '#', 6);
+		txtadd(tf_css, 'font-family:',get(ts_font),'; font-size:',get(ts_fontsize),'px; color:',get(ts_textcolor),'; ');
+		if(ts_textalign != 'none', txtadd(tf_css, get(tf_css), 'text-align:',get(ts_textalign),'; '));
+		if(ts_bold,   txtadd(tf_css, 'font-weight:bold; '));
+		if(ts_italic, txtadd(tf_css, 'font-style:italic; '));
+		if(ts.css !== null, txtadd(tf_css, get(ts.css)));
+		copy(tf.css, tf_css);
+
+		<!-- size settings -->
+		if(ts.width   !== null AND ts.width   !== '', copy(tf.width,   ts.width));
+		if(ts.height  !== null AND ts.height  !== '', copy(tf.height,  ts.height));
+		if(ts.vcenter !== null AND ts.vcenter !== '', copy(tf.vcenter, ts.vcenter));
+		if(ts.padding !== null AND ts.padding !== '', copy(tf.padding, ts.padding), set(tf.padding,1));
+
+		<!-- background, border, shadow settings -->
+		if(ts.background      !== null, copy(tf.background,      ts.background));
+		if(ts.backgroundcolor !== null, copy(tf.backgroundcolor, ts.backgroundcolor));
+		if(ts.backgroundalpha !== null, copy(tf.backgroundalpha, ts.backgroundalpha));
+		if(ts.border          !== null, copy(tf.border,          ts.border), set(tf.border,true));
+		if(ts.bordercolor     !== null, copy(tf.bordercolor,     ts.bordercolor));
+		if(ts.borderalpha     !== null, copy(tf.borderalpha,     ts.borderalpha));
+		if(ts.borderwidth     !== null, copy(tf.borderwidth,     ts.borderwidth));
+		if(ts.roundedge       !== null, copy(tf.roundedge,       ts.roundedge));
+		if(ts.shadow          !== null, copy(tf.shadow,          ts.shadow));
+		if(ts.shadowrange     !== null, copy(tf.shadowrange,     ts.shadowrange));
+		if(ts.shadowangle     !== null, copy(tf.shadowangle,     ts.shadowangle));
+		if(ts.shadowcolor     !== null, copy(tf.shadowcolor,     ts.shadowcolor));
+		if(ts.shadowalpha     !== null, copy(tf.shadowalpha,     ts.shadowalpha));
+		if(ts.textshadow      !== null, copy(tf.textshadow,      ts.textshadow));
+		if(ts.textshadowrange !== null, copy(tf.textshadowrange, ts.textshadowrange));
+		if(ts.textshadowangle !== null, copy(tf.textshadowangle, ts.textshadowangle));
+		if(ts.textshadowcolor !== null, copy(tf.textshadowcolor, ts.textshadowcolor));
+		if(ts.textshadowalpha !== null, copy(tf.textshadowalpha, ts.textshadowalpha));
+
+		<!-- showing settings -->
+		if(ts.alpha      !== null, copy(ts_alpha,      ts.alpha),      set(ts_alpha, 1.0));
+		if(ts.showtime   !== null, copy(ts_showtime,   ts.showtime),   set(ts_showtime, 0.1));
+		if(ts.fadetime   !== null, copy(ts_fadetime,   ts.fadetime),   set(ts_fadetime, 0.0));
+		if(ts.fadeintime !== null, copy(ts_fadeintime, ts.fadeintime), set(ts_fadeintime, 0.0));
+		copy(showtext_timeout, ts_showtime);
+		copy(showtext_fadeout, ts_fadetime);
+		if(ts_fadeintime GT 0,
+			set(tf.alpha, 0.0);
+			tween(global.layer[showtext_tf].alpha, get(ts_alpha), get(ts_fadeintime), linear);
+		  ,
+			copy(tf.alpha, ts_alpha);
+		  );
+
+		if(ts.noclip !== null, copy(showtext_clipping,ts.noclip), set(showtext_clipping, true));
+		
+		if(showtext_clipping,
+			set(tf.onloaded,    showtext_do_clipping() );
+			set(tf.onautosized, showtext_do_clipping() );
+		  );
+
+		<!-- special flash-only settings -->
+		if(ts.embeddedfonts !== null, copy(tf.embeddedfonts, ts.embeddedfonts));
+		if(ts.effect        !== null, copy(tf.effect,        ts.effect));
+		if(ts.blendmode     !== null, copy(tf.blendmode,     ts.blendmode));
+
+		<!-- set the text and the basic settings to start showing the textfield -->
+		copy(tf.html, showtext_text);
+		set(tf.enabled, false);
+		set(tf.zorder, 999999);
+		if(ts.parent, copy(tf.parent, ts.parent) );
+		set(tf.type, 'text');
+
+		<!-- start the text-hiding timer -->
+		delayedcall(showtext_timer, get(showtext_timeout), showtext_hide() );
+	</action>
+
+
+	<action name="showtext_do_clipping" scope="private:showtext">
+		if(showtext_clipping,
+			global.layer[showtext_tf].updatepos();
+			copy(tf_px, global.layer[showtext_tf].pixelx);
+			copy(tf_py, global.layer[showtext_tf].pixely);
+			if(tf_px LT 0,
+				sub(global.layer[showtext_tf].x, tf_px);
+			  ,
+				add(tf_rightedge, tf_px, global.layer[showtext_tf].pixelwidth);
+				if(tf_rightedge GE global.stagewidth, sub(tf_rightedge,global.stagewidth); sub(global.layer[showtext_tf].x,tf_rightedge); );
+			  );
+			if(tf_py LT 0,
+				sub(global.layer[showtext_tf].y,  tf_py);
+			  ,
+				add(tf_bottomedge, tf_py, global.layer[showtext_tf].pixelheight);
+				if(tf_bottomedge GE global.stageheight, sub(tf_bottomedge,global.stageheight); sub(global.layer[showtext_tf].y,tf_bottomedge); );
+			  );
+		  );
+	</action>
+
+
+	<action name="showtext_movetomouse" scope="private:showtext">
+		copy(global.layer[showtext_tf].x, global.mouse.stagex);
+		copy(global.layer[showtext_tf].y, global.mouse.stagey);
+
+		showtext_do_clipping();
+
+		delayedcall(showtext_mouseupdates, 0, showtext_movetomouse() );
+	</action>
+
+
+	<action name="showtext_hide" scope="private:showtext">
+		if(global.layer[showtext_tf],
+			tween(global.layer[showtext_tf].alpha, 0.0, get(showtext_fadeout), linear,
+					stopdelayedcall(showtext_mouseupdates);
+					removelayer(showtext_tf);
+					set(showtext_text, '');
+					set(showtext_prevtext, '');
+				);
+		  );
+	</action>
+
+</krpano>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 12 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/snow.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 5
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/soundinterface.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 5
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/videoplayer.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5 - 5
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 942 - 881
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr.xml


+ 89 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_autozoom.xml

@@ -0,0 +1,89 @@
+<krpano>
+
+	<!--
+		webvr_autozoom.xml
+		krpano 1.21
+		
+		https://krpano.com/plugins/xmlextensions/#webvr_autozoom
+
+		A helper script for zooming in VR.
+		
+		After ~2 seconds staring at one point, the view slowly starts zooming-in.
+		When looking around, the zooming-in stops and the view starts slowly zooming-out
+		back to the normal view (the faster the looking-around the faster the zooming-out). 
+	-->
+
+	<events name="webvr_autozoom" keep="true"
+	        onnewpano="webvr_autozoom_calc_maxzoom();"
+	        webvr_onentervr="webvr_autozoom_start();"
+	        webvr_onexitvr="webvr_autozoom_stop();"
+	        />
+
+
+	<!-- some settings -->
+	<action name="webvr_autozoom_init" scope="private:webvr_autozoom" autorun="onstart">
+		set(zoom_delay, 2.0);
+		set(movement_tolerance, 0.01);
+		set(zoom_speed, 1.0);
+		set(max_zoom, 10);
+	</action>
+
+
+	<!-- calc maxzoom depending onthe current pano image -->
+	<action name="webvr_autozoom_calc_maxzoom" scope="private:webvr_autozoom">
+		set(maxwidth, get(global.image.hres));
+		if(tolower(global.image.type) == 'cube',
+			calc(maxwidth, maxwidth * Math.PI);
+		  ,tolower(global.image.type) == 'flat',
+			calc(maxwidth, maxwidth * 360 / 90);
+		  ,
+			calc(maxwidth, maxwidth * 360 / global.image.hfov);
+		);
+		calc(max_zoom, maxwidth / 4000);
+	</action>
+
+
+	<action name="webvr_autozoom_stop" scope="private:webvr_autozoom">
+		clearinterval(webvr_autozoom);
+	</action>
+
+
+	<action name="webvr_autozoom_start" scope="private:webvr_autozoom">
+		copy(last_tick, global.timertick);
+		copy(last_movement_tick, last_tick);
+		copy(last_view_hlookat, global.view.hlookat);
+		copy(last_view_vlookat, global.view.vlookat);
+
+		setinterval(webvr_autozoom, 0.1,
+			copy(cur_tick, global.timertick);
+			if(global.webvr.isenabled,
+				getlooktodistance(move_distance, last_view_hlookat, last_view_vlookat);
+				calc(movespeed, move_distance / (cur_tick-last_tick));
+
+				calc(movement_tolerance, 0.01 / (global.webvr.zoom^0.5));
+				if(movespeed GT movement_tolerance,
+					copy(last_movement_tick, cur_tick);
+					tween(zoom_speed, 1.0, 0);
+					Math.pow(movespeed, 0.5);
+				);
+
+				if((cur_tick - last_movement_tick) GT (zoom_delay*1000),
+					tween(zoom_speed, 1.04);
+				);
+
+				calc(new_zoom, global.webvr.zoom * (zoom_speed * (1.0 - movespeed)) );
+				clamp(new_zoom, 1, get(max_zoom));
+				tween(global.webvr.zoom, get(new_zoom), 0.1, linear);
+
+				calc(global.webvr.friction, new_zoom GT 2.0 ? (new_zoom - 2.0) / 100.0 : 0);
+			  ,
+				copy(last_movement_tick, cur_tick);
+			);
+			copy(last_tick, cur_tick);
+			copy(last_view_hlookat, global.view.hlookat);
+			copy(last_view_vlookat, global.view.vlookat);
+		);
+	</action>
+
+</krpano>
+

BIN
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_handcursor.png


BIN
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_laser.png


BIN
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_light.png


BIN
packages/qjkankan-view/public/showviewer/lib/krpano/plugins/webvr_vrcursor.png


+ 4 - 1
packages/qjkankan-view/src/pages/show.vue

@@ -112,7 +112,7 @@ onMounted(async () => {
     // 所有audio入口
 
     const currentSceneData = firstScene || data.scenes[0];
-    
+
     store.dispatch(
       "audio/initNormalBGM",
       data.backgroundMusic ? data.backgroundMusic.ossPath : ""
@@ -206,6 +206,9 @@ onMounted(async () => {
 
       if (isHavePano) {
         app.Scene.on("sceneReady", () => {
+          // krpano 开debug
+          app.krpanoDom.call("showlog(true)");
+
           if (app.krpanoDom) {
             let defaultMask = `%SWFPATH%/skin/masking_${lang}.png`;
 

+ 3 - 0
packages/qjkankan-view/src/pages/showMobile.vue

@@ -204,6 +204,9 @@ onMounted(async () => {
 
       if (isHavePano) {
         app.Scene.on("sceneReady", () => {
+          // krpano 开debug
+          app.krpanoDom.call('showlog(true)');
+
           if (app.krpanoDom) {
             let defaultMask = `%SWFPATH%/skin/masking_${lang}.png`;