--
-- Big thanks to all of those who helped with development of IC
-- SFM-Modding, LoogleCZ, And other...
-- Original IC:                     Manuel Leithner
-- Edit IC and current development: Martin Fabík (LoogleCZ)
-- Testing: Daniel Zapletal, Martin Fabík
-- and others...
-- 
-- 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.95
-- version date - 24.4.2016 (19:44)
--

if originalInputBindingUpdate == nil then
	originalInputBindingUpdate = InputBinding.update;
	InputBinding.update = function(dt)
		InputBinding.accumMouseMovementXBackUp = InputBinding.accumMouseMovementX;
		InputBinding.accumMouseMovementYBackUp = InputBinding.accumMouseMovementY;
		originalInputBindingUpdate(dt);
	end;
end;

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(savegame)
	self.renderOverlayAndInfo = SpecializationUtil.callSpecializationsFunction("renderOverlayAndInfo");
	self.toggleICState = SpecializationUtil.callSpecializationsFunction("toggleICState");
	self.actionOnObject = SpecializationUtil.callSpecializationsFunction("actionOnObject");
	self.updateOpenStatus = SpecializationUtil.callSpecializationsFunction("updateOpenStatus");
	self.loadICButtonFromXML = InteractiveControl.loadICButtonFromXML;
	
	source(MDR.."ICSources/functionsInit.lua");
	
	self.LIC = {};
	self.LIC.interactiveObjects = {};
	self.LIC.objectsListeners = {};
	self.LIC.getElementListeners = {};
	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(self.xmlFile,"vehicle.interactiveComponents#minDist"), 3);
	self.LIC.toggleStateStyle = Utils.getNoNil(getXMLFloat(self.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;
	--=========================================--
	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;
	--=========================================--
	--             Interactive Window          --
	
	local i=0;
	while true do
		local objectType = 0;
		local key = string.format("vehicle.interactiveComponents.windows.window(%d)", i);	
		if not hasXMLProperty(self.xmlFile, key) then
			break;
		end;
		local animation = getXMLString(self.xmlFile, key .. "#animName");
		local looping = Utils.getNoNil(getXMLBool(self.xmlFile, key.."#looping"), false);
		local speedScale = -Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#animSpeedScale"), 1);
		local clipParent = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#clipRoot"));
		local animClip = nil;
		if clipParent ~= nil and clipParent ~= 0 then
			animClip = {};
			animClip.animCharSet = getAnimCharacterSet(clipParent);
			if animClip.animCharSet ~= 0 then
				local clip = getAnimClipIndex(animClip.animCharSet, getXMLString(self.xmlFile, key .. "#clip"));
				assignAnimTrackClip(animClip.animCharSet, 0, clip);
				setAnimTrackLoopState(animClip.animCharSet, 0, looping);
				animClip.animDuration = getAnimClipDuration(animClip.animCharSet, clip);
				setAnimTrackTime(animClip.animCharSet, 0, 0);
			end;
		end;
		if animation ~= nil or animClip ~= nil then
			self.LIC.interactiveObjects[j] = {};
			self.LIC.interactiveObjects[j].animation = animation;
			self.LIC.interactiveObjects[j].animClip = animClip;
			self.LIC.interactiveObjects[j].speedScale = speedScale;
			self.LIC.interactiveObjects[j].objectType = objectType;
			self.LIC.interactiveObjects[j].looping = looping;
			self.LIC.interactiveObjects[j].isEntered = false;
			self:loadICButtonFromXML(self.xmlFile, key, self.LIC.interactiveObjects[j], j);
			j = j + 1;
		else
			print(string.format("Cannot load Interactive Window - vehicle.interactiveComponents.windows.window(%d)",i));
			print("  - Missing animation or animation clip.");
		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(self.xmlFile, key) then
			break;
		end;
		local event = getXMLString(self.xmlFile, key .. "#event");
		if event ~= nil then
			self.LIC.interactiveObjects[j] = {};
			self.LIC.interactiveObjects[j].event = event;
			self.LIC.interactiveObjects[j].objectType = objectType;
			self.LIC.interactiveObjects[j].isEntered = false;
			self:loadICButtonFromXML(self.xmlFile, key, self.LIC.interactiveObjects[j], j);
			if string.sub( self.LIC.interactiveObjects[j].event, 1, 10 ) == "l2gsToggle" then
				self.LIC.interactiveObjects[j].synch = false;
			end;
			j = j + 1;
		else
			print(string.format("Cannot load Interactive Button - vehicle.interactiveComponents.buttons.button(%d)",i));
			print("  - missing event");
		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(self.xmlFile, key) then
			break;
		end;
		local useStart = Utils.getNoNil(getXMLBool(self.xmlFile, key .. "#useStart"), true);
		local startAnimation = getXMLString(self.xmlFile, key .. "#animName");
		local layerBackupPos = getXMLString(self.xmlFile, key .. "#layerClosePos");
		local layerVisPos = getXMLString(self.xmlFile, key .. "#layerVisPos");
		local defaultLayer = getXMLInt(self.xmlFile, key .. "#defaultLayer");
		local moveDef = Utils.getNoNil(getXMLBool(self.xmlFile, key .. "#moveDefaultLayer"), false);
		if layerBackupPos ~= nil and layerVisPos ~= nil then
			self.LIC.interactiveObjects[j] = {};
			self.LIC.interactiveObjects[j].objectType = objectType;
			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].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].activeLayer = defaultLayer;
			self.LIC.interactiveObjects[j].layerButtons = {};
			self.LIC.interactiveObjects[j].layerIndexes = {};
			self:loadICButtonFromXML(self.xmlFile, key, self.LIC.interactiveObjects[j]);
			local k = 0;
			local upperLayerIndex = j;
			while true do
				local key2 = string.format(key..".layer(%d)", k);
				if not hasXMLProperty(self.xmlFile, key2) then
					break;
				end;
				local name = Utils.getNoNil((getXMLString(self.xmlFile, key2 .. "#name")), "ERROR");
				local index = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key2 .. "#index"));
				local size = Utils.getNoNil(getXMLFloat(self.xmlFile, key2 .. ".open#size"), 0.1);
				local mark = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key2 .. ".open#mark"));
				local size1 = Utils.getNoNil(getXMLFloat(self.xmlFile, key2 .. ".close#size"), 0.1);
				local mark1 = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key2 .. ".close#mark"));
				local onMessage = g_i18n:getText(Utils.getNoNil(getXMLString(self.xmlFile, key2 .. "#onMessage"), "ic_button_on"));
				local offMessage =  g_i18n:getText(Utils.getNoNil(getXMLString(self.xmlFile, key2 .. "#offMessage") , "ic_button_off"));
				if mark ~= nil then
					setVisibility(mark,false);
				end;
				if mark1 ~= nil then
					setVisibility(mark1,false);
				end;
				if index ~= 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].size = size;
						self.LIC.interactiveObjects[j].onMessage = onMessage;
						self.LIC.interactiveObjects[j].offMessage = onMessage;
						self.LIC.interactiveObjects[j].synch = self.LIC.interactiveObjects[upperLayerIndex].synch;
						self.LIC.interactiveObjects[j].parentLayer = upperLayerIndex;
						self.LIC.interactiveObjects[j].isOpen = false;
						local sf = getXMLString(self.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].size = size1;
						self.LIC.interactiveObjects[j].onMessage = offMessage;
						self.LIC.interactiveObjects[j].offMessage = offMessage;
						self.LIC.interactiveObjects[j].synch = self.LIC.interactiveObjects[upperLayerIndex].synch;
						self.LIC.interactiveObjects[j].parentLayer = upperLayerIndex;
						self.LIC.interactiveObjects[j].isOpen = false;
						local sf = getXMLString(self.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);
						-- prvne open a potom close
					end;
				end;
				k = k + 1;
			end;
			j = j + 1;
			m = m + 1;
			self:actionOnObject(upperLayerIndex, false, true);
		else
			print(string.format("Cannot load Interactive monitor - vehicle.interactiveComponents.monitors.monitor(%d)",i));
			print("  - invalid backup and vis positions");
		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(self.xmlFile, key) then
			break;
		end;
		local defVis = getXMLBool(self.xmlFile, key .. "#defaultVis");
		local typeChange = Utils.getNoNil(getXMLString(self.xmlFile, key .. "#typeChange"), "set");
		local controlObject = getXMLString(self.xmlFile, key .. "#controlElem");
		self.LIC.interactiveObjects[j] = {};
		self.LIC.interactiveObjects[j].objectType = objectType;
		self.LIC.interactiveObjects[j].typeChange = typeChange;
		self.LIC.interactiveObjects[j].isEntered = false;
		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(self.xmlFile, key2) then
				break;
			end;
			local index = getXMLString(self.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;
		self:loadICButtonFromXML(self.xmlFile, key, self.LIC.interactiveObjects[j], j);
		j = j + 1;
		m = m + 1;
		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(self.xmlFile, key) then
			break;
		end;
		self.LIC.interactiveObjects[j] = {};
		self.LIC.interactiveObjects[j].objectType = objectType;
		self.LIC.interactiveObjects[j].isEntered = false;
		if hasXMLProperty(self.xmlFile, key..".control") then
			local mbtype = getXMLString(self.xmlFile, key..".control#type");
			local index = getXMLInt(self.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(self.xmlFile, key2) then
				break;
			end;
			local mbtype = getXMLString(self.xmlFile, key2.."#type");
			local index = getXMLInt(self.xmlFile, key2.."#index");
			local neg = Utils.getNoNil(getXMLInt(self.xmlFile, key2.."#negStatus"),false);
			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].actionElements[indexFinal] = neg;
			end;
			k = k + 1;
		end;
		self:loadICButtonFromXML(self.xmlFile, key, self.LIC.interactiveObjects[j], j);
		j = j + 1;
		self.LIC.partLen.mbutton = self.LIC.partLen.mbutton + 1;	
		i = i + 1;
	end;
	
	--====================================--
	--=== LOAD CROSS BUTTONS LISTENERS ===--
	local i=0;
	while true do
		local key = string.format("vehicle.interactiveComponents.buttonsListeners.listener(%d)", i);	
		if not hasXMLProperty(self.xmlFile, key) then
			break;
		end;
		self.LIC.objectsListeners[i] = {};
		local j = 0;
		while true do
			local key2 = string.format(key .. ".element(%d)", j);
			if not hasXMLProperty(self.xmlFile, key2) then
				break;
			end;
			local Ltype = getXMLString(self.xmlFile, key2.."#type");
			local Oindex = getXMLInt(self.xmlFile, key2.."#index");
			if Oindex <= self.LIC.partLen[Ltype] then
				local indexFinal = Oindex;
				if Ltype == "animation" then
				elseif Ltype == "button" then
					indexFinal = indexFinal + self.LIC.partLen.animation;
				elseif Ltype == "monitor" then
					indexFinal = indexFinal + self.LIC.partLen.button + self.LIC.partLen.animation;
				elseif Ltype == "visibility" then
					indexFinal = indexFinal + self.LIC.partLen.monitor + self.LIC.partLen.button + self.LIC.partLen.animation;
				elseif Ltype == "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.objectsListeners[i],indexFinal);
				if self.LIC.getElementListeners[indexFinal] == nil then
					table.insert(self.LIC.getElementListeners,indexFinal,{});
				end;
				self.LIC.getElementListeners[indexFinal][table.getn(self.LIC.getElementListeners[indexFinal])] = i;
			end;
			j = j + 1;
		end;
		i = i + 1;
	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, false);
			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)
	self.LIC.lastMouseXPos = posX;
    self.LIC.lastMouseYPos = posY;
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);
			if self.LIC.interactiveObjects[self.LIC.foundInteractiveObject].audio ~= nil then
				if self:getIsActiveForSound() then
					playSample(self.LIC.interactiveObjects[self.LIC.foundInteractiveObject].audio,1,1,0);
				end;
			end;
		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 and not self.isEntered then
		self.LIC.lastMouseXPos = InputBinding.mousePosXLast;
		self.LIC.lastMouseYPos = InputBinding.mousePosYLast;
		for _,v in pairs(self.LIC.interactiveObjects) do
			v.isEntered = false;
		end
		if self.LIC.lastMouseXPos ~= nil and self.LIC.lastMouseYPos ~= 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 self.LIC.lastMouseXPos > (x-v.size/2) and self.LIC.lastMouseXPos < (x+v.size/2) then
							if self.LIC.lastMouseYPos > (y-v.size/2) and self.LIC.lastMouseYPos < (y+v.size/2) then
								if v.canOutside then
									v.isEntered = true;
									self:renderOverlayAndInfo(v);
									self:updateOpenStatus(k);
									self.LIC.foundInteractiveObject = k;
									break;
								end;
							end;
						end;
					end;
				end;
			end;
		end;
	end;

	if self:getIsActive() then
		InputBinding.accumMouseMovementXBackUp = 0;
        InputBinding.accumMouseMovementYBackUp = 0;
	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(false, false);
				self.LIC.isInOutsideRange = false;
			end;
		end;
	end;
