--[[
миниигра с преломлением света. надо расставить разноцветные кристаллы, чтобы попасть лучом определенного цвета на кристалл в центре
]]

light_refraction = {}
local self = light_refraction

self.params = {
	sound_select = "crystal_select", -- выделение кристалла
	sound_put = "crystal_put", -- положить кристалл на место

	crystal_types = 
	{ -- id разных типов кристаллов (клипы)
		"crystall_red", 
		"crystall_green", 
		"crystall_blue"
	}, 
	crystal_active = 
	{ -- выделение на кристаллы, через которые проходит луч
		{
			id = "crystall_red_light", -- красный 
			alpha = 150
		},
		{
			id = "crystall_green_light", -- зеленый
			alpha = 200
		},
		{
			id = "crystall_blue_light", -- голубой
			alpha = 170
		}
	},
	win_crystal_wrong_shine = "yellow_shine_wrong", -- id свечения центр.кристалла, если цвет неверный
	win_crystal_right_shine = "yellow_shine", -- id свечения центр.кристалла для правильного цвета
	crystal_selection = "scene06_03_minigame_select", -- id клипа на выделение
	ray_id = "scenes_chapter06_scene03_minigame_ray", -- id лучика
	start_ray=
	{
		X = 480, Y = 0, angle = - math.pi/4,
		cross = {1, 3, 4}
	},
	ray_alpha = 120, -- прозрачность луча света
	win_delay = 1000, -- задержка после победы
	crystals = { 1, 1, 2, 2, 3, 3}, -- виды доступных изначально кристаллов
	--crystals_pos = sf.misc.FloatVector(160, 99), -- место, где изначально лежат кристаллы
	crystals_pos = {24, 25, 26, 27, 28, 29}, -- позиции, в которых находятся кристаллы
	init_pos_dist = 36, -- расстояние между начальными положениями
	max_ray_length = 1000, -- максимальная длина луча
	color_selected = sf.graphics.Color(255, 160, 200, 255),
	pos_size = sf.misc.FloatVector(20, 20), 
	win_positions = {3, 15, 14, 19, 22, 10}, -- последовательность для победы
	win_color = sf.graphics.Color(255, 255, 0), -- какой должен быть цвет у луча в конце
	win_crystal = sf.misc.FloatVector(510, 310), -- до какой позиции идет луч
	win_crystal_shine = sf.misc.FloatVector(497, 345), -- в каком месте сияние
	
	pos_shine = "hole_shine", -- клип на подсветку лунки при наведении мыши
	positions = 
	{ -- геморрой с настройкой преломлений луча, если он попадет на эту позицию, а в ней стоит кристалл
		{ -- 1
			X = 685, Y = 196, angle = math.pi/5.5, -- позиция кристалла , угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(680, 195), -- позиция, в которую ставится луч
			cross = {6, 13} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 2
			X = 801, Y = 188, angle = 0, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(796, 188), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 3
			X = 774, Y = 279, angle = math.pi/9, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(770, 279), -- позиция, в которую ставится луч
			cross = {5, 15, 17} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 4
			X = 860, Y = 367, angle = math.pi/6 - math.pi/40, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(855, 367), -- позиция, в которую ставится луч
			cross = {16} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 5
			X = 755, Y = 339, angle = -math.pi/7 + math.pi/64, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(747, 339), -- позиция, в которую ставится луч
			cross = {16} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 6
			X = 651, Y = 252, angle = -math.pi/14, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(645, 255), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 7
			X = 548, Y = 255, angle = math.pi/9 - math.pi/24, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(545, 255), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 8
			X = 434, Y = 194, angle = 13.4*math.pi/24, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(434, 192), -- позиция, в которую ставится луч
			cross = {9} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 9
			X = 227, Y = 160, angle = -2*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(235, 160), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 10
			X = 254, Y = 224, angle = -math.pi/2.8, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(250, 235), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 11
			X = 286, Y = 288, angle = -1.06*math.pi/2, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(286, 295), -- позиция, в которую ставится луч
			cross = {7, 6} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 12
			X = 313, Y = 365, angle = math.pi/2, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(313, 360), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 13
			X = 558, Y = 398, angle = 0.98*math.pi, --+ math.pi/44, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(565, 401), -- позиция, в которую ставится луч
			cross = {7, 29} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 14
			X = 631, Y = 407, angle = math.pi/6, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(625, 407), -- позиция, в которую ставится луч
			cross = {18, 19} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 15
			X = 729, Y = 416, angle = 1.08*math.pi/2, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(729, 410), -- позиция, в которую ставится луч
			cross = {14, 13, 12} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 16
			X = 812, Y = 471, angle = math.pi/3 , -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(812, 464), -- позиция, в которую ставится луч
			cross = {17} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 17
			X = 690, Y = 542, angle = 1.92*math.pi/3 + math.pi/24, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(695, 538), -- позиция, в которую ставится луч
			cross = {18, 11} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 18
			X = 589, Y = 489, angle = -math.pi/10, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(580, 489), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 19
			X = 542, Y = 563, angle = 1.28*math.pi/2,--  + math.pi/80, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(545, 558), -- позиция, в которую ставится луч
			cross = {20, 22, 23} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 20
			X = 453, Y = 528, angle = 1.2*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(463, 520), -- позиция, в которую ставится луч
			cross = {21} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 21
			X = 327, Y = 567, angle = 2.47*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(333, 567), -- позиция, в которую ставится луч
			cross = {23} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 22
			X = 354, Y = 475, angle = 2.65*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(363, 477), -- позиция, в которую ставится луч
			cross = {12, 11, 10, 9} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 23
			X = 227, Y = 422, angle = -2*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(227, 427), -- позиция, в которую ставится луч
			cross = {12} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 24
			X = 180, Y = 117, angle = -2*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(180, 117), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 25
			X = 249, Y = 117, angle = -2*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(249, 117), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 26
			X = 321, Y = 117, angle = -2*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(321, 117), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 27
			X = 392, Y = 117, angle = -2*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(392, 117), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 28
			X = 462, Y = 117, angle = -2*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(462, 117), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		},
		{ -- 29
			X = 532, Y = 117, angle = -2*math.pi/3, -- позиция, угол поворота луча в ней
			ray_pos = sf.misc.FloatVector(532, 125), -- позиция, в которую ставится луч
			cross = {} -- какие позиции пересекает луч, если проходит здесь
		}
	}	
}

