--
-- SFM-Modding, LoogleCZ, And other...
-- oroginal IC: 	Manuel Leithner
-- Edit IC:			Martin Fabík (new functions for FS15)
-- and other...
-- 
-- Free for non-comerecial usage
-- 
-- Important note: this is BETA script. If anyone found errors, please contact me at mar.fabik@gmail.com
--                 Script is under active development. You can discuss changes with me at mar.fabik@gmail.com
--
-- version ID   - 2.51
-- 
-- version date - 25.1.2015 (18:14)
-- 
-- NEW: add sound support (attribute 'soundFile' in button tag, that define local path to sound file in mod directory)
-- NEW: add looping animations support (attribute 'looping' in animation button tag - animation must be set as looping too)
--

InteractiveControl = {};

local MDR = g_currentModDirectory;
source(MDR.."ICSources/actionFunction.lua");
source(MDR.."ICSources/extraFunctions.lua");
source(MDR.."ICSources/InteractiveControlEvent.lua");

function InteractiveControl.prerequisitesPresent(specializations)
	return true;
end;

function InteractiveControl:load(xmlFile)
	self.renderOverlayAndInfo = SpecializationUtil.callSpecializationsFunction("renderOverlayAndInfo");
	self.toggleICState = SpecializationUtil.callSpecializationsFunction("toggleICState");
	self.actionOnObject = SpecializationUtil.callSpecializationsFunction("actionOnObject");
	self.updateOpenStatus = SpecializationUtil.callSpecializationsFunction("updateOpenStatus");
	
	source(MDR.."ICSources/functionsInit.lua");
	
	self.LIC = {};
	self.LIC.interactiveObjects = {};
	self.indoorCamIndex = 1;
	self.outdoorCamIndex = 2;
	self.LIC.lastMouseXPos = 0;
	self.LIC.lastMouseYPos = 0;					
	self.LIC.foundInteractiveObject = nil;
	self.LIC.isMouseActive = false;
	self.LIC.minOutsideDistance = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.interactiveComponents#minDist"), 3);
	self.LIC.toggleStateStyle = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.interactiveComponents#toggleStyle"), 0);
	self.LIC.isInOutsideRange = false;
	self.LIC.isInitialized = false;
	self.LIC.isClicked = false;
	self.LIC.camRotPlayer = {};
	self.LIC.partLen = {};
	
	local j = 0;
	--=========================================--
	--             Interactive Window          --
	
	local i=0;
	while true do
		local objectType = 0;
		local key = string.format("vehicle.interactiveComponents.windows.window(%d)", i);	
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		local animation = getXMLString(xmlFile, key .. "#animName");
		local name = g_i18n:getText(Utils.getNoNil((getXMLString(xmlFile, key .. "#name")), "ERROR"));			
		local mark = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#mark"));
		if mark ~= nil then
			local highlight = getChildAt(mark, 0);
			setVisibility(mark,false);
		end;
		local size = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#size"), 0.1);
		local onMessage = g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#onMessage"), "ic_button_on"));
		local offMessage =  g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#offMessage") , "ic_button_off"));
		local vyserSeNaToto = Utils.getNoNil(getXMLBool(xmlFile, key.."#inactive"),false);
		local synch = Utils.getNoNil(getXMLBool(xmlFile, key .. "#synch"), true);
		if animation ~= nil then
			self.LIC.interactiveObjects[j] = {};
			self.LIC.interactiveObjects[j].animation = animation;
			self.LIC.interactiveObjects[j].name = name;
			self.LIC.interactiveObjects[j].mark = mark;
			self.LIC.interactiveObjects[j].highlight = highlight;
			self.LIC.interactiveObjects[j].size = size;
			self.LIC.interactiveObjects[j].onMessage = onMessage;
			self.LIC.interactiveObjects[j].offMessage = offMessage;
			self.LIC.interactiveObjects[j].synch = synch;
			self.LIC.interactiveObjects[j].objectType = objectType;
			self.LIC.interactiveObjects[j].inactive = vyserSeNaToto;
			self.LIC.interactiveObjects[j].isEntered = false;
			self.LIC.interactiveObjects[j].isOpen = false;
			self.LIC.interactiveObjects[j].canOutside = Utils.getNoNil(getXMLBool(xmlFile, key.."#isOutside"), false);
			local sf = getXMLString(xmlFile, key.."#soundFile");
			if sf ~= nil then
				self.LIC.interactiveObjects[j].audio = createSample(string.format("ICSound%d",j));
				loadSample(self.LIC.interactiveObjects[j].audio, MDR..sf, false);
			end;
			self.LIC.interactiveObjects[j].looping = getXMLBool(xmlFile, key.."#looping");

			j = j + 1;
		else
			print(string.format("Cannot load Interactive Window - vehicle.interactiveComponents.windows.window(%d)",i));
		end;
		i = i + 1;
	end;
	self.LIC.partLen.animation = j;
	--=========================================--
	
	--=========================================--
	--           Interactive Buttons           --
	
	local i=0;
	while true do
		local objectType = 1;
		local key = string.format("vehicle.interactiveComponents.buttons.button(%d)", i);	
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		local event = getXMLString(xmlFile, key .. "#event");
		local name = g_i18n:getText(Utils.getNoNil((getXMLString(xmlFile, key .. "#name")), "ERROR"));
		local mark = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#mark"));
		if mark ~= nil then
			local highlight = getChildAt(mark, 0);
			setVisibility(mark,false);
		end;
		local size = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#size"), 0.1);
		local onMessage = g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#onMessage"), "ic_button_on"));
		local offMessage =  g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#offMessage") , "ic_button_off"));
		local synch = Utils.getNoNil(getXMLBool(xmlFile, key .. "#synch"), true);
		local vyserSeNaToto = Utils.getNoNil(getXMLBool(xmlFile, key.."#inactive"),false);
		if event ~= nil then
			self.LIC.interactiveObjects[j] = {};
			self.LIC.interactiveObjects[j].event = event;
			self.LIC.interactiveObjects[j].name = name;
			self.LIC.interactiveObjects[j].mark = mark;
			self.LIC.interactiveObjects[j].highlight = highlight;
			self.LIC.interactiveObjects[j].size = size;
			self.LIC.interactiveObjects[j].onMessage = onMessage;
			self.LIC.interactiveObjects[j].offMessage = offMessage;
			self.LIC.interactiveObjects[j].synch = synch;
			self.LIC.interactiveObjects[j].objectType = objectType;
			self.LIC.interactiveObjects[j].inactive = vyserSeNaToto;
			self.LIC.interactiveObjects[j].isEntered = false;
			self.LIC.interactiveObjects[j].isOpen = false; 
			self.LIC.interactiveObjects[j].canOutside = Utils.getNoNil(getXMLBool(xmlFile, key.."#isOutside"), false);
			local sf = getXMLString(xmlFile, key.."#soundFile");
			if sf ~= nil then
				self.LIC.interactiveObjects[j].audio = createSample(string.format("ICSound%d",j));
				loadSample(self.LIC.interactiveObjects[j].audio, MDR..sf, false);
			end;
			j = j + 1;
		else
			print(string.format("Cannot load Interactive Button - vehicle.interactiveComponents.buttons.button(%d)",i));
		end;		
		i = i + 1;
	end;
	self.LIC.partLen.button = j-self.LIC.partLen.animation;
	--=========================================--
	--=========================================--
	--           Interactive Monitors          --
	
	local i=0;
	local m=0;
	while true do
		local objectType = 2;
		local key = string.format("vehicle.interactiveComponents.monitors.monitor(%d)", i);	
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		local name = g_i18n:getText(Utils.getNoNil((getXMLString(xmlFile, key .. "#name")), "ERROR"));
		local mark = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#mark"));
		if mark ~= nil then
			local highlight = getChildAt(mark, 0);
			setVisibility(mark,false);
		end;
		local size = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#size"), 0.1);
		local useStart = Utils.getNoNil(getXMLBool(xmlFile, key .. "#useStart"), true);
		local startAnimation = getXMLString(xmlFile, key .. "#animName");
		local layerBackupPos = getXMLString(xmlFile, key .. "#layerClosePos");
		local layerVisPos = getXMLString(xmlFile, key .. "#layerVisPos");
		local defaultLayer = getXMLInt(xmlFile, key .. "#defaultLayer");
		local moveDef = getXMLBool(xmlFile, key .. "#moveDefaultLayer");
		local onMessage = g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#onMessage"), "ic_button_on"));
		local offMessage =  g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#offMessage") , "ic_button_off"));
		local vyserSeNaToto = Utils.getNoNil(getXMLBool(xmlFile, key.."#inactive"),false);
		local synch = Utils.getNoNil(getXMLBool(xmlFile, key .. "#synch"), true);
		if name ~= nil and layerBackupPos ~= nil and layerVisPos ~= nil then
			self.LIC.interactiveObjects[j] = {};
			self.LIC.interactiveObjects[j].objectType = objectType;
			self.LIC.interactiveObjects[j].name = name;
			self.LIC.interactiveObjects[j].mark = mark;
			self.LIC.interactiveObjects[j].highlight = highlight;
			self.LIC.interactiveObjects[j].size = size;
			self.LIC.interactiveObjects[j].onMessage = onMessage;
			self.LIC.interactiveObjects[j].offMessage = offMessage;
			self.LIC.interactiveObjects[j].synch = synch;
			self.LIC.interactiveObjects[j].useStart = useStart;
			self.LIC.interactiveObjects[j].startAnimation = startAnimation;
			self.LIC.interactiveObjects[j].defaultLayer = defaultLayer;
			self.LIC.interactiveObjects[j].moveDef = moveDef;
			self.LIC.interactiveObjects[j].inactive = vyserSeNaToto;
			self.LIC.interactiveObjects[j].layerBackupPos = {};
			self.LIC.interactiveObjects[j].layerBackupPos[1],self.LIC.interactiveObjects[j].layerBackupPos[2],self.LIC.interactiveObjects[j].layerBackupPos[3] = Utils.getVectorFromString(layerBackupPos);
			self.LIC.interactiveObjects[j].layerVisPos = {};
			self.LIC.interactiveObjects[j].layerVisPos[1],self.LIC.interactiveObjects[j].layerVisPos[2],self.LIC.interactiveObjects[j].layerVisPos[3] = Utils.getVectorFromString(layerVisPos);
			self.LIC.interactiveObjects[j].isEntered = false;
			self.LIC.interactiveObjects[j].isOpen = false;
			self.LIC.interactiveObjects[j].canOutside = Utils.getNoNil(getXMLBool(xmlFile, key.."#isOutside"), false);			
			local sf = getXMLString(xmlFile, key.."#soundFile");
			if sf ~= nil then
				self.LIC.interactiveObjects[j].audio = createSample(string.format("ICSound%d",j));
				loadSample(self.LIC.interactiveObjects[j].audio, MDR..sf, false);
			end;		
			self.LIC.interactiveObjects[j].activeLayer = defaultLayer;
			self.LIC.interactiveObjects[j].layerButtons = {};
			self.LIC.interactiveObjects[j].layerIndexes = {};
			local k = 0;
			local upperLayerIndex = j;
			while true do
				local key2 = string.format(key..".layer(%d)", k);
				if not hasXMLProperty(xmlFile, key2) then
					break;
				end;
				local name = Utils.getNoNil((getXMLString(xmlFile, key2 .. "#name")), "ERROR");
				local index = Utils.indexToObject(self.components, getXMLString(xmlFile, key2 .. "#index"));
				local size = Utils.getNoNil(getXMLFloat(xmlFile, key2 .. ".open#size"), 0.1);
				local mark = Utils.indexToObject(self.components, getXMLString(xmlFile, key2 .. ".open#mark"));
				if mark ~= nil then
					local highlight = getChildAt(mark, 0);
					setVisibility(mark, false);
				end;
				local size1 = Utils.getNoNil(getXMLFloat(xmlFile, key2 .. ".close#size"), 0.1);
				local mark1 = Utils.indexToObject(self.components, getXMLString(xmlFile, key2 .. ".close#mark"));
				if mark1 ~= nil then
					local highlight1 = getChildAt(mark1, 0);
					setVisibility(mark1, false);
				end;
				local onMessage = g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key2 .. "#onMessage"), "ic_button_on"));
				local offMessage =  g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key2 .. "#offMessage") , "ic_button_off"));
				local synch = Utils.getNoNil(getXMLBool(xmlFile, key2 .. "#synch"), true);
				if index ~= nil and name ~= nil then
					self.LIC.interactiveObjects[upperLayerIndex].layerIndexes[k] = index;
					if mark1 ~= nil and mark ~= nil then
						j = j + 1;
						m = m + 1;
						self.LIC.interactiveObjects[j] = {};
						self.LIC.interactiveObjects[j].event = "openDisplayLayer";
						self.LIC.interactiveObjects[j].objectType = 1;
						self.LIC.interactiveObjects[j].index = k;
						self.LIC.interactiveObjects[j].name = name;
						self.LIC.interactiveObjects[j].mark = mark;
						self.LIC.interactiveObjects[j].highlight = highlight;
						self.LIC.interactiveObjects[j].size = size;
						self.LIC.interactiveObjects[j].onMessage = onMessage;
						self.LIC.interactiveObjects[j].offMessage = onMessage;
						self.LIC.interactiveObjects[j].synch = synch;
						self.LIC.interactiveObjects[j].inactive = inactive;
						self.LIC.interactiveObjects[j].parentLayer = upperLayerIndex;
						self.LIC.interactiveObjects[j].isOpen = true;
						local sf = getXMLString(xmlFile, key2..".open#soundFile");
						if sf ~= nil then
							self.LIC.interactiveObjects[j].audio = createSample(string.format("ICSound%d",j));
							loadSample(self.LIC.interactiveObjects[j].audio, MDR..sf, false);
						end;						
						table.insert(self.LIC.interactiveObjects[upperLayerIndex].layerButtons,j);
						j = j + 1;
						m = m + 1;
						self.LIC.interactiveObjects[j] = {};
						self.LIC.interactiveObjects[j].event = "closeDisplayLayer";
						self.LIC.interactiveObjects[j].objectType = 1;
						self.LIC.interactiveObjects[j].index = k;
						self.LIC.interactiveObjects[j].name = name;
						self.LIC.interactiveObjects[j].mark = mark1;
						self.LIC.interactiveObjects[j].highlight = highlight1;
						self.LIC.interactiveObjects[j].size = size1;
						self.LIC.interactiveObjects[j].onMessage = offMessage;
						self.LIC.interactiveObjects[j].offMessage = offMessage;
						self.LIC.interactiveObjects[j].inactive = inactive1;
						self.LIC.interactiveObjects[j].synch = synch;
						self.LIC.interactiveObjects[j].parentLayer = upperLayerIndex;
						self.LIC.interactiveObjects[j].isOpen = false;
						local sf = getXMLString(xmlFile, key2..".close#soundFile");
						if sf ~= nil then
							self.LIC.interactiveObjects[j].audio = createSample(string.format("ICSound%d",j));
							loadSample(self.LIC.interactiveObjects[j].audio, MDR..sf, false);
						end;
						table.insert(self.LIC.interactiveObjects[upperLayerIndex].layerButtons,j);
						setVisibility(index, false);
					end;
				end;
				k = k + 1;
			end;
			j = j + 1;
			m = m + 1;
			self:actionOnObject(upperLayerIndex, false);
		else
			print(string.format("Cannot load Interactive monitor - vehicle.interactiveComponents.monitors.monitor(%d)",i));
		end;
		i = i + 1;
	end;
	self.LIC.partLen.monitor = m;
	--=========================================--
	--=========================================--
	--         Interactive visibility          --
	
	local i=0;
	local m=0;
	while true do
		local objectType = 3;
		local key = string.format("vehicle.interactiveComponents.visControls.button(%d)", i);	
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		local name = g_i18n:getText(Utils.getNoNil((getXMLString(xmlFile, key .. "#name")), "ERROR"));			
		local mark = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#mark"));
		if mark ~= nil then
			local highlight = getChildAt(mark, 0);
			setVisibility(mark,false);
		end;
		local size = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#size"), 0.1);
		local onMessage = g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#onMessage"), "ic_button_on"));
		local offMessage =  g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#offMessage") , "ic_button_off"));		
		local synch = Utils.getNoNil(getXMLBool(xmlFile, key .. "#synch"), true);
		local defVis = getXMLBool(xmlFile, key .. "#defaultVis");
		local typeChange = Utils.getNoNil(getXMLString(xmlFile, key .. "#typeChange"), "set");
		local controlObject = getXMLString(xmlFile, key .. "#controlElem");
		local inactive = Utils.getNoNil(getXMLBool(xmlFile, key.."#inactive"),false);
		if name ~= nil then
			self.LIC.interactiveObjects[j] = {};
			self.LIC.interactiveObjects[j].name = name;
			self.LIC.interactiveObjects[j].mark = mark;
			self.LIC.interactiveObjects[j].highlight = highlight;
			self.LIC.interactiveObjects[j].size = size;
			self.LIC.interactiveObjects[j].onMessage = onMessage;
			self.LIC.interactiveObjects[j].offMessage = offMessage;
			self.LIC.interactiveObjects[j].synch = synch;
			self.LIC.interactiveObjects[j].objectType = objectType;
			self.LIC.interactiveObjects[j].typeChange = typeChange;
			self.LIC.interactiveObjects[j].inactive = inactive;
			self.LIC.interactiveObjects[j].isEntered = false;
			self.LIC.interactiveObjects[j].isOpen = false;
			self.LIC.interactiveObjects[j].canOutside = Utils.getNoNil(getXMLBool(xmlFile, key.."#isOutside"), false);
			local sf = getXMLString(xmlFile, key.."#soundFile");
			if sf ~= nil then
				self.LIC.interactiveObjects[j].audio = createSample(string.format("ICSound%d",j));
				loadSample(self.LIC.interactiveObjects[j].audio, MDR..sf, false);
			end;
			if controlObject ~= nil then
				self.LIC.interactiveObjects[j].controlObject = Utils.indexToObject(self.components, controlObject); 
			end;
			self.LIC.interactiveObjects[j].objects = {};
			local k = 0;
			while true do
				local key2 = string.format(key..".index(%d)", k);
				if not hasXMLProperty(xmlFile, key2) then
					break;
				end;
				local index = getXMLString(xmlFile, key2.."#index");
				if index ~= nil then
					self.LIC.interactiveObjects[j].objects[(k+1)] = Utils.indexToObject(self.components, index);
					if defVis ~= nil then
						setVisibility(self.LIC.interactiveObjects[j].objects[(k+1)], defVis);
					end;
				end;
				k = k + 1;
			end;
			j = j + 1;
			m = m + 1;
		else
			print(string.format("Cannot load Interactive visibility - vehicle.interactiveComponents.visControls.button(%d)",i));
		end;
		i = i + 1;
	end;
	self.LIC.partLen.visibility = m;
	--=========================================--
	
	--============ MULTI BUTTONS ==============--

	local i=0;
	self.LIC.partLen.mbutton = 0;
	while true do
		local objectType = 4;
		local key = string.format("vehicle.interactiveComponents.multiButtons.mbutton(%d)", i);	
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		local name = g_i18n:getText(Utils.getNoNil((getXMLString(xmlFile, key .. "#name")), "ERROR"));
		local mark = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#mark"));
		if mark ~= nil then
			setVisibility(mark,false);
			local highlight = getChildAt(mark, 0);
		end;
		local size = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#size"), 0.1);
		local onMessage = g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#onMessage"), "ic_button_on"));
		local offMessage =  g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#offMessage") , "ic_button_off"));
		local synch = Utils.getNoNil(getXMLBool(xmlFile, key .. "#synch"), true);
		local inactive = Utils.getNoNil(getXMLBool(xmlFile, key.."#inactive"),false);
		if name ~= nil then
			self.LIC.interactiveObjects[j] = {};
			self.LIC.interactiveObjects[j].name = name;
			self.LIC.interactiveObjects[j].mark = mark;
			self.LIC.interactiveObjects[j].highlight = highlight;
			self.LIC.interactiveObjects[j].size = size;
			self.LIC.interactiveObjects[j].onMessage = onMessage;
			self.LIC.interactiveObjects[j].offMessage = offMessage;
			self.LIC.interactiveObjects[j].synch = synch;
			self.LIC.interactiveObjects[j].objectType = objectType;
			self.LIC.interactiveObjects[j].isEntered = false;
			self.LIC.interactiveObjects[j].isOpen = false; 
			self.LIC.interactiveObjects[j].inactive = inactive; 
			self.LIC.interactiveObjects[j].canOutside = Utils.getNoNil(getXMLBool(xmlFile, key.."#isOutside"), false);
			local sf = getXMLString(xmlFile, key.."#soundFile");
			if sf ~= nil then
				self.LIC.interactiveObjects[j].audio = createSample(string.format("ICSound%d",j));
				loadSample(self.LIC.interactiveObjects[j].audio, MDR..sf, false);
			end;
			if hasXMLProperty(xmlFile, key..".control") then
				local mbtype = getXMLString(xmlFile, key..".control#type");
				local index = getXMLInt(xmlFile, key..".control#index");
				if index <= self.LIC.partLen[mbtype] then
					local indexFinal = index;
					if mbtype == "animation" then
					elseif mbtype == "button" then
						indexFinal = indexFinal + self.LIC.partLen.animation;
					elseif mbtype == "monitor" then
						indexFinal = indexFinal + self.LIC.partLen.button + self.LIC.partLen.animation;
					elseif mbtype == "visibility" then
						indexFinal = indexFinal + self.LIC.partLen.monitor + self.LIC.partLen.button + self.LIC.partLen.animation;
					elseif mbtype == "mbutton" then
						indexFinal = indexFinal + self.LIC.partLen.visibility + self.LIC.partLen.monitor + self.LIC.partLen.button + self.LIC.partLen.animation;
					end;
					self.LIC.interactiveObjects[j].controlElement = indexFinal;
				end;
			end;
			local k = 0;
			self.LIC.interactiveObjects[j].actionElements = {};
			while true do
				key2 = string.format(key..".part(%d)",k);
				if not hasXMLProperty(xmlFile, key2) then
					break;
				end;
				local mbtype = getXMLString(xmlFile, key2.."#type");
				local index = getXMLInt(xmlFile, key2.."#index");
				if index <= self.LIC.partLen[mbtype] then
					local indexFinal = index;
					if mbtype == "animation" then
					elseif mbtype == "button" then
						indexFinal = indexFinal + self.LIC.partLen.animation;
					elseif mbtype == "monitor" then
						indexFinal = indexFinal + self.LIC.partLen.button + self.LIC.partLen.animation;
					elseif mbtype == "visibility" then
						indexFinal = indexFinal + self.LIC.partLen.monitor + self.LIC.partLen.button + self.LIC.partLen.animation;
					elseif mbtype == "mbutton" then
						indexFinal = indexFinal + self.LIC.partLen.visibility + self.LIC.partLen.monitor + self.LIC.partLen.button + self.LIC.partLen.animation;
					end;
					table.insert(self.LIC.interactiveObjects[j].actionElements,indexFinal);
				end;
				k = k + 1;
			end;
			j = j + 1;
			self.LIC.partLen.mbutton = self.LIC.partLen.mbutton + 1;
		else
			print(string.format("Cannot load Interactive Button - vehicle.interactiveComponents.buttons.button(%d)",i));
		end;		
		i = i + 1;
	end;
	
	--=========================================--
	self.LIC.joints = {};
	self.LIC.joints.front = {};
	self.LIC.joints.back = {};
	for k,joint in pairs(self.attacherJoints) do
		if joint.jointType == Vehicle.JOINTTYPE_IMPLEMENT or joint.jointType == Vehicle.JOINTTYPE_CUTTER or joint.jointType == Vehicle.JOINTTYPE_CUTTERHARVESTER or joint.jointType == Vehicle.JOINTTYPE_TRAILER or joint.jointType == Vehicle.JOINTTYPE_TRAILERLOW then
			local x,y,z = getWorldTranslation(self.attacherJoints[k].jointTransform);
			local rx,ry,rz = worldToLocal(self.rootNode,x,y,z);
			if rz > 0 then
				table.insert(self.LIC.joints.front,k);
			else
				table.insert(self.LIC.joints.back,k);
			end;
		end;
	end;