end;

function InteractiveControl:draw()
	if self.LIC.isMouseActive and self.isEntered then
		for _,v in pairs(self.LIC.interactiveObjects) do
			v.isEntered = false;
		end
		if self.LIC.lastMouseXPos ~= nil and self.LIC.lastMouseYPos ~= 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 self.LIC.lastMouseXPos > (x-v.size/2) and self.LIC.lastMouseXPos < (x+v.size/2) then
							if self.LIC.lastMouseYPos > (y-v.size/2) and self.LIC.lastMouseYPos < (y+v.size/2) then
								if not v.canOutside then
									v.isEntered = true;
									self:renderOverlayAndInfo(v);
									self:updateOpenStatus(k);
									self.LIC.foundInteractiveObject = k;
									break;
								end;
							end;
						end;
					end;
				end;
			end;
		end;
	end;
end;

function InteractiveControl:onEnter()
end;

function InteractiveControl:onLeave()
	self:toggleICState(false, 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.isClient then
		if self.LIC.isMouseActive == nil then
			print("Shit happens");
			self.LIC.isMouseActive = false;
			self:toggleICState(false, true);
			self:toggleICState(false, false);
		end;
		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);
				if self.cameras ~= nil then
					for _,v in pairs(self.cameras) do
						v.isActivated = false;
					end;
				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;
				if self.cameras ~= nil then
					for _,v in pairs(self.cameras) do
						v.isActivated = true;
					end;
				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;