function self.Init(_owner)
	sminigames.SetStandartScriptName(_owner, light_refraction)
	
	-- инициализация первого луча
	self.rays = {}
	local widget = sf.gui.CImageWidget(self.params.ray_id, "ray", 2, 0)
	local size = widget.GetSize()
	widget.SetSize(size.X, self.params.max_ray_length)
	widget.SetOffset(self.params.start_ray.X, self.params.start_ray.Y)
	self.SetRotation(widget, self.params.start_ray.angle)
	_owner.AddWidget(widget)
	
	self.AddAlphaToRay(widget)
	
	local obj = {
		image = widget,
		angle = self.params.start_ray.angle,
		cross =  self.params.start_ray.cross,
		cur_crystal = 0 -- ни на какой позиции, которую пересекает луч, не стоит кристалл
	}
	table.insert(self.rays, obj)
	
	-- инициализация кристаллов
	self.crystals = {}
	for i = 1, #self.params.crystals do
		local name = self.params.crystal_types[self.params.crystals[i]] -- ресурс кристалла
		local widg = sf.gui.CClipWidget("crystal", 4, 0)
		widg.GetClip().Load(name, true)
		table.insert(self.crystals, {image = widg, obj_type = self.params.crystals[i], pos = 0})
		_owner.AddWidget(widg)
	end
	
	self.positions = {}
	for i, pos in ipairs(self.params.positions) do
		table.insert(self.positions, 0) -- все позиции свободны от кристаллов
	end
	
	self.first_init = true
	-- расставляем по дыркам
	for i = 1, #self.params.crystals do
		self.selected = i
		self.PlaceCrystal(_owner, self.params.crystals_pos[i], true)
	end
	self.first_init = nil
	self.selected = nil -- выбранный кристалл
	
	self.win = false
	self.timer = __create_timer("", "qe_level")
	
	self.crystals_shine = {} -- выделение кристалликов, стоящих на пути лучей 
	
	self.pos_shine = sf.gui.CClipWidget("", 0, 0)
	if self.params.pos_shine and self.params.pos_shine ~= "" then
		self.pos_shine.GetClip().Load(self.params.pos_shine, true)
	end
	_owner.AddWidget(self.pos_shine)
	self.pos_shine.AddFlags(sf.gui.CWidget.FlagHidden)
