function OnSceneLoad(screen)
    LoadData(screen)
    DefaultOnSceneLoad('data/Scenes/27_Pendulum_MG.lua', 'quest', 'data/Scenes/27_Master_Hall_Main.lua')
	LinkScene('area', 'CursorDoorDown', 'data/Scenes/27_Master_Hall_Main.lua', false)

    game_state.maxAmplitude = 30 * math.pi/180;
    game_state.time         = 3;
    game_state.spd          = math.pi*2 / game_state.time;
    game_state.fadeSpd      = 10 * math.pi/180
    
    game_state.amplitude = 0;
    game_state.curTime   = 0;
    game_state.capsArray = {};
    
    game_state.stage = 'wait';
    game_state.pendulumWork = false;
    
    game_state.screen = screen;
    key_frame = 0;
    
    play_field:GetObject('area_3'):SetVisible(false);
    
    play_field:GetObject('Key_anim'):SetVisible(false);
    play_field:GetObject('Key_anim'):GetAnimation():Stop();
    play_field:GetObject('Key_anim'):GetAnimation():SetMode(HGEANIM_FWD + HGEANIM_NOLOOP);
    
	game_state.pendulumWork = false;
	
    play_field:GetObject('cap1'):GetAnimation():Stop();
    play_field:GetObject('cap2'):GetAnimation():Stop();
    play_field:GetObject('cap3'):GetAnimation():Stop();
    play_field:GetObject('cap4'):GetAnimation():Stop();
    play_field:GetObject('Glow'):SetVisible(false);
    
	play_field:GetObject('str_1'):SetVisible(false);
	play_field:GetObject('str_2'):SetVisible(false);
	play_field:GetObject('str_3'):SetVisible(false);
	play_field:GetObject('str_4'):SetVisible(false);
        
    CreateCap('cap1',  22.5, 5);
    CreateCap('cap2',   7.5, 5);
    CreateCap('cap3',    -8, 5);
    CreateCap('cap4', -22.7, 5);
    
    game_state.sel = CreateSelector();
    game_state.sel.SetStack('cap1', 'cap2', 'cap3', 'cap4')
    game_state.sel.ShiftStack();
    
    LoadSound('CoinRotate', 'data/Sound/27_Master_Hall/Coin_rotate.ogg');
    LoadSound('27_Pendulum_open', 'data/Sound/27_Master_Hall/Pendulum_open.ogg');
    
    play_field:GetObject('Key_anim'):GetAnimation():SetFrame(key_frame);
    
    --[[current_step = 0;
	local on_click = function()
		local lenght = GetAnimationLength(play_field:GetObject('Key_anim'):GetAnimation())
		TimerDoString('StartPendulum()', lenght, screen:GetTimer())
		play_field:GetObject('Key_anim'):GetAnimation():Play();
		current_step = current_step + 1;
		play_field:GetObject('Key_anim'):GetAnimation():SetFrame(current_step);
	end
	local on_load_when_clicked = function()
		if HasGameState('MiniGameCompleted', '27_Pendulum') == false then
			StartPendulum();
		end
		play_field:GetObject('Key_anim'):GetAnimation():SetFrame(3);
	end]]
	
	--RegisterActiveObject('area_3', PressKey, nil, true, 'CursorActive');
		
	RegisterActiveObject('area_hint',
        ShowPendulumComment, nil, true, 'CursorGlass');
	
	local on_key_apply = function(tool_name, object_name)
		play_field:GetObject('area_3'):SetVisible(true);
		play_field:GetObject('area_2'):SetVisible(false);
		RegisterActiveObject('area_3', PressKey, nil, true, 'CursorActive');
		--RegisterActiveObject('area_3', on_click, on_load_when_clicked)
		play_field:GetObject('Key_anim'):SetVisible(true);
		play_field:GetObject('Key_anim'):ChangeOpacity(0.0, 1.0, 0.2);
		game_state.level_type = 'mini_game';
		play_field:GetLevelScreen():GetPanel():SetMode(PM_MINIGAME);
		UnregisterActiveObject('area_2');
		UnregisterActiveObject('area_hint');
		play_field:IgnoreOnTestPoint('area_hint');
    end
    local on_load_when_key_applied = function(tool_name)
		play_field:GetObject('area_3'):SetVisible(true);
		RegisterActiveObject('area_3', PressKey, nil, true, 'CursorActive');
		--RegisterActiveObject('area_3', on_click, on_load_when_clicked)
		game_state.level_type = 'mini_game';
		play_field:GetLevelScreen():GetPanel():SetMode(PM_MINIGAME);
		UnregisterActiveObject('area_2')
		play_field:GetObject('area_2'):SetVisible(false);
		play_field:GetObject('Key_anim'):SetVisible(true);
		UnregisterActiveObject('area_hint');
		play_field:IgnoreOnTestPoint('area_hint');
    end
    
    RegisterMonologObject('area_2', 'C_27_PENDULUM_KEY_HOLE');
    
    RegisterToolApplyInfo('28_small_key', 'area_2', nil, nil, on_key_apply, on_load_when_key_applied);
    
    ShowPendulumComment();
    
    if HasGameState('MiniGameCompleted', '27_Pendulum') == true then
		play_field:GetObject('cap1'):GetAnimation():SetFrame(4);
		play_field:GetObject('cap2'):GetAnimation():SetFrame(4);
		play_field:GetObject('cap3'):GetAnimation():SetFrame(4);
		play_field:GetObject('cap4'):GetAnimation():SetFrame(4);
		game_state.screen:GetObject('DialPlate'):SetXY(game_state.screen:GetObject('DialPlate'):GetX() - 90, game_state.screen:GetObject('DialPlate'):GetY());
		game_state.screen:GetObject('DialPlate'):SetAngle(M_PI / 2);
		game_state.screen:GetObject("area_3"):SetVisible(false);
		UnregisterActiveObject('area_3');
		RegisterToolFure();
	else
		for i = 1,3 do
			if HasGameState('Pendulum_Key', ''..i) == true then
				key_frame = i;
				play_field:GetObject('Key_anim'):GetAnimation():SetFrame(key_frame);
				if(i == 3) then
					game_state.screen:GetObject("area_3"):SetVisible(false);
					StartPendulum();
					UnregisterActiveObject('area_3');
				end
			end
		end
	end
	
	LoadSound('27_Key_rotate', 'data/Sound/27_Master_Hall/Key_rotate.ogg');
