Custom Logic

Warning

Chapters for advanced users

These features are for advanced users who want to create more complex applications with the VR-Suite. Basic programming knowledge is required to understand this chapter.

Warning

Data protection must be respected

It is the responsibility of the project creator to maintain GDPR conformity. In case of violations we are obliged to deactivate the account if necessary.

Introduction

To create your own logic based on variables and conditions, custom events can be added to HotSpots, slideshows, SlideSpots and POIs. For example, a survey can be created and different 360° media, slideshows or icons can be displayed depending on the results. Furthermore, variables can also be sent to other programs and to web servers, e.g. to analyze user behavior. It is the responsibility of the project producer to maintain GDPR conformity. In case of violations we are obliged to deactivate the account if necessary.

Example of a Custom Logic (CL) function:

If the corresponding spot is clicked, it is checked if the variable is “LightOn” = “true”. In positive case an external .exe is called and serveral parameters are transferred.

<event type="onClick" condition="lightOn == true" function="startEXE(p4D_Socket_Controller.exe,Local,1,on)" />

There are the following events. See also: Event Types

  • onLoad

  • onClick

  • onUpdate

  • onVideoEnd

  • onSlideshowClose

  • onLevelEnd

  • onItemCollected

Variables:

With the key F8 all defined variables are displayed (Non-VR). They are only added to the list after the respective event has been triggered, i.e. not immediately when the application is started.

Examples for the use of events

Custom events can be added to the following elements:

Location HotSpots

<hotspot text="Light Toggle" scaleH="0.25" distanceH="6" pan="125.267532" tilt="1.29934692" tourHotspot="false" color="" icon="" visibility="visible" iconType="auto">
    <location id="1_3" goalPan="263.314819" goalTilt="-2.24454069" />
    <event type="onLoad" condition="" function="createVariable(lightOn,false)" />
    <event type="onClick" condition="" function="setValue(lightOn,!lightOn)" />
    <event type="onClick" condition="lightOn == true" function="startEXE(p4D_Socket_Controller.exe,Local,1,on)" />
    <event type="onClick" condition="lightOn == false" function="startEXE(p4D_Socket_Controller.exe,Local,1,off)" />
</hotspot>

Slideshow HotSpots

<hotspot text="Tutorial starten" scaleH="1.2" distanceH="10" pan="30.9731445" tilt="13.5549316" tourHotspot="false" color="" icon="Symbol-Video" visibility="visible" iconType="auto">
    <slideshow url="Tutorial/" distance="20.0" scale="3.75" pictureTime="3" playPauseEnabled="true" autoStart="true" />
    <event type="onClick" condition="" function="setValue(lightOn,!lightOn)" />
</hotspot>

Slidespots

With SlideSpots you can enhance slideshow pages with interactive buttons and sounds. This allows you to create more complex quizzes, for example, which can then also influence the conduct of the tour.

<hotspot text="" scaleH="6.5" distanceH="10" pan="1.96492767" tilt="6.89324951" tourHotspot="false" color="" icon="Icon_Uns" visibility="visible" hideText="false">
    <slideshow url="Wir ueber uns/" distance="20.0" scale="3.75" pictureTime="3" playPauseEnabled="false">
        <slidespots>
            <slidespot_icon posx="0.548" posy="0.384" scale="0.4" icon="Punkt" corresponding_file="KPMG1.jpg" iconClick="Punkt-Gefuellt" toggleID="question1">
                <event type="onClick" condition="" function="setValue(question1Answered,1)" />
                <event type="onClick" condition="" function="setValue(question1Score,0)" />
            </slidespot_icon>
        </slidespots>
    </slideshow>
</hotspot>

The positions are each between 0 and 1, where 0|0 is top left and 1|1 is bottom right. 0.5|0.5 is always exactly the center.

Required parameters

  • posx=”0.5” (See above)

  • posy=”0.5” (See above)

  • scale=”1” (Factor for Icon Size)

  • icon=”Icon_example” (must be defined in the media.xml under <icons>)

  • corresponding_file=”1_VR_Tour36.jpg” (the concrete slideshow file within the slideshow, to which these SlideSpots belong)

SlideSpot type: Icon

<slidespot_icon>

A minimal version of a SlideSpot, displays the icon in the specified size and position on the corresponding slide.

<hotspot text="" scaleH="6.5" distanceH="10" pan="1.96492767" tilt="6.89324951" tourHotspot="false" color="" icon="Icon_Uns" visibility="visible">
<slideshow url="Wir ueber uns/" distance="20.0" scale="3.75" pictureTime="3" playPauseEnabled="false">
    <slidespots>
    <slidespot_icon posx="0.5" posy="0.5" scale="1" icon="Icon_Uns" corresponding_file="1_VR_Tour36.jpg" />
    </slidespots>
</slideshow>
</hotspot>

SlideSpot type: Sound

<slidespot_sound>

This SlideSpot is like slidespot_icon, but has the additional ability to play a sound. The sound can either be started with a click or automatically. Only one SlideSpot sound can play at a time. If a new one is started, the old one is stopped automatically.

Additional required parameters

  • sound_file=”sfx/Welcome.wav”