end;

function InteractiveControl:delete()
end;

function InteractiveControl:readStream(streamId, connection)
	local icCount = streamReadInt8(streamId);
	for i=0, icCount do
		local LICId = streamReadInt8(streamId);
		local isOpen = streamReadBool(streamId);
		if self.LIC.interactiveObjects[LICId] ~= nil then
			if self.LIC.interactiveObjects[LICId].synch then
				self:actionOnObject(LICId, isOpen);
			end;
		end;
	end;
end;

function InteractiveControl:writeStream(streamId, connection)
	local icCount = (table.getn(self.LIC.interactiveObjects)-1);
	streamWriteInt8(streamId, icCount);
	for i=0, icCount do
		streamWriteInt8(streamId, i);
		streamWriteBool(streamId, self.LIC.interactiveObjects[i].isOpen);
	end;
end;

function InteractiveControl:mouseEvent(posX, posY, isDown, isUp, button)
end;

function InteractiveControl:keyEvent(unicode, sym, modifier, isDown)
end;

function InteractiveControl:update(dt)
	local blockToggle = false;
	if self.isMotorStarted then
		self.forceIsActive = true;
		if not self.LIC.isInitialized then
			self.LIC.isInitialized = not self.LIC.isInitialized;
			for k,v in pairs(self.LIC.interactiveObjects) do
				if v.objectType == 2 and v.useStart then
					self:actionOnObject(k, true);
				end;
			end;
		end;
	else
		self.forceIsActive = false;
		if self.LIC.isInitialized then
			self.LIC.isInitialized = not self.LIC.isInitialized;
			for k,v in pairs(self.LIC.interactiveObjects) do
				if v.objectType == 2 then
					self:actionOnObject(k, false);
				end;
			end;
		end;
	end;
	
	if Input.isMouseButtonPressed(Input.MOUSE_BUTTON_LEFT) and self.LIC.foundInteractiveObject ~= nil then
		if not self.LIC.isClicked then
			self.LIC.isClicked = true;
			self:actionOnObject(self.LIC.foundInteractiveObject);
		end;
	else
		self.LIC.isClicked = false;
	end;
	if self.isMouseActive then
		self.mouseButton = MouseControlsVehicle.BUTTON_NONE;
	end;
	self.LIC.foundInteractiveObject = nil;
	if self.LIC.isInOutsideRange and not blockToggle then
		if self.LIC.isMouseActive then
			g_currentMission:addHelpButtonText(g_i18n:getText("InteractiveControl_Off"), InputBinding.INTERACTIVE_CONTROL_SWITCH);
		else
			g_currentMission:addHelpButtonText(g_i18n:getText("InteractiveControl_On"), InputBinding.INTERACTIVE_CONTROL_SWITCH);
		end;
		if self.LIC.toggleStateStyle == 0 then
			if InputBinding.hasEvent(InputBinding.INTERACTIVE_CONTROL_SWITCH) then
				self:toggleICState(true);
			end;
		elseif self.LIC.toggleStateStyle == 1 then
			if InputBinding.isPressed(InputBinding.INTERACTIVE_CONTROL_SWITCH) then
				self:toggleICState(true,true);
			else
				self:toggleICState(true,false);
			end;
		end;
		blockToggle = true;
	end;
	if self:getIsActive() then
		if self.isClient and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() and not blockToggle then
			if self.LIC.isMouseActive then
				g_currentMission:addHelpButtonText(g_i18n:getText("InteractiveControl_Off"), InputBinding.INTERACTIVE_CONTROL_SWITCH);
			else
				g_currentMission:addHelpButtonText(g_i18n:getText("InteractiveControl_On"), InputBinding.INTERACTIVE_CONTROL_SWITCH);
			end;
			if self.LIC.toggleStateStyle == 0 then
				if InputBinding.hasEvent(InputBinding.INTERACTIVE_CONTROL_SWITCH) then
					self:toggleICState(false);
				end;
			elseif self.LIC.toggleStateStyle == 1 then
				if InputBinding.isPressed(InputBinding.INTERACTIVE_CONTROL_SWITCH) then
					self:toggleICState(false,true);
				else
					self:toggleICState(false,false);
				end;
			end;
			blockToggle = true;
		end;
	end;
	if self.LIC.isMouseActive then
		for _,v in pairs(self.LIC.interactiveObjects) do
			v.isEntered = false;
		end
		if InputBinding.mousePosXLast ~= nil and InputBinding.mousePosYLast ~= nil then
			for k,v in pairs(self.LIC.interactiveObjects) do
				if v.mark ~= nil and self.LIC.foundInteractiveObject == nil then
					local worldX,worldY,worldZ = getWorldTranslation(v.mark);
					local x,y,z = project(worldX,worldY,worldZ);
					if z <= 1 then
						if InputBinding.mousePosXLast > (x-v.size/2) and InputBinding.mousePosXLast < (x+v.size/2) then
							if InputBinding.mousePosYLast > (y-v.size/2) and InputBinding.mousePosYLast < (y+v.size/2) then
								if self.isEntered and not v.canOutside then
									v.isEntered = true;
									self:renderOverlayAndInfo(v);
									self.LIC.foundInteractiveObject = k;
									break;
								end;
								if not self.isEntered and v.canOutside then
									v.isEntered = true;
									self:renderOverlayAndInfo(v);
									self.LIC.foundInteractiveObject = k;
									break;
								end;
							end;
						end;
					end;
				end;
			end;
		end;
	end;
