--------------------------------------------------------------------------------
function DefaultOnSceneLoad(path, level_mode, parent_scene)
    game_state = {}
    game_state.custom_cursors = {}
    game_state.locked_objects = {}
    game_state.tool = nil
    game_state.tool_objects = {}
    game_state.locker = ReferenceCounter()
    game_state.state = GetGameManager():GetCurrPlayer().m_gameState
    game_state.level_mode = level_mode
    game_state.parent_scene = parent_scene
    game_state.scene_path = path
    game_state.is_inventory_opened = false
    game_state.comics = nil
    game_state.linked_scenes = {}
    game_state.ignore_on_highlight = {}
	game_state.quest_objects = {}
	
	DragObject = nil;
	
	play_field.mouseBlocker = MouseBlocker:New()

	local anim = CreateAnimation('data/Texture/GUI/Zoom/zoom_border.png',0,0,686,554,1,0)
	anim:SetHotSpot(343,277)
	anim:SetBlendMode(2)
	anim:SetColor('0x00FFFFFF')
	play_field:CreateObject('zoom_border',anim,512,368,205,0,1,1)
	play_field:GetObject('zoom_border'):SetScale(1.)
	--play_field:GetObject('zoom_border'):SetVisible(false)
	local anim = CreateAnimation('data/Texture/GUI/Zoom/zoom_close.png',0,93,81,93,1,0)
	anim:SetHotSpot(40,46)
	anim:SetBlendMode(2)
	anim:SetColor('0x01FFFFFF')
	play_field:CreateObject('zoom_button_back',anim,0,0,499,0,1,1)
	play_field:GetObject('zoom_button_back'):SetMaxOpacity(0.01)
	local anim = CreateAnimation('data/Texture/GUI/info_back.png',0,0,642,547,1,0)
	anim:SetHotSpot(321,273)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	play_field:CreateObject('zoom_info_back',anim,512,326,300,0,1,1)
	play_field:GetObject('zoom_info_back'):SetOpacity(0.)
	local anim = CreateAnimation('data/Texture/GUI/info_button.png',0,0,114,73,1,0)
	anim:SetHotSpot(57,36)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	play_field:CreateObject('zoom_info_button',anim,511,565,310,0,1,1)
	play_field:GetObject('zoom_info_button'):SetOpacity(0.)

    local anim = CreateAnimation('data/Texture/Scenes/Common/fade.png',0,0,512,384,1,0)
    anim:SetHotSpot(256,192)
    anim:SetBlendMode(2)
    anim:SetColor('0xFFFFFFFF')
    play_field:CreateObject('zoom_fade',anim,512,384,200,0,2,2)
    play_field:GetObject('zoom_fade'):SetOpacity(0.0)
    play_field:IgnoreOnTestPoint('zoom_fade')

	local anim = CreateAnimation('data/Texture/Scenes/Common/fade.png',0,0,512,384,1,0)
	anim:SetHotSpot(256,192)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	play_field:CreateObject('fade_in_on_load',anim,512,384,1000,0,2,2)
	play_field:IgnoreOnTestPoint('fade_in_on_load')
	play_field:GetObject('fade_in_on_load'):ChangeOpacity(1., 0., 0.5)

	local anim = CreateAnimation('data/Texture/Effect/Single_Particle.PNG',0,0,36,36,1,0)
	anim:SetHotSpot(18,18)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	play_field:CreateObject('object_highlight',anim,512,384,140,0,1,1)
    play_field:GetObject('object_highlight'):SetOpacity(0.)
    play_field:IgnoreOnTestPoint('object_highlight')

	local anim = CreateAnimation('data/Texture/Effect/Single_Particle.PNG',0,0,36,36,1,0)
	anim:SetHotSpot(18,18)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	play_field:CreateObject('quest_object_highlight',anim,512,384,140,0,1,1)
    play_field:GetObject('quest_object_highlight'):SetOpacity(0.)
    play_field:IgnoreOnTestPoint('quest_object_highlight')

    game_state.object_highlight_delay = 4.
    game_state.object_highlight_period = 3.

    game_state.quest_object_highlight_delay = 2.5
    game_state.quest_object_highlight_period = 3.
    game_state.quest_object_highlight_period_min = 1.3
    local quest_object_highlight_period_change_time = 60.
    local x1 = game_state.quest_object_highlight_period
    local x2 = game_state.quest_object_highlight_period_min
    local t = quest_object_highlight_period_change_time
    game_state.quest_object_highlight_period_change_speed = (x2 - x1) / t

    if level_mode == 'quest' then
        local screen_bak = GetGameManager():GetCurrentScreen()
        local inventory = play_field:GetLevelScreen():GetInventory()
        GetGameManager():SetCurrentScreen(inventory)
        LoadInventoryData(inventory)
        GetGameManager():SetCurrentScreen(screen_bak)
        play_field:GetLevelScreen():GetPanel():SetMode(PM_QUEST)
    end
    if level_mode == 'hidden_object' then
        play_field:GetLevelScreen():GetPanel():SetMode(PM_HIDDENOBJECT)
        local state_name = GetHintTimerState(path)
        local hint_timer = 0
        if GameStateExists(state_name) then
            hint_timer = tonumber(GetGameState(state_name):Get(0))
        --else
            --AddGameState(state_name, tostring(nhints))
        end
        play_field:GetLevelScreen():GetPanel():SetDelayTimer(hint_timer)
    end
    if level_mode == 'mini_game' then
        play_field:GetLevelScreen():GetPanel():SetMode(PM_MINIGAME)
    end
    if level_mode == 'clean'
    then
        play_field:GetLevelScreen():GetPanel():SetMode(PM_CLEAN)
    end

    RegisterTools()

    --[[
    if GameStateExists('ToolFound') then
        local rec = GetGameState('ToolFound')
        for i = 0, rec:GetSize() - 1 do
            local val = rec:Get(i)
            if not HasGameState('ToolApplied', val) then
                AddTool(val)
            end
        end
    end
    ]]

	if HasGameState('IgnoreOnHighlight') then
		local st = GetGameState('IgnoreOnHighlight')
		for i = 0, st:GetSize() - 1 do
			game_state.ignore_on_highlight[st:Get(i)] = true
		end
	end

    PanelOnSceneStart()

    if not HasGameState('SceneVisited', path) then
        AddGameState('SceneVisited', path)
    end
    if level_mode ~= 'mini_game' then
        if not HasGameState('LastVisitedScene') then
            AddGameState('LastVisitedScene', path)
        else
            SetGameState('LastVisitedScene', path)
        end
    end

    if (level_mode ~= 'none')
    then
        PlayRandomAmbientMusic();
    end
    
    if (PendingIngameMenu)
    then
        ingameMenuBlocker = 0;
        StartIngameMenu()
    end