The path to the sound file is given relative to the slideshow folder. It should be used in subfolders, otherwise the sound will also be recognized as a slide.

Additional optional parameters

  • on_end=”nothing” (“nothing”, “loop”)

  • visibility=”visible” (“visible”, “hidden” - still clickable -, “gone”)

  • autostart=”false” (“true”, “false” - should the sound start automatically when calling a slide?)

  • pauseAllOtherSounds=”false” (“true”, “false” - pauses not only other soundspots, but also all sound HotSpots and the background sound)

Example with minimum and maximum parameterization

<hotspot text="" scaleH="6.5" distanceH="10" pan="1.96492767" tilt="6.89324951" tourHotspot="false" color="" icon="Icon_Uns" visibility="visible" hideText="false">
  <slideshow url="Wir ueber uns/" distance="20.0" scale="3.75" pictureTime="3" playPauseEnabled="false">
    <slidespots>
      <slidespot_sound posx=".25" posy=".25" scale="1" icon="Icon_Volksbank" corresponding_file="1_VR_Tour36.jpg" sound_file="sfx/Welcome.wav" />
      <slidespot_sound posx=".25" posy=".25" scale="1" icon="Icon_Volksbank" corresponding_file="1_VR_Tour36.jpg" sound_file="sfx/Welcome.wav" on_end="nothing" visibility="gone" autostart="true" pauseAllOtherSounds="true"/>
    </slidespots>
  </slideshow>
</hotspot>

POI

For POIs, only onLoad and onUpdate are available, as POIs cannot be clicked.

<hotspot pan="135.628" tilt="7.688202" text="" icon="poi" scaleH="0.3" distanceH="6">
    <poi headline="Licht" subheadline="Aus" />
    <event type="onUpdate" condition="lightOn" function="setText(An)" />
    <event type="onUpdate" condition="!lightOn" function="setText(Aus)" />
</hotspot>

Universalspot

<hotspot text="conta_petdander" scaleH="1.5" distanceH="6" pan="-65.1018" tilt="-15.4673309" tourHotspot="false" color="" icon="petdander" visibility="onHoverOnly" iconType="solid" spotID="18">
    <event type="onClick" condition="" function="collectItem(4)" />
</hotspot>

Item

See also Gamification Module: Gamification Modul

<item slot="2" iconDefault="vocs_bar_default" iconFound="vocs_bar" iconTimeOver="vocs_bar_not_found">
    <event type="onClick" condition="$%itemCollected(2)%$  || $%gameIsRunning()%$ == false" function="openSlideshow(1_3/vocs_slides)" />
</item>

Level

See Gamification Module: Gamification Modul

<level id="Level 1" time="90">
     <event type="onLevelEnd" condition="" function="changeVisibility(visible,7)" />

Methods

General

changeIcon(string iconName, int spotID*)

Changes the icon texture of a spot. The icons must be defined in the media.xml.

Example
  • changeIcon(customIcon)

  • changeIcon(customIcon,7)

changeVisibility(string visibility,int spotID*)

Changes the visibility of HotSpots, Slideshows and Overlay Media to hidden, visible or onHoverOnly.

Example
  • changeVisibility(hidden)

  • changeVisibility(hidden,21)

closeSlideshow()

Closes the currently opened slideshow.

createVariable(string nameOfVariable,value*)

Creates a variable and sets it to the specified value. Only executed if the variable is not yet defined. Therefore, it is useful to create a variable with onLoad which is later changed via setValue.

Examples
  • createVariable(lightOn,false)

  • createVariable(question1answered,answerID != 0)

deleteValue(string valueName*)

Deletes a variable and the memory data. If no parameter is given then all values are deleted.

Example
  • deleteValue(quizScore)

  • deleteValue()

enableExecution(bool enable*)

Prevents the execution of the original function of the parent element. For example, the function of the HotSpot can be deactivated so that only custom events are executed.

Example
  • enableExecution(false)

enableGuidedTourArrow(bool enable, int spotID*)

Activates the Guided Tour Arrow and points to the spot with the SpotID.

Example
  • enableGuidedTourArrow(true,9)

executeSpot(int spotID)

Activates the function of a HotSpot located in the same pano. Simulates a click so that Custom Logic is also executed.

Example
  • executeSpot(9)

isInteractive(bool enable,int spotID*)

Enables/disables whether the button is clickable. Useful to make an object visible but not clickable.

Example
  • isInteractive(false)

loadLocation(locID*,optional goalPan*,optional goalTilt*)

Loads a location, either with the default orientation or with goalPan and goalTilt. The entries can also consist of variables.

Example
  • loadLocation(1_2,-40,0)

loadLocation(1_2)

mqtt_publish(broker, port, id_prefix, topic, message)

Send the specified message to the specified Message MQTT Broker.

id_prefix is supplemented by the system time in ticks.

Example
<event type="onClick" condition="" function="mqtt_publish(broker.xyz.de,1916,dfa_cpg3d_A,DFA/CPG3D/MSG,dev rs adress 123456 unit 0 switch on)" />
newQuizSession()

Creates a new line in the QuizResults.csv

Example
  • newQuizSession();