end 

function self.OnMouseMove(_this, _pos, _state, _broadcast)
	if self.win then
		return true
	end
	
	local pos = self.IsPos(_pos)
	local crystal = self.IsCrystal(_pos)
	if pos and not crystal then
		local center = sf.misc.FloatVector(self.params.positions[pos].X, self.params.positions[pos].Y)
		if self.pos_shine then
			local size = self.pos_shine.GetClip().GetViewSize()
			local off = center - size/2
			self.pos_shine.SetOffset(off.X, off.Y)
			self.pos_shine.RemFlags(sf.gui.CWidget.FlagHidden)
		end
	else
		self.pos_shine.AddFlags(sf.gui.CWidget.FlagHidden)
	end
	return true
end

function self.AddAlphaToRay(_widget)
	local color = sf.graphics.Color(_widget.GetColor())
	color.Alpha = self.params.ray_alpha or 255
	_widget.SetColor(color)
end

function self.SetRotation(_widget, _angle)
	if _angle < 0 then
		_angle = _angle + (math.pi * 2) * (((math.abs(_angle) - (math.abs(_angle) % (math.pi * 2))) / math.pi * 2) + 1)
	end
	if	_angle > math.pi * 2 then
		_angle = _angle % (math.pi * 2)
	end
	local width = _widget.GetSize().X
	_widget.SetRotation(sf.misc.MatrixRotation(_angle, 0, 0))
end 

-- проверяет клик на объект
function self.IsCrystal(_pos)
	for i = 1, #self.crystals do
		local off = self.crystals[i].image.GetOffset()
		local size = self.crystals[i].image.GetClip().GetViewSize()
		if  off.X <= _pos.X and off.X + size.X >=_pos.X and off.Y <= _pos.Y and off.Y+size.Y >= _pos.Y then --and 
				-- sminigames.IsVisiblePoint(self.crystals[i].image.GetImage(), _pos.X - self.crystals[i].image.GetOffset().X, _pos.Y - self.crystals[i].image.GetOffset().Y) then
					return i
		end
	end
	return nil
end 

-- проверяет клик на позицию
function self.IsPos(_pos)
	for i, pos in ipairs(self.params.positions) do
		if (_pos.X >= pos.X - self.params.pos_size.X/2) and (_pos.X <= pos.X + self.params.pos_size.X/2) and
			(_pos.Y >= pos.Y - self.params.pos_size.Y/2) and (_pos.Y <= pos.Y + self.params.pos_size.Y/2) then
				return i
		end
	end
	return nil
end 

-- выделяет кристалл
function self.SelectCrystal(_i, _owner)
	self.DeselectCrystal(_owner)
	self.selected = _i
	if self.params.sound_select then
		sound(self.params.sound_select)
	end
	
	self.selection_clip = sf.gui.CClipWidget("", 1, 0)
	self.selection_clip.GetClip().Load(self.params.crystal_selection, true)
	
	local offset = self.crystals[self.selected].image.GetOffset() + self.crystals[self.selected].image.GetClip().GetViewSize()/2
	local size = self.selection_clip.GetClip().GetViewSize()
	self.selection_clip.SetOffset(offset.X - size.X/2, offset.Y - size.Y/2)
	
	_owner.AddWidget(self.selection_clip)
end

-- снимает выделение с кристалла
function self.DeselectCrystal(_owner)
	_owner.RemoveWidget(self.selection_clip)
	self.selection_clip = nil
	self.selected = nil
end	

-- находит луч, который мы пересекли, когда поставили кристалл
function self.FindRay(_pos)
	local i = #self.rays
	while i > 0 do
		local ray = self.rays[i]

		for j, cross in ipairs(ray.cross) do
			if cross == _pos  then
				return {i, j}
			end
		end
		i = i - 1
	end
	return nil
end

-- находит, какой кристалл стоит на позиции
function self.FindCrystalByPos(_pos)
	for i = 1, #self.crystals do
		if self.crystals[i].pos == _pos then
			return i
		end
	end
	return nil