end

function GetHintTimerState(path)
    return "HintTimer"
    --return "HintTimer("..path..")"
end

function HighlightObject(obj_name, effect_time, is_quest_object)
	if game_state.highlighting_disabled then
		return
	end

	local obj
	if is_quest_object then
		obj = play_field:GetObject('quest_object_highlight')
	else
		obj = play_field:GetObject('object_highlight')
	end

	local target = play_field:GetObject(obj_name)

	obj:Show()
	obj:SetXY(target:GetX(), target:GetY())
	--obj:SetZ(target:GetZ() + 50.) -- magic const
	obj:SetLayer(target:GetLayer() + 1)
	--obj:AttachTo()

	--Log(target:GetName())

	local scale_coeff = 1.

	if not effect_time then
		effect_time = 1.3
	end

	local af = CreateAnimationEffector()
	af:AttachTo(obj)
	af:SetMode(_ANIM_NOLOOP)
	af:SetKey(_TRACK_O, effect_time * 0.,   0.)
	af:SetKey(_TRACK_A, effect_time * 0.,   0.)
	af:SetKey(_TRACK_S, effect_time * 0.,   0.3)
	af:SetKey(_TRACK_O, effect_time * 0.05, 1.)
	af:SetKey(_TRACK_S, effect_time * 0.25, 1.)
	af:SetKey(_TRACK_O, effect_time * 0.45, 1.)
	af:SetKey(_TRACK_A, effect_time * 0.45, 35. * M_PI / 180.)
	af:SetKey(_TRACK_S, effect_time * 0.45, 1.4)
	af:SetKey(_TRACK_O, effect_time * 0.70, 1.)
	af:SetKey(_TRACK_A, effect_time * 1.,   50. * M_PI / 180.)
	af:SetKey(_TRACK_S, effect_time * 1.,   1.)
	af:SetKey(_TRACK_O, effect_time * 1.,   0.)
	af:Play()