end;

function InteractiveControl:loadICButtonFromXML(xmlFile, key, ICBtn, index)
	ICBtn.name = g_i18n:getText(Utils.getNoNil((getXMLString(xmlFile, key .. "#name")), "ERROR"));
	ICBtn.size = Utils.getNoNil((getXMLFloat(xmlFile, key .. "#size")), 0.05);
	ICBtn.mark = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#mark"));
	if ICBtn.mark ~= nil then
		setVisibility(ICBtn.mark,false);
	end;
	ICBtn.isOpen = Utils.getNoNil((getXMLBool(xmlFile, key .. "#defaultStatus")), false);
	
	ICBtn.onMessage = g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#onMessage"), "ic_button_on"));
	ICBtn.offMessage =  g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, key .. "#offMessage") , "ic_button_off"));
	
	ICBtn.canOutside =  Utils.getNoNil(getXMLBool(xmlFile, key.."#isOutside"), false);
	ICBtn.synch =  Utils.getNoNil(getXMLBool(xmlFile, key.."#synch"), true);
	
	local initAction = Utils.getNoNil((getXMLBool(xmlFile, key .. "#initAction")), true);
	local soundFile = getXMLString(xmlFile, key.."#soundFile");
	if soundFile ~= nil and index ~= nil then
		ICBtn.audio = createSample(string.format("ICSound%d",index));
		loadSample(ICBtn.audio, MDR..soundFile, false);
	end;
	if initAction and index ~= nil and self.isServer then
		self:actionOnObject(index, ICBtn.isOpen, true);
	end;
end;