end

-- восстанавливает лучи после того, как кристалл убрали
function self.ReturnOldRays(_owner, _ray, _old_crystal)
	local flag = false
	for j, cross in ipairs(self.rays[_ray].cross) do
		if self.positions[cross] > 0 and j ~= _old_crystal then
			-- на позиции стоит кристалл
			self.rays[_ray].cur_crystal = j
			flag = true
			self.selected = self.FindCrystalByPos(cross)
			if self.selected then
				self.PlaceCrystal(_owner, cross, false)			
				self.ReturnOldRays(_owner, _ray + 1, 0)
			end
			break
		end
	end
	if not flag and (not self.end_ray) then
		local size = self.rays[_ray].image.GetSize()
		self.rays[_ray].image.SetSize(size.X, self.params.max_ray_length)
		self.rays[_ray].cur_crystal = 0
	end
end

-- вычисляет длину луча от позиции _ray_start до позиции _pos 
function self.RayLength(_ray_start, _pos)
	local off1 = self.rays[_ray_start].image.GetOffset()
	local off2 = self.params.positions[_pos]
	local count_x = (off1.X - off2.X)*(off1.X - off2.X)
	local count_y = (off1.Y - off2.Y)*(off1.Y - off2.Y)
		
	local dist = math.sqrt(count_x + count_y)
	return dist
end

-- возвращает список кристаллов, которые должны светиться
function self.ShiningCrystals()
	local crystals = {}
	for i, ray in ipairs(self.rays) do
		if ray.cur_crystal ~= 0 then
			local num = self.FindCrystalByPos(ray.cross[ray.cur_crystal])
			table.insert(crystals, num)
		end
	end
	return crystals
end

-- проверяет, сияет ли уже кристалл _i
function self.CrystalHasShine(_i)
	for i, shine in ipairs(self.crystals_shine) do
		if shine.crystal_num == _i then
			return i
		end
	end
	return false
end

-- проверяет, есть ли объект _obj в списке _list 
function self.ListHasObject(_list, _obj)
	for i, obj in ipairs(_list) do
		if obj == _obj then 
			return i
		end
	end
	return false
end

-- обновляет клипы с сияющими кристаллами
function self.SetCrystalsShine(_owner)
	-- получаем список кристаллов, которые должны гореть
	local crystals_to_shine = self.ShiningCrystals()
	
	-- добавляем сияния туда, где его еще нет
	if crystals_to_shine then
		for _, num in pairs(crystals_to_shine) do
			local shining = self.CrystalHasShine(num)
			if not shining then
				-- еще нет сияния
			--	__message("+ shine to "..num)
				local shine_id = self.params.crystal_active[self.crystals[num].obj_type].id
			--	__message(shine_id)
				local img = sf.gui.CClipWidget("shine", 0, 0)
				img.GetClip().Load(shine_id, true)
				local color = sf.graphics.Color(img.GetColor())
				color.Alpha = self.params.crystal_active[self.crystals[num].obj_type].alpha
				img.SetColor(color)
				
				local offset = self.crystals[num].image.GetOffset() + self.crystals[num].image.GetClip().GetViewSize()/2
				local size = img.GetClip().GetViewSize()
				img.SetOffset(offset.X - size.X/2, offset.Y - size.Y/2)
				_owner.AddWidget(img)
				
				local obj = {image = img, crystal_num = num}
				table.insert(self.crystals_shine, obj)
			else
				-- восстанавливаем позицию сияния, если мы передвинули кристалл с одного луча под другой
				local obj = self.crystals_shine[shining]
				local offset = self.crystals[num].image.GetOffset() + self.crystals[num].image.GetClip().GetViewSize()/2
				local size = obj.image.GetClip().GetViewSize()
				obj.image.SetOffset(offset.X - size.X/2, offset.Y - size.Y/2)
			end
		end
	end
	-- смотрим, какие надо удалить
	local shine_to_remove = {}
	for i = 1, #self.crystals do
		if not self.ListHasObject(crystals_to_shine, i) and self.CrystalHasShine(i) then
			-- надо удалить сияние
			for j = 1, #self.crystals_shine do
				if self.crystals_shine[j].crystal_num == i then
					_owner.RemoveWidget(self.crystals_shine[j].image)
					table.insert(shine_to_remove, j)
				end
			end
		end
	end
	
	local i, n = #self.crystals_shine, #self.crystals_shine
	while i > 0 do
		local num = self.ListHasObject(shine_to_remove, i)
		if num then
			table.remove(self.crystals_shine, shine_to_remove[num])
			table.remove(shine_to_remove, num)
			n = n - 1
		else
			i = i - 1
		end
	end