end

function IsValidHighlightCandidate(obj_name)
	return play_field:HasObject(obj_name) and
		   play_field:GetObject(obj_name):IsVisible() and
		   play_field:GetObject(obj_name):GetOpacity() > 0. and
		   game_state.ignore_on_highlight[obj_name] ~= true and
		   ((game_state.active_zone and game_state.active_zone.HasObject(obj_name)) or
			(not game_state.active_zone)) and
		   (not game_state.linked_scenes[obj_name] or not game_state.linked_scenes[obj_name].mark_with_ps)
end

function HighlightRandomObject()
	game_state.object_highlight_delay = game_state.object_highlight_period

	local candidates = {}

	if game_state.level_mode ~= "hidden_object" then
		for i, v in pairs(game_state.tools) do
			if v.trigger_name then
				table.insert(candidates, v.trigger_name)
			end
		end
	end

	for i, v in pairs(game_state.custom_cursors) do
		if v ~= nil and v ~= '' then
			table.insert(candidates, i)
		end
	end

	local candidates_copy = candidates
	candidates = {}
	for i, v in ipairs(candidates_copy) do
		if IsValidHighlightCandidate(v) and
		   game_state.quest_objects[v] ~= true
		then
			table.insert(candidates, v)
		end
	end
	candidates_copy = nil

	if table.getn(candidates) > 0 then
		local target_index = math.random(1, table.getn(candidates))
		local effect_time = 1.3
		if effect_time > game_state.object_highlight_period then
		    effect_time = game_state.object_highlight_period
		end
		HighlightObject(candidates[target_index], effect_time)
	end
end

function HighlightRandomQuestObject()
	game_state.quest_object_highlight_delay = game_state.quest_object_highlight_period

	local candidates = {}
	for i, v in pairs(game_state.quest_objects) do
		if v == true and IsValidHighlightCandidate(i) then
			table.insert(candidates, i)
		end
	end

	if table.getn(candidates) > 0 then
		local target_index = math.random(1, table.getn(candidates))
		local effect_time = 1.3
		if effect_time > game_state.quest_object_highlight_period then
		    effect_time = game_state.quest_object_highlight_period
		end
		HighlightObject(candidates[target_index], effect_time, true)
	end
end

function DefaultOnSceneFree()
end

function DefaultOnSceneDestroy(screen)
    --[[
    if screen:GetLevelScreen():GetPanel():GetMode() == PM_HIDDENOBJECT then
        local state_name = GetHintTimerState(screen:GetName())
        local hint_timer = screen:GetLevelScreen():GetPanel():GetHintTimer()
        SetGameState(state_name, tostring(hint_timer))
    end
    ]]
end

function IsZoomZoneNeedsScreenBottomExitZone(zone)
    return zone.biggest_object:GetAnimation():GetWidth() > 1000.
end

function DefaultOnUpdate(dt)
    play_field:UpdateObjectUnderMouse()
    local return_zone_check_needed =
        (game_state.active_zone and
         IsZoomZoneNeedsScreenBottomExitZone(game_state.active_zone)) or
        game_state.level_mode == 'hidden_object' or
        game_state.level_mode == 'mini_game'
    if return_zone_check_needed and IsAboveReturnFromZoomZone() then
        if currentCursor ~= 'CursorDoorDown' then
            game_state.cursor_to_restore = currentCursor
        end
        SetCursor('CursorDoorDown')
    else
        if game_state.cursor_to_restore then
            SetCursor(game_state.cursor_to_restore)
            game_state.cursor_to_restore = nil
        end
    end

	if not game_state.comics or game_state.comics.is_monolog then
		if game_state.quest_object_highlight_period > game_state.quest_object_highlight_period_min then
			local dperiod = game_state.quest_object_highlight_period_change_speed * dt
			if game_state.quest_object_highlight_period + dperiod >= game_state.quest_object_highlight_period_min then
				game_state.quest_object_highlight_period = game_state.quest_object_highlight_period + dperiod
			else
				game_state.quest_object_highlight_period = game_state.quest_object_highlight_period_min
			end
		end
		
		if game_state.forcedObject
		then
		    game_state.object_highlight_delay = game_state.object_highlight_delay - dt
		    if game_state.object_highlight_delay < 0. then
		        HighlightObject(game_state.forcedObject)
		        game_state.object_highlight_delay = game_state.object_highlight_period
            end
        else
            game_state.object_highlight_delay = game_state.object_highlight_delay - dt
            if game_state.object_highlight_delay < 0. then
                HighlightRandomObject()
            end

            game_state.quest_object_highlight_delay = game_state.quest_object_highlight_delay - dt
            if game_state.quest_object_highlight_delay < 0. then
                --play_field:GetObject('quest_object_highlight'):GetAnimation():SetColor('0xFF2222FF') -- temporary for testing purposes
                HighlightRandomQuestObject()
            end
		end
	end