openSlideshow(string url,string picturename)

Opens a slideshow with the specified start image.

Example
  • openSlideshow(1_1/SlideshowMix/,Foto3)

pauseTimer(string variableName)

Pauses the timer. The time value is retained.

Example
  • pauseTimer(myTimer1)

resetTimer(string variableName)

Stops the timer and sets the variable to 0

Example
  • resetTimer(myTimer1)

round(string variableName, int decimals)

Rounds the value to the selected number of decimal places.

Example
  • round(RoundTest,2) -> Makes from 1.973 = 1.97

  • round(RoundTest,0) -> Makes from 1.973 = 2

saveValue(string valueName)

Saves a variable so, that it will be instantiated automatically on restart.

Example
  • saveValue(quizScore)

showNotification(string note)

Shows an indication in the form of a notification.

Example
  • showNotification(Your score is: quizScore)

sendPostRequest(string url,string postVariableName,value*,…,…)

Sends a post request with any number of post variables.

Example

Note

All parameters with a * can contain previously defined variables and operators. For example score + 1. See also Conditions.

setText(value*)

Sets the subheadline of a POI.

Example
  • setText(All systems are running.)

setValue(string nameOfVariable,value*)

Sets the value of a variable.

Example
  • setValue(question1Score,4)

startEXE(string url,parameter*,…,…,…)

Starts an EXE with any number of start parameters. The URL is relative to the data folder. In the example the .exe file is located directly in the Data folder. Only available on Windows. When using this function a warning is displayed.

Example
  • startEXE(p4D_Socket_Controller.exe,Local,1,on)

Example: Open PDF
<hotspot text="Open PDF" scaleH="0.3" distanceH="6" pan="-20.0905457" tilt="-14.8600264" tourHotspot="false" color="" icon="" visibility="visible" iconType="auto" hideText="false">
    <location id="1_2" goalPan="-40.88153" goalTilt="0.533447266" />
    <event type="onClick" condition="" function="enableExecution(false)" />
    <event type="onClick" condition="" function="startEXE(mypdf.pdf)" />
</hotspot>

Example: Switch lights on and off with a HotSpot Toggle and a POI as status indicator. In this example we connected an Arduino Board via USB.

<hotspot text="Light Toggle" scaleH="0.25" distanceH="6" pan="125.267532" tilt="1.29934692" tourHotspot="false" color="" icon="" visibility="visible" iconType="auto">
    <location id="1_3" goalPan="263.314819" goalTilt="-2.24454069" />
    <event type="onClick" condition="" function="enableExecution(false)" />
    <event type="onLoad" condition="" function="createVariable(lightOn,false)" />
    <event type="onClick" condition="" function="setValue(lightOn,!lightOn)" />
    <event type="onClick" condition="lightOn == true" function="startEXE(p4D_Socket_Controller.exe,Local,1,on)" />
    <event type="onClick" condition="lightOn == false" function="startEXE(p4D_Socket_Controller.exe,Local,1,off)" />
</hotspot>
<hotspot pan="135.628" tilt="7.688202" text="" icon="poi" scaleH="0.3" distanceH="6">
    <poi headline="Licht" subheadline="Aus" />
    <event type="onUpdate" condition="lightOn" function="setText(An)" />
    <event type="onUpdate" condition="!lightOn" function="setText(Aus)" />
</hotspot>
startTimer(string variableName)

Creates a timer that stores its value in a variable. The value of the timer is in the unit seconds and is updated every second.

Example
  • startTimer(myTimer1)

startVideoAtTime(Time in seconds)

Jump to a specific video time in the current video. Must be set twice:

  1. onLoad inside the location tag: startVideoAtTime() XXX CHECK IF THIS LINE IS REALLY NECESSARY

  2. onClick inside the HotSpot tag: startVideoAtTime(10)

<location id="1_1" title="on stage" category="" pan="0" tilt="0" backgroundMusic="" northCorrection="0" dateUpId="" dateDownId="" panoOnBackgroundEnd="" volume="0.6">
    <event type="onLoad" condition="" function="startVideoAtTime()" />

    <showVideoControls />
    <hotspot text="to10Sec" scaleH="1" distanceH="6" pan="33.7857437" tilt="2.43096924" visibility="visible" iconType="auto" icon="Symbol-i" spotID="238">
    <event type="onClick" condition="" function="startVideoAtTime(10)" />
    </hotspot>

</location>
startVideoAtTime() & setVideoTime()

Jump to an other 360° video and start it at the current playback time. Must be set twice:

  1. onLoad inside the location tag of the target video: startVideoAtTime()

  2. onClick inside the hotspot tag: setVideoTime()