end

-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Функция перемещения кристалла по позициям и перетасовка лучей в связи с изменением его положения
function self.PlaceCrystal(_owner, _pos, _flag)
	if self.params.sound_put and not self.first_init then
		sound(self.params.sound_put)
	end
	local ray_num1 = self.FindRay(self.crystals[self.selected].pos)
	local sel = self.selected -- запоминаем выделенный номер, т.к. он может потеряться при восстановлении лучей
	if _flag and ray_num1 and  
			(ray_num1[2] <= self.rays[ray_num1[1]].cur_crystal or self.rays[ray_num1[1]].cur_crystal == 0) then
		-- он раньше стоял на пути у луча => надо восстановить старый луч
		-- сперва удаляем лучи, полученные после преломления
		while ray_num1[1] ~= #self.rays do
				_owner.RemoveWidget(self.rays[ray_num1[1] + 1].image)
				table.remove(self.rays, ray_num1[1] + 1)
		end
		if self.end_ray then
			self.end_ray = false
			self.RemWinCrystalShine(_owner)
		end
		-- восстановление лучей
		self.ReturnOldRays(_owner, ray_num1[1], ray_num1[2])
	end
	
	self.positions[self.crystals[sel].pos] = 0
	local img = self.crystals[sel ].image
	local sz = self.crystals[sel ].image.GetClip().GetViewSize()
	img.SetOffset(self.params.positions[_pos].X - sz.X/2, self.params.positions[_pos].Y - sz.Y/2)
	self.crystals[sel].pos = _pos
	self.positions[_pos] = self.crystals[sel].obj_type
	
	-- проверяем, не пересекли ли какой-нибудь луч
	local ray_num = self.FindRay(_pos)
	
	if ray_num then
		-- проверяем, доходит ли луч до этой позиции
		if  (ray_num[2] <= self.rays[ray_num[1]].cur_crystal or self.rays[ray_num[1]].cur_crystal == 0)then
			-- если до этого луч не пересекал другой кристалл
			-- удаляем лучи, которые идут дальше
			while ray_num[1] ~= #self.rays do
				_owner.RemoveWidget(self.rays[ray_num[1] + 1].image)
				table.remove(self.rays, ray_num[1] + 1)
			end
			-- вычисляем новую длину луча, который пересекли
			local dist = self.RayLength(ray_num[1], _pos)
			local size = self.rays[ray_num[1]].image.GetSize()
			self.rays[ray_num[1]].image.SetSize(size.X, dist)
			
			self.rays[ray_num[1]].cur_crystal = ray_num[2]  -- установили, что этот луч пересекает кристалл
			-- создание нового луча
			local widget = sf.gui.CImageWidget(self.params.ray_id, "ray", 2, 0)
			local size = widget.GetSize()
			local length = self.params.max_ray_length
			if _pos == self.params.win_positions[#self.params.win_positions] then
				-- последний луч выигрышной последовательности, надо сделать его не бесконечным
				--__message("_pos =".._pos)
				local off1 = {X = self.params.positions[_pos].X, Y = self.params.positions[_pos].Y}
				local off2 = self.params.win_crystal
				local count_x = (off1.X - off2.X)*(off1.X - off2.X)
				local count_y = (off1.Y - off2.Y)*(off1.Y - off2.Y)
		
				length = math.sqrt(count_x + count_y)
				self.end_ray = true
			else 
				self.end_ray = false
				self.RemWinCrystalShine(_owner)
			end
			widget.SetSize(size.X, length)
			widget.SetOffset(self.params.positions[_pos].ray_pos.X, self.params.positions[_pos].ray_pos.Y)
			self.SetRotation(widget, self.params.positions[_pos].angle)
			_owner.AddWidget(widget)
			
			-- меняем цвет луча
			local color = sf.graphics.Color(self.rays[ray_num[1]].image.GetColor())
			self.UpdateColor(color, _pos)
			widget.SetColor(color)
			self.AddAlphaToRay(widget)
			
			-- создали новый луч
			local obj = 
			{
				image = widget,
				angle = self.params.positions[_pos].angle,
				cross =  self.params.positions[_pos].cross,
				cur_crystal = 0 -- ни на какой позиции, которую пересекает луч, не стоит кристалл
			}
			table.insert(self.rays, obj)
			-- если луч попадает на поставленный ранее кристалл, надо снова поменять лучи
			self.ReturnOldRays(_owner, #self.rays, 0)
		end
	end
end

-- меняет цвет луча
function self.UpdateColor(_color, _pos)
	if self.positions[_pos] == 1 then -- красный
		if _color.Red == 255 and _color.Green == 255 and _color.Blue == 255 then
			_color.Green = 0 
			_color.Blue = 0
		else
			_color.Red = 255
		end
	elseif self.positions[_pos] == 2 then -- зеленый 
		if _color.Red == 255 and _color.Green == 255 and _color.Blue == 255 then
			_color.Red = 0 
			_color.Blue = 0
		else
			_color.Green = 255
		end
	elseif self.positions[_pos] == 3 then -- синий 
		if _color.Red == 255 and _color.Green == 255 and _color.Blue == 255 then
			_color.Green = 0 
			_color.Red = 0
		else
			_color.Blue = 255
		end
	end
end

function self.OnMouseDown(_owner, _pos, _button, _keyboard_state, _broadcast)
	local crystal = self.IsCrystal(_pos)
	local pos = self.IsPos(_pos)
	if crystal then
		if self.selected == crystal then
			self.DeselectCrystal(_owner)
		else
			self.SelectCrystal(crystal, _owner)
		end
	elseif pos then
		if self.selected  and self.positions[pos] == 0 then
			self.PlaceCrystal(_owner, pos, true)
			self.SetCrystalsShine(_owner)
			self.DeselectCrystal(_owner)
			self.CheckEnd(_owner)
		end
	end
	
	return true
end 
-- проверить победу
function self.CheckEnd(_owner)
	for i = 1, #self.params.win_positions do
		if self.positions[self.params.win_positions[i]] == 0 then
			return nil
		end
	end
	-- если на всех позициях стоит кристалл, надо сравнить цвет луча с тем, который должен быть последним
	local color = sf.graphics.Color(self.rays[#self.rays].image.GetColor())
	local aim_color = self.params.win_color
	if color.Red == aim_color.Red and color.Green == aim_color.Green and color.Blue == aim_color.Blue then
		self.AddWinCrystalShine(_owner, true)
		self.win = true
		self.start_win = self.timer.Get().GetTime()
		return true
	end
	self.AddWinCrystalShine(_owner, false)
	return nil
end 

-- устанавливает свечение последнего кристалла
function self.AddWinCrystalShine(_owner, flag)
	local id = self.params.win_crystal_wrong_shine
	if flag then
		-- добавляем победное свечение
		id = self.params.win_crystal_right_shine
	end
--	__message(id)
	local offset = self.params.win_crystal_shine
	if self.win_shine then
		_owner.RemoveWidget(self.win_shine)
	end
	self.win_shine = sf.gui.CClipWidget("", 0, 0)
	self.win_shine.GetClip().Load(id, true)
	local size = self.win_shine.GetClip().GetViewSize()
	self.win_shine.SetOffset(offset.X - size.X/2, offset.Y - size.Y/2)
	_owner.AddWidget(self.win_shine)
end
-- убирает свечение центрального кристалла
function self.RemWinCrystalShine(_owner)
	if self.win_shine then
		_owner.RemoveWidget(self.win_shine)
	end
end

function self.OnUpdate(_owner)
	if  sf.core.g_Application.GetTimeManager().GetTimer(_T("qe_level")).GetK() < 0.01 then
		return
	end

	if self.win then
		if self.timer.Get().GetTime() - self.start_win >= self.params.win_delay then
			_owner.SetGameResult(1)
			_owner.OnEndGame()
		end
	end
	return true
end 