end

function OnLastItemFound()
    if not HasGameState("AllSceneTaskObjectsFound", game_state.scene_path) then
        AddGameState("AllSceneTaskObjectsFound", game_state.scene_path)
    end

    if game_state.tools then
        for tool_name, tool_info in pairs(game_state.tools) do
            if tool_info.trigger_name == nil and
               tool_info.find_scene == game_state.scene_path
            then
                if game_state.level_mode == 'quest' then
                    AddTool(tool_name)
                end
                if tool_info.on_find ~= nil then
                    tool_info.on_find(tool_name)
                end
                if not HasGameState('ToolFound', tool_name) then
                    AddGameState('ToolFound', tool_name)
                end
            end
        end
    end

    if game_state.level_mode == 'hidden_object' then
        AddGameState('ClosedScene', game_state.scene_path)
    end

    SetGameState('LastVisitedScene', game_state.parent_scene)
end

function DefaultOnAllItemsFound()
    play_field:GetLevelScreen():GetPanel():ButtonPress('Close')
end

function DefaultOnLose()
end

function DefaultOnExit()
end

function DefaultOnClose()
    if game_state.parent_scene then
        StartLevel(game_state.parent_scene)
    end
end

function DefaultOnObjectMouseEnter(object)
    if game_state.tool then
        SetCursor('CursorTool', true)
    else
        local objectName = object:GetName();
        if game_state.custom_cursors[objectName] ~= nil and
           game_state.custom_cursors[objectName] ~= '' and
           --not game_state.comics-- and
           (not game_state.active_zone or game_state.active_zone.HasObject(objectName))
           and (not play_field.mouseDownBlocked or game_state.forcedObject == objectName)
           --(play_field:GetLevelScreen():IsTaskObject(object:GetName()) or
           --game_state.custom_cursors[object:GetName()] ~= 'CursorPhoto')
        then
            name = game_state.custom_cursors[objectName]
            if (game_state.forcedObject)
            then
                SetCursor(name, true);
            else
                SetCursor(name)
            end
        end
    end
end

function DefaultOnObjectMouseLeave(object)
    SetCursor('CursorDefault', true)
end