end

function PressKey()
	key_frame = key_frame + 1;
	if(key_frame < 3) then
		play_field:GetObject('Key_anim'):GetAnimation():Play();
		MakeSoundEntity('27_Key_rotate'):Play(false);
	else
		play_field:GetObject('Key_anim'):GetAnimation():Play();
		game_state.screen:GetObject("area_3"):SetVisible(false);
		MakeSoundEntity('27_Key_rotate'):Play(false);
		StartPendulum();
	end
	
	 if HasGameState('Pendulum_Key', ''..(key_frame - 1)) == true then
		RemoveGameState('Pendulum_Key', ''..(key_frame - 1))
	 end
	 AddGameState('Pendulum_Key', ''..key_frame)
end

function ShowPendulumComment()

    if (not HasGameState('ToolFound', '28_small_key'))
    then
        ShowMonolog('C_27_PENDULUM_NO_KEY', 'C_27_PENDULUM_NO_KEY');
    elseif (not HasGameState('ToolApplied', '28_small_key'))
    then
        ShowMonolog('C_27_PENDULUM_APPLY_KEY', 'C_27_PENDULUM_APPLY_KEY');
    end

end

function OnSceneFree(screen)
    DefaultOnSceneFree()
    FreeData(screen)
end

--------------------------------------------------------
-- my functions
--------------------------------------------------------