end;

function InteractiveControl:updateTick(dt)
	if g_currentMission.player ~= nil then
		local nearestDistance = self.LIC.minOutsideDistance;
		local px, py, pz = getWorldTranslation(self.rootNode); 
		local vx, vy, vz = getWorldTranslation(g_currentMission.player.rootNode);
		local distance = Utils.vector3Length(px-vx, py-vy, pz-vz);
		if distance < nearestDistance then
			self.LIC.isInOutsideRange = true;
		else
			if self.LIC.isInOutsideRange then
				self:toggleICState(nil, false);
				self.LIC.isInOutsideRange = false;
			end;
		end;
	end;
end;

function InteractiveControl:draw()
end;

function InteractiveControl:onEnter()
end;

function InteractiveControl:onLeave()
	self:toggleICState(nil, false);
	g_mouseControlsHelp.active = true;
	if g_gui.currentGui == nil then
		InputBinding.setShowMouseCursor(false);
	end;
end;

function InteractiveControl:renderOverlayAndInfo(object)
	if object.isOpen then
		g_currentMission:addExtraPrintText(string.format(object.offMessage, object.name));
	else
		g_currentMission:addExtraPrintText(string.format(object.onMessage, object.name));
	end;
end;

function InteractiveControl:toggleICState(isOutside, forceStatus)
	if self.LIC.isMouseActive ~= forceStatus then
		if forceStatus == nil then
			self.LIC.isMouseActive = not self.LIC.isMouseActive;
		else
			self.LIC.isMouseActive = forceStatus;
		end;
		g_mouseControlsHelp.active = not self.LIC.isMouseActive;
		if self.LIC.isMouseActive then

			if g_currentMission.player ~= nil then
				g_currentMission.player.walkingIsLocked = true;
			end;
			
			InputBinding.setShowMouseCursor(true);
			for _,v in pairs(self.cameras) do
				v.isActivated = false;
			end;
		else 
			
			if g_currentMission.player ~= nil then
				g_currentMission.player.walkingIsLocked = false;
			end;

			InputBinding.setShowMouseCursor(false);
			for _,v in pairs(self.LIC.interactiveObjects) do
				v.isEntered = false;
				if v.mark ~= nil then
					setVisibility(v.mark, false);
				end;
			end;
			for _,v in pairs(self.cameras) do
				v.isActivated = true;
			end;
		end;
		if self.LIC.isMouseActive then
			for k,v in pairs(self.LIC.interactiveObjects) do
				if isOutside and v.canOutside then
					if v.mark ~= nil then
						setVisibility(v.mark, true);
					end;
				elseif (not isOutside or isOutside == nil) and not v.canOutside then
					if v.mark ~= nil then
						setVisibility(v.mark, true);
					end;
				end;
			end;
		end;
		if not self.LIC.isMouseActive then
			self.LIC.foundInteractiveObject = nil;
		end;
	end;
end;