<location id="1_63" title="Timespots1" category="" pan="0" tilt="0" backgroundMusic="" northCorrection="0" dateUpId="" dateDownId="" panoOnBackgroundEnd="" volume="0.6">
    <event type="onLoad" condition="" function="startVideoAtTime()" />
    <hotspot text="1_54" scaleH="0.25" distanceH="6" pan="-41.049572" tilt="0.369750977" tourHotspot="false" color="" icon="" visibility="visible" iconType="auto" spotID="233">
    <location id="1_54" goalPan="0" goalTilt="0" goalViewLock="true" />
    </hotspot>
    <showVideoControls />
    <hotspot text="Timespots2, current time" scaleH="0.3" distanceH="6" pan="8.282921" tilt="-2.15299" tourHotspot="true" color="" icon="" visibility="visible" iconType="auto" spotID="234">
    <location id="1_64" goalPan="0.009773254" goalTilt="-2.43762779" goalViewLock="False" />
    <event type="onClick" condition="" function="setVideoTime()" />
    <event type="onLoad" condition="" function="startVideoAtTime()" /> XXX CHECK IF THIS LINE IS REALLY NECESSARY
    </hotspot>
</location>
quitApplication()

Closes the VR-Suite.

Gamification Module Methods

See also Gamification Module: Gamification Modul

changeCustomItemIcon(int slotID,string iconName, string levelID*)

Changes the icon of an item from the item bar. Item must be defined as a custom item in the Gamification Modules.

Example
  • changeCustomItemIcon(2,duster_1,Level 1)

collectItem(int slotID, string levelID*)

Collects items and automatically changes the respective icon in the ItemBar. State is automatically saved.

Example
  • collectItem(3,Level 1)

  • collectItem(1)

enableItemBar(bool enable, string levelID*)

Enables/disables the ItemBar from the chapter Gamification and initializes the values to a certain level.

Example
  • enableItemBar(true,Level 1)

pauseItemBarTime(bool enable)

Starts or stops the time within the ItemBar.

Example
  • pauseItemBarTime(false)

  • pauseItemBarTime(true)

removeItem(int slotID, string LevelID)

Deletes the stored data of an item.

resetLevelData(string LevelID)

Deletes the stored data of a level and reloads the information from the XML.

Event Types

onLoad

Is executed when the object is initialized. In most cases while loading the location.

onClick

Is executed when the element is clicked. Not possible for POI.

onUpdate

Currently only available for POI. Is executed every 1/10 second as long as the element is active.

onVideoEnd

Currently only available at OverlayMedia and Slideshow. Important: For Slideshow the VideoControls must be on, otherwise errors may occur.

onEnteredPanoVideoTime(float beginTime, float endTime)

For use as an event: Executed when the time range is reached. Also works when winding, and is also executed again after a loop.

enterPanoVideoTime(float beginTime, float endTime)

For use as a condition: Executed when the time range is reached. Also works when winding, and is also executed again after a loop.

Example
  • enterPanoVideoTime(10, 14)

  • see code examples below “onLeftPanoVideoTime”

onLeftPanoVideoTime(float beginTime, float endTime)

For use as an event: Executed when the time range is left. Also works when winding, and is also executed again after a loop.

Example
  • onLeftPanoVideoTime(10, 14)

Example
  • onEnteredPanoVideoTime(10, 14)

  • see code examples below “onLeftPanoVideoTime”

<event type="onEnterPanoVideoTime(40,120)" condition="” function="changeVisibility(visible)” />
<event type="onLeavePanoVideoTime(40,120)" condition=" function="changeVisibility(notVisible)" />

<event type="onEnterPanoVideoTime(0,40)" condition="” function="changeVisibility(notVisible)” />
<event type="onEnterPanoVideoTime(40,120)" condition=" function="changeVisibility(visible)" />
<event type="onEnterPanoVideoTime(120,160)" condition=" function="changeVisibility(notVisible)" />

<event type="onUpdate" condition="enterPanoVideoTime(0,40)” function="changeVisibility(notVisible)” /> XXX Check enterPanoVideoTime(0,40) or enteredPanoVideoTime(0,40)
<event type="onUpdate" condition="enterPanoVideoTime(40,80)” function="changeVisibility(visible)" />
<event type="onUpdate" condition="enterPanoVideoTime(80,120)” function="changeVisibility(notVisible)" />
onSlideshowClose

Must be added to a Slideshow HotSpot. Will be executed when the slideshow is closed.

onLevelEnd

Is executed when the time of the ItemBar expires or all items have been collected. Can only be added to the ItemBar.

onItemCollected

Is executed when an item is collected. Can only be added to the ItemBar.

onQuizCompleted

For use as a condition: Will be executed when the quiz is completed.

Conditions

With the value Condition expressions can be entered which have the result “True” or “False”. The following characters will be converted to be XML compliant:

“<” -> &lt;

“>” -> &gt;

“&” -> &amp;

Examples:

condition=”lightOn == true”

condition=”finalScore + 2 &gt= 10”

condition=”question1Answered == 1 &amp;&amp; question2Answered == 1 &amp;&amp; question3Answered == 1”

Global Variables

Besides self-defined variables, there are system-specific variables which can be used in Conditions and Methods. These variables are marked as follows:

$%itemCollected(1)%$
  • The function is defined within $% %$.

itemCollected(int slotID)
  • Indicates whether an item was collected or not.

  • Possible return values: true, false

alltemsCollected()
  • Indicates whether all items have been found.

  • Possible return values: true, false

numberOfItemsCollected(string level)
  • Specifies the number of already found items.

  • Possible return values: 1…12