function StartPendulum()
    game_state.curTime = 0;
    game_state.pendulumWork = true;
    game_state.stage = 'accel';
end
--------------------------------------------------------
function SkipMiniGame()
    game_state.sel.Reset();
    
    for i, v in pairs(game_state.capsArray) do
        if v.opened == false then
            v.Open();
        end
    end
    
	UnregisterActiveObject('area_2')
	UnregisterActiveObject('area_3')
	
	if game_state.pendulumWork then
	    game_state.stage = 'fade'
	else
        game_state.stage = 'competed'
        OnComplete()
	end
	
    --[[
    if game_state.stage == 'accel' or game_state.stage ~= 'work' then
        game_state.stage = 'fade';
    elseif game_state.stage == 'wait' then
        game_state.stage = 'competed';
        OnComplete();
    end
    ]]
end
--------------------------------------------------------
function OnComplete()
    if HasGameState('MiniGameCompleted', '27_Pendulum') == false then
		AddGameState('MiniGameCompleted', '27_Pendulum');
	end
	
	game_state.screen:GetObject('DialPlate'):Move(-90, 0, 0.4);
	game_state.screen:GetObject('DialPlate'):Rotate(M_PI / 2, 0.4);
	RegisterToolFure();
	
	MakeSoundEntity('27_Pendulum_open'):Play(false);