function DefaultOnObjectMouseDown(object)

    local object_found = false
    local obj_name = object:GetName()
    
    if (play_field.mouseDownBlocked and (game_state.forcedObject == nil or game_state.forcedObject ~= obj_name))
    then
        return true;
    end

    UpdateComicsRequest()

    local has_tool = play_field:GetTool() ~= ''

    -- tool finding
    local success = false
    local trigger_name
    if game_state.locked_objects[obj_name] ~= true and
       game_state.tools and
       not has_tool
    then
        for tool_name, tool_info in pairs(game_state.tools) do
            if tool_info.find_scene == game_state.scene_path then
                trigger_name = tool_info.trigger_name
                local action_triggered = obj_name == tool_info.trigger_name
                if not action_triggered and type(tool_info.trigger_name) == 'table' then
                    for i, v in ipairs(tool_info.trigger_name) do
                        if obj_name == v then
                            table.remove(tool_info.trigger_name, i)
                            if table.getn(tool_info.trigger_name) == 0 then
                                trigger_name = v
                                action_triggered = true
                            end
                        end
                    end
                end
                if action_triggered and not success then
                    local objects_zone = nil
                    if game_state.zones ~= nil then
                        for i, zone in pairs(game_state.zones) do
                            if zone.HasObject(trigger_name) then
                                objects_zone = zone
                            end
                        end
                    end

                    if (game_state.locker:GetNReferences() == 0 and objects_zone == nil) or
                       (objects_zone ~= nil and objects_zone.IsVisible())
                    then
                        success = true

                        if objects_zone ~= nil then
                            objects_zone.SetObjectVisible(trigger_name, false)
                            objects_zone.SetVisible(false)
                            --game_state.custom_cursors[objects_zone.trigger_name] = ''
                            --game_state.locked_objects[objects_zone.trigger_name] = true
                        else
                            object:ChangeOpacity(1., 0., 0.1)
                        end

                        FindTool(tool_name)

                        object_found = true
                    end
                end
            end
        end
    end

    -- active objects
    local state_value = game_state.scene_path..'('..obj_name..')'
    if game_state.active_objects and
       game_state.active_objects[obj_name] and
       game_state.locked_objects[obj_name] ~= true and
       not has_tool and
       (not HasGameState('ObjectClicked', state_value) or game_state.active_objects[obj_name].multi_use == true) and
       (game_state.locker:GetNReferences() == 0 or (game_state.active_zone and game_state.active_zone.HasObject(obj_name)))
    then
        if not HasGameState('ObjectClicked', state_value) then
            AddGameState('ObjectClicked', state_value)
        end
        
        local callback = game_state.active_objects[obj_name].on_click;
        
        if HasGameState('ObjectClicked', state_value) and
           not game_state.active_objects[obj_name].multi_use == true
        then
            game_state.locked_objects[obj_name] = true
            game_state.custom_cursors[obj_name] = ''
            game_state.active_objects[obj_name] = nil
        end

        callback(obj_name);
        object_found = true
        
    end

    if not object_found and
	   game_state.locked_objects[obj_name] ~= true and
       play_field:GetLevelScreen():IsTaskObject(obj_name) and
       game_state.locker:GetNReferences() == 0 and
       not has_tool
    then
        local is_in_zone =
            game_state.active_zone ~= nil and game_state.active_zone.HasObject(obj_name)
        if (is_in_zone and game_state.locker:GetNReferences() == 1) or
           (not is_in_zone and game_state.locker:GetNReferences() == 0)
        then
            play_field:OnObjectFound(object)
            play_field:IgnoreOnTestPoint(obj_name)
            local state_value = game_state.scene_path.."("..object:GetName()..")"
            assert(not HasGameState("TaskObjectFound", state_value))
            AddGameState("TaskObjectFound", state_value)
            object_found = true
        end

        if game_state.tool_objects[object:GetName()] then
            -- save xml data
        end
    end

    -- linked scenes
    local linked_scene_info = game_state.linked_scenes[obj_name]
    if not object_found and game_state.locked_objects[obj_name] ~= true and
       linked_scene_info and
       (game_state.locker:GetNReferences() == 0 or (game_state.active_zone and game_state.active_zone.HasObject(obj_name))) and
       not has_tool
    then
        local is_closed = HasGameState('ClosedScene', linked_scene_info.path)
        if linked_scene_info.condition then
            if linked_scene_info.condition() and not is_closed then
                StartLevel(linked_scene_info.path)
            else
                if linked_scene_info.on_condition_fail then 
                    linked_scene_info.on_condition_fail()
                end
            end
        else
            if not is_closed then
				object_found = true
                StartLevel(linked_scene_info.path)
            end
        end
    end

    local zone_opened = false
    if not object_found and (game_state.locker:GetNReferences() == 0 or (game_state.active_zone and game_state.active_zone.HasObject(obj_name))) and
       game_state.locked_objects[obj_name] ~= true and
       game_state.zones ~= nil and
       not has_tool
    then
        for i, zone in pairs(game_state.zones) do
            if zone.trigger_name == obj_name then
                zone.SetVisible(true)
                zone_opened = true
				object_found = true
            end
        end
    end

    local inventory = play_field:GetLevelScreen():GetInventory()
    if inventory:IsToolsVisible() then
        OnInventoryButtonPress()
    end

    -- test for return zone of opened zoom zone click
    if game_state.active_zone and
       not zone_opened and
       IsZoomZoneNeedsScreenBottomExitZone(game_state.active_zone) and
       IsAboveReturnFromZoomZone()
    then
        game_state.active_zone.SetVisible(false)
        SetCursor('CursorDefault')
		object_found = true
    end

    if game_state.level_mode == 'mini_game' and
       IsAboveReturnFromZoomZone()
    then
        SetCursor('CursorDefault')
        play_field:GetLevelScreen():GetPanel():ButtonPress('Close')
		object_found = true
    end
    
    if object_found and game_state.forcedObject and tutorScreen
    then
        tutorScreen:Hide();
    end

    return object_found