gameIsRunning()
  • The game (the current level) runs when either not all items have been collected or the time is not over yet.

  • Possible return values: true, false

timeOfItemBar(string LevelID)
  • Indicates the number of seconds left in the given level.

currentPlattform()
  • Returns the current platform

  • Possible return values: Android, iOS, Windows

(Basically all these values could be returned: https://docs.unity3d.com/ScriptReference/RuntimePlatform.html but “WindowsEditor” and “WindowsPlayer” were combined under “Windows” and “iPhonePlayer” was renamed to “iOS”.)

currentVRDevice()
  • Returns the current VR glasses.

  • Possible return values: None, Cardboard, GearVR, Oculus, SteamVR

currentSystemTime()
  • Returns the current date & time.

<event type="onLoad" condition="$%currentSystemTime()%$ &gt;= $%date(2017,11,13,13,59)%$" function="changeVisibility(visible,1)" />
getSystemTime()
  • Returns the current system time in seconds

date(y,m,d,h,min)
  • Returns the seconds for a given date, making it comparable using >= <= etc.

  • date(year,month,day,hours,minutes)

  • date(2017,11,18,22,11) For (18. November .2017 - 10:11 pm)

  • date(y,m,d) fills hours and minutes with 0.

Global Settings

The following general settings can be changed for the Custom Logic. The customLogicSettings must be added to the tourSettings in the media.xml:

<customLogicSettings>
    <!---All values will be saved automatically-->
    <saveAllValues>true</saveAllValues>
</customLogicSettings>

Gamification Modul

A gamification module can be created within the toursettings.

ItemBar

_images/ItemBar.png

The ItemBar is a bar which can be used mainly for a certain game logic. It is about the collection of items or hints. The item bar is divided into two areas. Left and right are “item slots” which can be defined. A level can have up to 12 items. The items have three states: default, found, timeOver. For each state an icon can be defined. By using CustomLogic items can be collected. For example, a universal spot in the panorama can serve as an “item” which is collected by onClick. The ItemBar automatically takes care of saving the values, so that even after a restart the already collected items are displayed correctly.

Each item is also a “button” and can, for example, open a slideshow or load a panorama using Custom Logic.

Hint: It is recommended to watch an example tour first.

The Itembar must be added to the Toursettings:

<!---GAMIFICATION -->
    <gamification>
    <itemBar active="true">
        <!---ITEMBAR LEVEL 1-->
        <level id="Level 1" time="300">
        <event type="onLevelEnd" condition="" function="changeVisibility(visible,7)" />
        <event type="onLevelEnd" condition="" function="isInteractive(true,7)" />
        <event type="onLevelEnd" condition="" function="enableGuidedTourArrow(true,7)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,11)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,14)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,16)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,18)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,20)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,22)" />
        <!--- 0 -->
        <event type="onLevelEnd" condition="$%itemCollected(1)%$ == false" function="changeVisibility(visible,11)" />
        <event type="onLevelEnd" condition="$%itemCollected(1)%$ == false" function="changeIcon(co_not_found,11)" />
        <event type="onLevelEnd" condition="$%itemCollected(2)%$ == false" function="changeVisibility(visible,14)" />
        <event type="onLevelEnd" condition="$%itemCollected(2)%$ == false" function="changeIcon(vocs_not_found,14)" />
        <event type="onLevelEnd" condition="$%itemCollected(3)%$ == false" function="changeVisibility(visible,16)" />
        <event type="onLevelEnd" condition="$%itemCollected(3)%$ == false" function="changeIcon(tabacco_not_found,16)" />
        <event type="onLevelEnd" condition="$%itemCollected(4)%$ == false" function="changeVisibility(visible,18)" />
        <event type="onLevelEnd" condition="$%itemCollected(4)%$ == false" function="changeIcon(petdander_not_found,18)" />
        <event type="onLevelEnd" condition="$%itemCollected(5)%$ == false" function="changeVisibility(visible,20)" />
        <event type="onLevelEnd" condition="$%itemCollected(5)%$ == false" function="changeIcon(radon_not_found,20)" />
        <event type="onLevelEnd" condition="$%itemCollected(6)%$ == false" function="changeVisibility(visible,22)" />
        <event type="onLevelEnd" condition="$%itemCollected(6)%$ == false" function="changeIcon(particularmatter_not_found,22)" />
        <!--- 0 -->
        <!--- Notification LevelEnd -->
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="showNotification(notes101)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$" function="showNotification(notes102)" />
        <!--- Notification LevelEnd Ende -->
        <event type="onItemCollected" condition="$%numberOfItemsCollected(Level 1)%$ == 2 || $%numberOfItemsCollected(Level 1)%$ == 3" function="changeCustomItemIcon(7,duster_1_3_full,Level 1)" />
        <event type="onItemCollected" condition="$%numberOfItemsCollected(Level 1)%$ == 4 || $%numberOfItemsCollected(Level 1)%$ == 5" function="changeCustomItemIcon(7,duster_1_2_full,Level 1)" />
        <event type="onItemCollected" condition="$%numberOfItemsCollected(Level 1)%$ == 6" function="changeCustomItemIcon(7,duster_full,Level 1)" />
        <event type="onLevelEnd" condition="$%numberOfItemsCollected(Level 1)%$ == 2 || $%numberOfItemsCollected(Level 1)%$ == 3" function="setValue(completeScore, completeScore + 1/3 + 1/3)" />
        <event type="onLevelEnd" condition="$%numberOfItemsCollected(Level 1)%$ == 4 || $%numberOfItemsCollected(Level 1)%$ == 5" function="setValue(completeScore, completeScore + 0.5)" />
        <event type="onLevelEnd" condition="$%numberOfItemsCollected(Level 1)%$ == 6" function="setValue(completeScore, completeScore + 1)" />
        <event type="onItemCollected" condition="$%numberOfItemsCollected(Level 1)%$ == 2 || $%numberOfItemsCollected(Level 1)%$ == 3" function="changeCustomItemIcon(7,duster_1_3_full,Level 2)" />
        <event type="onItemCollected" condition="$%numberOfItemsCollected(Level 1)%$ == 4 || $%numberOfItemsCollected(Level 1)%$ == 5" function="changeCustomItemIcon(7,duster_1_2_full,Level 2)" />
        <event type="onItemCollected" condition="$%numberOfItemsCollected(Level 1)%$ == 6" function="changeCustomItemIcon(7,duster_full,Level 2)" />
        <event type="onItemCollected" condition="$%numberOfItemsCollected(Level 1)%$ == 2 || $%numberOfItemsCollected(Level 1)%$ == 3" function="changeCustomItemIcon(7,duster_1_3_full,Level 3)" />
        <event type="onItemCollected" condition="$%numberOfItemsCollected(Level 1)%$ == 4 || $%numberOfItemsCollected(Level 1)%$ == 5" function="changeCustomItemIcon(7,duster_1_2_full,Level 3)" />
        <event type="onItemCollected" condition="$%numberOfItemsCollected(Level 1)%$ == 6" function="changeCustomItemIcon(7,duster_full,Level 3)" />
        <!--- ITEMBAR DIRTTRACKER -->
        <item slot="1" iconDefault="co_bar_default" iconFound="co_bar" iconTimeOver="co_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(1)%$  || $%gameIsRunning()%$ == false" function="executeSpot(4)" />
        </item>
        <item slot="2" iconDefault="vocs_bar_default" iconFound="vocs_bar" iconTimeOver="vocs_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(2)%$  || $%gameIsRunning()%$ == false" function="executeSpot(10)" />
        </item>
        <item slot="3" iconDefault="tabacco_bar_default" iconFound="tabacco_bar" iconTimeOver="tabacco_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(3)%$  || $%gameIsRunning()%$ == false" function="executeSpot(9)" />
        </item>
        <item slot="4" iconDefault="petdander_bar_default" iconFound="petdander_bar" iconTimeOver="petdander_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(4)%$  || $%gameIsRunning()%$ == false" function="executeSpot(6)" />
        </item>
        <item slot="5" iconDefault="radon_bar_default" iconFound="radon_bar" iconTimeOver="radon_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(5)%$  || $%gameIsRunning()%$ == false" function="executeSpot(8)" />
        </item>
        <item slot="6" iconDefault="particularmatter_bar_default" iconFound="particularmatter_bar" iconTimeOver="particularmatter_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(6)%$  || $%gameIsRunning()%$ == false" function="executeSpot(5)" />
        </item>
        <!--- ITEMBAR DIRTTRACKER END -->
        <!--- ITEMBAR DUSTER -->
        <item slot="7" customIcon="duster_empty">
        </item>
        <item slot="8" customIcon="duster_empty">
        </item>
        <item slot="9" customIcon="duster_empty">
        </item>
        <item slot="10" customIcon="duster_empty">
        </item>
        <item slot="11" customIcon="duster_empty">
        </item>
        <item slot="12" customIcon="duster_empty">
        </item>
        <!--- ITEMBAR DUSTER END -->
        </level>
        <!---ITEMBAR LEVEL 2 -->
        <level id="Level 2" time="90">
        <event type="onLevelEnd" condition="" function="changeVisibility(visible,52)" />
        <event type="onLevelEnd" condition="" function="isInteractive(true,52)" />
        <event type="onLevelEnd" condition="" function="enableGuidedTourArrow(true,52)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,37)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,43)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,47)" />
        <!--- 0 -->
        <event type="onLevelEnd" condition="$%itemCollected(1)%$ == false" function="changeVisibility(visible,37)" />
        <event type="onLevelEnd" condition="$%itemCollected(1)%$ == false" function="changeIcon(mold_not_found,37)" />
        <event type="onLevelEnd" condition="$%itemCollected(2)%$ == false" function="changeVisibility(visible,43)" />
        <event type="onLevelEnd" condition="$%itemCollected(2)%$ == false" function="changeIcon(bacteria_not_found,43)" />
        <event type="onLevelEnd" condition="$%itemCollected(3)%$ == false" function="changeVisibility(visible,47)" />
        <event type="onLevelEnd" condition="$%itemCollected(3)%$ == false" function="changeIcon(vocs_not_found,47)" />
        <!--- 0 -->
        <event type="onLevelEnd" condition="" function="setValue(timeLeftinPercentLevel2,$%timeOfItemBar(Level 2)%$ / 50)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt;= 0.40" function="changeCustomItemIcon(9,duster_full,Level 2)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt;= 0.40" function="setValue(completeScore, completeScore + 1)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt;= 0.40" function="showNotification(notes201)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt;= 0.15 &amp;&amp; timeLeftinPercentLevel2 &lt; 0.40" function="changeCustomItemIcon(9,duster_1_2_full,Level 2)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt;= 0.15 &amp;&amp; timeLeftinPercentLevel2 &lt; 0.40" function="setValue(completeScore, completeScore + 0.5)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt;= 0.15 &amp;&amp; timeLeftinPercentLevel2 &lt; 0.40" function="showNotification(notes202)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt; 0.00 &amp;&amp; timeLeftinPercentLevel2 &lt; 0.15" function="changeCustomItemIcon(9,duster_1_3_full,Level 2)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt; 0.00 &amp;&amp; timeLeftinPercentLevel2 &lt; 0.15" function="setValue(completeScore, completeScore + 0.333)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt; 0.00 &amp;&amp; timeLeftinPercentLevel2 &lt; 0.15" function="showNotification(notes203)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 == 0.00 " function="showNotification(notes204)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt;= 0.40" function="changeCustomItemIcon(9,duster_full,Level 3)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt;= 0.15 &amp;&amp; timeLeftinPercentLevel2 &lt; 0.40" function="changeCustomItemIcon(9,duster_1_2_full,Level 3)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel2 &gt; 0.00 &amp;&amp; timeLeftinPercentLevel2 &lt; 0.15" function="changeCustomItemIcon(9,duster_1_3_full,Level 3)" />
        <!--- ITEMBAR DIRTTRACKER -->
        <item slot="1" iconDefault="mold_bar_default" iconFound="mold_bar" iconTimeOver="mold_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(1)%$  || $%gameIsRunning()%$ == false" function="executeSpot(49)" />
        </item>
        <item slot="2" iconDefault="bacteria_bar_default" iconFound="bacteria_bar" iconTimeOver="bacteria_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(2)%$  || $%gameIsRunning()%$ == false" function="executeSpot(51)" />
        </item>
        <item slot="3" iconDefault="vocs_bar_default" iconFound="vocs_bar" iconTimeOver="vocs_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(3)%$  || $%gameIsRunning()%$ == false" function="executeSpot(50)" />
        </item>
        <!--- ITEMBAR DIRTTRACKER END -->
        <!--- ITEMBAR DUSTER -->
        <item slot="7" customIcon="duster_empty">
        </item>
        <item slot="8" customIcon="duster_empty">
        </item>
        <item slot="9" customIcon="duster_empty">
        </item>
        <item slot="10" customIcon="duster_empty">
        </item>
        <item slot="11" customIcon="duster_empty">
        </item>
        <item slot="12" customIcon="duster_empty">
        </item>
        <!--- ITEMBAR DUSTER END -->
        </level>
        <!---ITEMBAR LEVEL 3 -->
        <level id="Level 3" time="90">
        <event type="onLevelEnd" condition="" function="changeVisibility(visible,74)" />
        <event type="onLevelEnd" condition="" function="isInteractive(true,74)" />
        <event type="onLevelEnd" condition="" function="enableGuidedTourArrow(true,74)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,59)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,61)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,63)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,65)" />
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,67)" />
        <!--- 0 -->
        <event type="onLevelEnd" condition="$%itemCollected(1)%$ == false" function="changeVisibility(visible,59)" />
        <event type="onLevelEnd" condition="$%itemCollected(1)%$ == false" function="changeIcon(mites_not_found,59)" />
        <event type="onLevelEnd" condition="$%itemCollected(2)%$ == false" function="changeVisibility(visible,61)" />
        <event type="onLevelEnd" condition="$%itemCollected(2)%$ == false" function="changeIcon(pollen_not_found,61)" />
        <event type="onLevelEnd" condition="$%itemCollected(3)%$ == false" function="changeVisibility(visible,63)" />
        <event type="onLevelEnd" condition="$%itemCollected(3)%$ == false" function="changeIcon(viruses_not_found,63)" />
        <event type="onLevelEnd" condition="$%itemCollected(4)%$ == false" function="changeVisibility(visible,65)" />
        <event type="onLevelEnd" condition="$%itemCollected(4)%$ == false" function="changeIcon(ozon_not_found,65)" />
        <event type="onLevelEnd" condition="$%itemCollected(5)%$ == false" function="changeVisibility(visible,67)" />
        <event type="onLevelEnd" condition="$%itemCollected(5)%$ == false" function="changeIcon(oxide_not_found,67)" />
        <!--- 0 -->
        <event type="onLevelEnd" condition="" function="setValue(timeLeftinPercentLevel3,$%timeOfItemBar(Level 3)%$ / 50)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel3 &gt;= 0.50" function="changeCustomItemIcon(11,duster_full,Level 3)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel3 &gt;= 0.50" function="setValue(completeScore, completeScore + 1)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel3 &gt;= 0.50" function="showNotification(notes301)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel3 &gt;= 0.25 &amp;&amp; timeLeftinPercentLevel3 &lt; 0.50" function="changeCustomItemIcon(11,duster_1_2_full,Level 3)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel3 &gt;= 0.25 &amp;&amp; timeLeftinPercentLevel3 &lt; 0.50" function="setValue(completeScore, completeScore + 0.5)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel3 &gt;= 0.25 &amp;&amp; timeLeftinPercentLevel3 &lt; 0.50" function="showNotification(notes302)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel3 &gt; 0.00 &amp;&amp; timeLeftinPercentLevel3 &lt; 0.25" function="changeCustomItemIcon(11,duster_1_3_full,Level 3)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel3 &gt; 0.00 &amp;&amp; timeLeftinPercentLevel3 &lt; 0.25" function="setValue(completeScore, completeScore + 0.333)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel3 &gt; 0.00 &amp;&amp; timeLeftinPercentLevel3 &lt; 0.25" function="showNotification(notes303)" />
        <event type="onLevelEnd" condition="timeLeftinPercentLevel3 == 0.00 " function="showNotification(notes304)" />
        <!--- ITEMBAR DIRTTRACKER -->
        <item slot="1" iconDefault="mites_bar_default" iconFound="mites_bar" iconTimeOver="mites_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(1)%$  || $%gameIsRunning()%$ == false" function="executeSpot(69)" />
        </item>
        <item slot="2" iconDefault="pollen_bar_default" iconFound="pollen_bar" iconTimeOver="pollen_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(2)%$  || $%gameIsRunning()%$ == false" function="executeSpot(70)" />
        </item>
        <item slot="3" iconDefault="viruses_bar_default" iconFound="viruses_bar" iconTimeOver="viruses_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(3)%$  || $%gameIsRunning()%$ == false" function="executeSpot(71)" />
        </item>
        <item slot="4" iconDefault="ozon_bar_default" iconFound="ozon_bar" iconTimeOver="ozon_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(4)%$  || $%gameIsRunning()%$ == false" function="executeSpot(72)" />
        </item>
        <item slot="5" iconDefault="oxide_bar_default" iconFound="oxide_bar" iconTimeOver="oxide_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(5)%$  || $%gameIsRunning()%$ == false" function="executeSpot(73)" />
        </item>
        <!--- ITEMBAR DIRTTRACKER END -->
        <!--- ITEMBAR DUSTER -->
        <item slot="7" customIcon="duster_empty">
        </item>
        <item slot="8" customIcon="duster_empty">
        </item>
        <item slot="9" customIcon="duster_empty">
        </item>
        <item slot="10" customIcon="duster_empty">
        </item>
        <item slot="11" customIcon="duster_empty">
        </item>
        <item slot="12" customIcon="duster_empty">
        </item>
        <!--- ITEMBAR DUSTER END -->
        </level>
        <!---ITEMBAR tutorial-->
        <level id="Tutorial" time="90">
        <event type="onLevelEnd" condition="$%allItemsCollected()%$ == false" function="changeVisibility(visible,91)" />
        <!--- 0 -->
        <event type="onLevelEnd" condition="$%itemCollected(1)%$ == false" function="changeVisibility(visible,91)" />
        <event type="onLevelEnd" condition="$%itemCollected(1)%$ == false" function="changeIcon(vocs_not_found,91)" />
        <!--- 0 -->
        <!--- Notification LevelEnd -->
        <event type="onItemCollected" condition="$%numberOfItemsCollected(Tutorial)%$ == 1" function="changeCustomItemIcon(7,duster_full,Tutorial)" />
        <!--- ITEMBAR DIRTTRACKER -->
        <item slot="1" iconDefault="vocs_bar_default" iconFound="vocs_bar" iconTimeOver="vocs_bar_not_found">
            <event type="onClick" condition="" function="pauseItemBarTime(true)" />
            <event type="onClick" condition="$%itemCollected(1)%$  || $%gameIsRunning()%$ == false" function="executeSpot(96)" />
        </item>
        <!--- ITEMBAR DIRTTRACKER END -->
        <!--- ITEMBAR DUSTER -->
        <item slot="7" customIcon="duster_empty">
        </item>
        <!--- ITEMBAR DUSTER END -->
        </level>
    </itemBar>
</gamification>
<!---END GAMIFICATION-->

Example to collect an item using a universal spot

<hotspot text="conta_vocs" scaleH="1.5" distanceH="6" pan="-28.6029434" tilt="-22.9364414" tourHotspot="false" color="" icon="vocs" visibility="onHoverOnly" iconType="solid" spotID="14">

  <event type="onClick" condition="" function="collectItem(2)" />

</hotspot>

Custom Item

 <item slot="7" customIcon="duster_empty">
    <event type="onClick" condition="" function="openSlideshow(1_3/particularmatter_slides)" />
</item>

The item bar can also be used without the regular game logic, where the item slots are only used to display an icon and run CustomLogic. The icon can also be modified via custom logic using the method changeCustomItemIcon.

Video Tutorials

Visit our Youtube Tutorial Video Channel