end
--------------------------------------------------------
function RegisterToolFure()
	--[[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)
	
	on_find = function()
	end
	
	on_load_when_tool_found = function()
	end
	
	RegisterToolFindInfo('27_Fuse', 'Layer_Fuse_BG', on_find, on_load_when_tool_found)
end

--------------------------------------------------------
function CreateCap(objName, angle, range)
    local clip = {};
    
    clip.obj    = play_field:GetObject(objName);
    clip.angle  =  angle * math.pi/180;
    clip.radius = (range * math.pi/180) / 2;
    clip.opened = false;
    
    clip.isContain = function(angle)
        return (math.abs(clip.angle - angle) <= clip.radius);
    end
    
    clip.Open = function()
        clip.obj:GetAnimation():SetMode(HGEANIM_FWD + HGEANIM_NOLOOP);
        clip.obj:GetAnimation():Play();
        clip.opened = true;
    end
    
    game_state.capsArray[objName] = clip;
    return clip;
end
--------------------------------------------------------
function GetCap(objName)
    return game_state.capsArray[objName];
end
--------------------------------------------------------
function CreateSelector()
    local sel = {};
    
    sel.obj = play_field:GetObject('Glow');
    sel.selectObj = nil;
    
    sel.stack      = {};
    sel.stackCount = 0;
    sel.stackIndex = 0;
    
    sel.showEffect = CreateAnimationEffector();
    sel.showEffect:AttachTo(sel.obj);
    sel.showEffect:SetKey(_TRACK_O, 0, 0);
    sel.showEffect:SetKey(_TRACK_O, 1, 1);
    
    sel.SelectObject = function(objName)
        sel.selectObj = objName;
        
        sel.obj:SetX( play_field:GetObject(objName):GetX() );
        sel.obj:SetY( play_field:GetObject(objName):GetY() );
        sel.showEffect:Play();
        sel.obj:SetVisible(true);
    end
    
    sel.Reset = function()
        sel.showEffect:Stop();
        sel.selectObj = nil;
        sel.obj:SetVisible(false);
    end
    
    sel.IsSelectObject = function(objName)
        return (sel.selectObj == objName);
    end
    
    sel.SetStack = function(...)
        local args = {...}
        
        for i = 1, table.getn(args) do
            sel.stackCount = sel.stackCount + 1;
            sel.stack[sel.stackCount] = args[i];
        end
    end
    
    sel.ShiftStack = function()
        for i=1, sel.stackCount do
            local stackIndex = math.random(1, sel.stackCount);
            sel.stack[i], sel.stack[stackIndex] = sel.stack[stackIndex], sel.stack[i];
        end
    end
    
    sel.SelectNext = function()
        if sel.stackIndex == sel.stackCount then
            return false;
        else
            sel.stackIndex = sel.stackIndex + 1;
            play_field:GetObject('str_'..string.sub(sel.stack[sel.stackIndex], 4)):SetVisible(true);
            sel.SelectObject( sel.stack[sel.stackIndex] );
            return true;
        end
    end
    
    return sel;
end
--------------------------------------------------------
function OnUpdate(dt)
    if game_state.pendulumWork == true then
        game_state.curTime = game_state.curTime + dt;
        
        if game_state.stage == 'accel' then
            game_state.amplitude = game_state.amplitude + game_state.fadeSpd * dt;
            
            if game_state.amplitude > game_state.maxAmplitude then
                ShowMonolog('C_27_PENDULUM_STARTED', 'C_27_PENDULUM_STARTED');
                game_state.amplitude = game_state.maxAmplitude;
                game_state.stage = 'work';
                game_state.sel.SelectNext();
            end
        elseif game_state.stage == 'fade' then
            game_state.amplitude = game_state.amplitude - game_state.fadeSpd * dt;
            
            if game_state.amplitude < 0 then
                game_state.amplitude = 0;
                game_state.stage = 'competed';
                game_state.pendulumWork = false;
            end
        end
        
        local angle = math.sin(game_state.curTime * game_state.spd) * game_state.amplitude;
        play_field:GetObject('Pendulum'):SetAngle( angle );
        
        if game_state.stage == 'competed' then
            OnComplete();
        end
    end
    
    DefaultOnUpdate(dt)
end

function OnAllItemsFound()
    DefaultOnAllItemsFound()
end

function OnLose()
    DefaultOnLose()
end

function OnExit()
    DefaultOnExit()
end

function OnClose()
    DefaultOnClose()
end

function OnObjectMouseEnter(object)
    DefaultOnObjectMouseEnter(object)
end

function OnObjectMouseLeave(object)
    DefaultOnObjectMouseLeave(object)
end

function OnObjectMouseDown(object)
    local is_wrong_click = not DefaultOnObjectMouseDown(object)
    local obj_name = object:GetName()
    local pf = play_field;
    
    if game_state.pendulumWork == true and game_state.stage == 'work' then
        local clip = GetCap(obj_name);
        
        if clip ~= nil and game_state.sel.IsSelectObject( clip.obj:GetName() ) == true then
            if clip.isContain(play_field:GetObject('Pendulum'):GetAngle()) == true then
                play_field:GetObject('str_1'):SetVisible(false);
				play_field:GetObject('str_2'):SetVisible(false);
				play_field:GetObject('str_3'):SetVisible(false);
				play_field:GetObject('str_4'):SetVisible(false);
	
				clip.Open();
                
                PlaySound('CoinRotate');
                
                if game_state.sel.SelectNext() == false then
					if HasGameState('MiniGameCompleted', '27_Pendulum') == false then
						AddGameState('MiniGameCompleted', '27_Pendulum');
					end
                    game_state.sel.Reset();
                    game_state.stage = 'fade';
                end
            end
        end
    end
    
    DefaultOnObjectMouseDownProcessed(is_wrong_click);
end

function OnObjectMouseUp(object)
    DefaultOnObjectMouseUp(object)
end

function OnObjectFound(object)
    DefaultOnObjectFound(object)
end

function OnToolFound(tool)
    DefaultOnToolFound(tool)
end

function OnToolApply(tool, object)
    DefaultOnToolApply(tool, object)
end

function OnObjectReachPanel(object)
    DefaultOnObjectReachPanel(object)
end

function OnButtonPress(title)
    DefaultOnButtonPress(title)
end

function OnMouseMove(previous_pos, current_pos)
    DefaultOnMouseMove(previous_pos, current_pos)
end

function OnSetTool(tool)
    DefaultOnSetTool(tool)
end

function LevelLoaded(level)
end

function OnSceneDestroy(playfield)
    DefaultOnSceneDestroy(playfield)
end

--------------------------------------------------------------------------------
-- CLEAR_ON_SAVE_BEGIN
-- Do not edit code listed below (generated by the editor on each save)
function LoadData(screen)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/fon.jpg',0,0,1024,768,1,0)
	anim:SetHotSpot(512,384)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('fon',anim,512,384,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/Pendulum.png',0,0,140,338,1,0)
	anim:SetHotSpot(66,-30)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Pendulum',anim,501,134,103,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/DialPlate.png',0,0,156,164,1,0)
	anim:SetHotSpot(78,82)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('DialPlate',anim,502,134,106,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/cap1.png',0,0,80,76,5,8)
	anim:SetHotSpot(40,38)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('cap1',anim,352,497,102,21,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/cap2.png',0,0,80,76,5,8)
	anim:SetHotSpot(40,38)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('cap2',anim,449,520,102,7,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/cap3.png',0,0,80,76,5,8)
	anim:SetHotSpot(40,38)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('cap3',anim,552,520,102,-10,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/cap4.png',0,0,80,76,5,8)
	anim:SetHotSpot(40,38)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('cap4',anim,649,496,102,-24,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/radial_glow.png',0,0,97,99,1,0)
	anim:SetHotSpot(48,49)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Glow',anim,832,200,101,0,2.5,2.5)
	local anim = CreateAnimation('data/Texture/Scenes/Common/area.png',0,0,8,8,1,0)
	anim:SetHotSpot(2,3)
	anim:SetBlendMode(2)
	anim:SetColor('0x01FFFFFF')
	screen:CreateObject('area_2',anim,738,466,200,0,20,20)
	local anim = CreateAnimation('data/Texture/Scenes/Common/area.png',0,0,8,8,1,0)
	anim:SetHotSpot(2,3)
	anim:SetBlendMode(2)
	anim:SetColor('0x01FFFFFF')
	screen:CreateObject('area_3',anim,738,466,200,0,20,20)
	local anim = CreateAnimation('data/Texture/Scenes/Common/area.png',0,0,8,8,1,0)
	anim:SetHotSpot(4,4)
	anim:SetBlendMode(2)
	anim:SetColor('0x01FFFFFF')
	screen:CreateObject('area',anim,486,713,350,0,90,15)
	local anim = CreateAnimation('data/Texture/Scenes/Common/area.png',0,0,8,8,1,0)
	anim:SetHotSpot(4,4)
	anim:SetBlendMode(2)
	anim:SetColor('0x01FFFFFF')
	screen:CreateObject('area_hint',anim,488,335,105,0,50,70)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/Key_anim.png',0,0,82,77,4,10)
	anim:SetHotSpot(41,38)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Key_anim',anim,768,444,110,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/str.png',0,0,60,38,2,4)
	anim:SetHotSpot(30,19)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('str_1',anim,372,452,102,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/str.png',0,0,60,38,2,4)
	anim:SetHotSpot(30,19)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('str_2',anim,459,472,102,-12,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/str.png',0,0,60,38,2,4)
	anim:SetHotSpot(30,19)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('str_3',anim,549,472,102,-24,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/str.png',0,0,60,38,2,4)
	anim:SetHotSpot(30,19)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('str_4',anim,633,452,102,-37,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/Layer_Fuse_BG.png',0,0,145,126,1,0)
	anim:SetHotSpot(72,63)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Layer_Fuse_BG',anim,505,154,105,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/Pendulum/Layer_Pendulum_Over.PNG',0,0,121,47,1,0)
	anim:SetHotSpot(60,23)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Layer_Pendulum_Over',anim,504,186,104,0,1,1)
end

function FreeData(screen)
end
-- CLEAR_ON_SAVE_END