end

function DefaultOnObjectMouseDownProcessed(is_wrong_click)

    if is_wrong_click and game_state.level_mode == 'hidden_object' then
        play_field:ShowWrongObjectEffect();
        PlaySound("Wrong_click");
        
        if (play_field.wrongClicksCount)
        then
            local curTime = APP:GetCurrentTime();
            if (curTime - play_field.lastClickTime <=
                    CLICK_TIME_TO_PUNISH / CLICKS_COUNT_TO_PUNISH)
            then
                play_field.wrongClicksCount = play_field.wrongClicksCount + 1;
                if (play_field.wrongClicksCount >= CLICKS_COUNT_TO_PUNISH)
                then
                    PunishClicking();
                    play_field.wrongClicksCount = 0;
                end
            else
                play_field.wrongClicksCount = 1;
            end
        else
            play_field.wrongClicksCount = 1;
        end
        
    end
    
    play_field.lastClickTime = APP:GetCurrentTime();

end

function DefaultOnObjectMouseUp(object)
    if game_state.linked_scenes then
        for i, v in pairs(game_state.linked_scenes) do
            local is_closed = HasGameState('ClosedScene', v.path)
            local mark_zone = not is_closed --[[and (not v.condition or v.condition())]]
            if mark_zone then
                MarkLinkZone(i, true)
            else
                MarkLinkZone(i, false)
            end
        end
    end
end

function DefaultOnObjectFound(object)

    if (play_field.itemFoundSound)
    then
        play_field.itemFoundSound:StopSound();
        play_field.itemFoundSound:Play(false);
    else
        play_field.itemFoundSound = MakeSoundEntity("Item_found");
        play_field.itemFoundSound:Play(false);
    end
    
end

function DefaultOnToolFound(tool)

end

function DefaultOnToolApply(tool_name, object)
    --game_state.tool = nil
    local tool_applied = false
	local obj_name = object:GetName()
	
	if (play_field.mouseDownBlocked and (game_state.forcedObject == nil or game_state.forcedObject ~= obj_name))
    then
        return true;
    end

    if object and game_state.tools ~= nil then
        for name, info in pairs(game_state.tools) do
            local is_target = false
            local target_table_index

            if info and info.target_name then
                if type(info.target_name) == 'string' then
                    is_target = info.target_name == object:GetName()
                else
                    for i, v in pairs(info.target_name) do
                        is_target = v == object:GetName()
                        target_table_index = i
                        if is_target then
                            break
                        end
                    end
                end
            end

            if not tool_applied and
               tool_name == name and
               is_target
            then
                game_state.custom_cursors[object:GetName()] = ''
                if info.on_apply and type(info.target_name) ~= 'string' then
                    info.on_apply(tool_name, object:GetName())
                end
                if type(info.target_name) == 'table' then
                    assert(not HasGameState('ToolTargetUsed', object:GetName()))
                    AddGameState('ToolTargetUsed', object:GetName())
                    table.remove(info.target_name, target_table_index)
                end
                if type(info.target_name) == 'string' or table.getn(info.target_name) == 0 then
                    if info.on_apply then
                        info.on_apply(tool_name)
                    end
                    play_field:SetTool('')
                    game_state.tool = nil
                    local inv = play_field:GetLevelScreen():GetInventory()
                    inv:GetToolInfo(tool_name).m_tool:ChangeOpacity(1., 0., 0.2)
                    inv:RemoveTool(tool_name)
                    assert(not HasGameState('ToolApplied', tool_name))
                    AddGameState('ToolApplied', tool_name)
                    OnInventoryButtonPress()
                end
                tool_applied = true
            end
        end
    end

    if not tool_applied then
		local zoom_opened = false
		if game_state.locker:GetNReferences() == 0 or (game_state.active_zone and game_state.active_zone.HasObject(obj_name)) and
		   game_state.locked_objects[obj_name] ~= true and
		   game_state.zones ~= nil
		then
		    if game_state.zones then
                for i, zone in pairs(game_state.zones) do
                    if zone.trigger_name == obj_name and
					   not zone.IsDisabled()
					then
                        zone.SetVisible(true)
                        zoom_opened = true
                        break
                    end
                end
			end
		end
		if not zoom_opened then
            local is_target_for_some_tool = false
            for i, v in pairs(game_state.tools) do
                if v.target_name and not HasGameState('ToolApplied', v.name) then
                    if type(v.target_name) == 'string' then
                        if v.target_name == obj_name then
                            is_target_for_some_tool = true
                            break
                        end
                    else
                        for i, v in pairs(v.target_name) do
                            if v == obj_name then
                                is_target_for_some_tool = true
                                break
                            end
                        end
                    end
                end
                if is_target_for_some_tool then
                    break
                end
            end

			if object and is_target_for_some_tool then
				ShowMonolog('ToolDenyMonolog', 'C_TOOL_DENY_'..tostring(math.random(1, 2)))
			end

			DropTool()
		end
    end
    
    if tool_applied and game_state.forcedObject and tutorScreen
    then
        tutorScreen:Hide();
    end
    
end

function DefaultOnObjectReachPanel(object)
end

function DefaultOnButtonPress(title)

    if (play_field.mouseDownBlocked and (game_state.forcedObject == nil or game_state.forcedObject ~= title))
    then
        return;
    end
    
    if game_state.zones ~= nil then
        for i, zone in pairs(game_state.zones) do
            if zone.close_button_message == title then
                zone.SetVisible(false)
                PlaySound('Menu_button_click');
            end
        end
    end
end

function DefaultOnMouseMove(previous_pos, current_pos)
end

function DefaultOnSetTool(tool)
end

function DefaultOnMiniGameWin()
    --assert(game_state.mini_game ~= nil)
    if game_state.mini_game ~= nil then
        dofile(game_state.level_path)
        --ReleaseFocus(game_state.mini_game)
        game_state.mini_game:Destroy()
        game_state.mini_game = nil
        play_field:GetLevelScreen():Go()
        play_field:GetLevelScreen():ScreenShow()
        --SetFocusTo(play_field:GetLevelScreen())
    end
end

function DefaultOnIntroFinish()
    if game_state.intro ~= nil then
        --local timer = play_field:GetLevelScreen():GetTimer()
        dofile(game_state.level_path)
        --game_state.intro:SetOpacity(0.7)
        GTimerDoString('game_state.intro:ScreenDestroy()', 0.5)
    end
end

--[[ ***
function DefaultOnPhotographing(phone_screen_center_pos)
    local pf = play_field
    local success = false

    if game_state.photo_objects ~= nil then
        for i, photo_info in ipairs(game_state.photo_objects) do
            if pf:HasObject(photo_info.obj_name) and
               pf:GetLevelScreen():IsTaskObject(photo_info.obj_name) and
               custom_cursors[photo_info.obj_name] == 'CursorPhoto' and
               not success
            then
                local obj = pf:GetObject(photo_info.obj_name)
                local dist = Vector(phone_screen_center_pos.x - obj:GetX(),
                                    phone_screen_center_pos.y - obj:GetY())
                if dist:Length() < 150. then
                    local objects_zone = nil
                    if game_state.zones ~= nil then
                        for i, info in pairs(game_state.zones) do
                            if info.zone.HasObject(photo_info.obj_name) then
                                objects_zone = info
                            end
                        end
                    end

                    if objects_zone == nil or objects_zone.zone.IsVisible() then
                        success = true

                        if objects_zone ~= nil then
                            objects_zone.zone.RemoveObject(photo_info.obj_name)
                            objects_zone.zone.SetVisible(false)
                            game_state.locker:Release()
                            custom_cursors[objects_zone.trigger_name] = ''
                            locked_objects[objects_zone.trigger_name] = true
                        end

                        if photo_info.photo_action ~= nil then
                            photo_info.photo_action()
                        end

                        RemoveFromTask(photo_info.obj_name)
                        pf:OnToolFound(obj, pf:GetObject(photo_info.photo_name))
                    end
                end
            end
        end
    end
end
]]