-- Game State ----------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------

text_sheet = "re";                 -- Text sheet const
sheet = "gr";                   -- Tool sheet const
gamedata = {};                  -- Table of logical game data
gamedata.id_index = 50000;            -- Starting value of objects id index
gamedata.current_level = "comics1";        -- имя уровня
gamedata.cur_lev_number = 1;          -- номер папки
gamedata.cur_sub_lev_number = 50;        -- номер подпапки
collapsingobj=0
NOW_ATTACHED = nil                -- айдишник предмета в руке
NOW_MINI = false                -- труе: сейчас работает миниигра

alfa = false                  -- труе: экран затемнен глобальным фейдом
threads = {}                  -- таблица потоков загрузки/удаления ресурсов

lvl = nil                    -- имя уровня (временная переменная) в jump()
dop = nil                    -- имя допки

obj = {};                    -- таблица объектов
flags = {};                    -- таблица флагов
cursors = {}                  -- таблица пользовательских курсоров на текущей локации
GI_table = {}                  -- таблица имён функций-гейминпутов

-- Functions for internal use -----------------------------------------------------------------------
-- table.save/table.load ----------------------------------------------------------------------------
do
-- declare local variables
--// exportstring( string )
--// returns a "Lua" portable version of the string
local function exportstring( s )
  s = string.format( "%q",s )
  -- to replace
  s = string.gsub( s,"\\\n","\\n" )
  s = string.gsub( s,"\r","\\r" )
  s = string.gsub( s,string.char(26),"\"..string.char(26)..\"" )
  return s
end
--// The Save Function
function table.save(  tbl,filename )
  local charS,charE = "   ","\n"
  local file,err
  -- create a pseudo file that writes to a string and return the string
  if not filename then
    file =  { write = function( self,newstr ) self.str = self.str..newstr end, str = "" }
    charS,charE = "",""
  -- write table to tmpfile
  elseif filename == true or filename == 1 then
    charS,charE,file = "","",io.tmpfile()
  -- write table to file
  -- use io.open here rather than io.output, since in windows when clicking on a file opened with io.output will create an error
  else
    file,err = io.open( filename, "w" )
    if err then return _,err end
  end
  -- initiate variables for save procedure
  local tables,lookup = { tbl },{ [tbl] = 1 }
  file:write( "return {"..charE )
  for idx,t in ipairs( tables ) do
    if filename and filename ~= true and filename ~= 1 then
      file:write( "-- Table: {"..idx.."}"..charE )
    end
    file:write( "{"..charE )
    local thandled = {}
    for i,v in ipairs( t ) do
      thandled[i] = true
      -- escape functions and userdata
      if type( v ) ~= "userdata" then
        -- only handle value
        if type( v ) == "table" then
          if not lookup[v] then
            table.insert( tables, v )
            lookup[v] = #tables
          end
          file:write( charS.."{"..lookup[v].."},"..charE )
        elseif type( v ) == "function" then
          file:write( charS.."loadstring("..exportstring(string.dump( v )).."),"..charE )
        else
          local value =  ( type( v ) == "string" and exportstring( v ) ) or tostring( v )
          file:write(  charS..value..","..charE )
        end
      end
    end
    for i,v in pairs( t ) do
      -- escape functions and userdata
      if (not thandled[i]) and type( v ) ~= "userdata" then
        -- handle index
        if type( i ) == "table" then
          if not lookup[i] then
            table.insert( tables,i )
            lookup[i] = #tables
          end
          file:write( charS.."[{"..lookup[i].."}]=" )
        else
          local index = ( type( i ) == "string" and "["..exportstring( i ).."]" ) or string.format( "[%d]",i )
          file:write( charS..index.."=" )
        end
        -- handle value
        if type( v ) == "table" then
          if not lookup[v] then
            table.insert( tables,v )
            lookup[v] = #tables
          end
          file:write( "{"..lookup[v].."},"..charE )
        elseif type( v ) == "function" then
          file:write( "loadstring("..exportstring(string.dump( v )).."),"..charE )
        else
          local value =  ( type( v ) == "string" and exportstring( v ) ) or tostring( v )
          file:write( value..","..charE )
        end
      end
    end
    file:write( "},"..charE )
  end
  file:write( "}" )
  -- Return Values
  -- return stringtable from string
  if not filename then
    -- set marker for stringtable
    return file.str.."--|"
  -- return stringttable from file
  elseif filename == true or filename == 1 then
    file:seek ( "set" )
    -- no need to close file, it gets closed and removed automatically
    -- set marker for stringtable
    return file:read( "*a" ).."--|"
  -- close file and return 1
  else
    file:close()
    return 1
  end
end

function PlayMusic()
  --if not flags.is_comics then
  k=table.getn(play)
  m=math.random(1,k);
  if play[m]~=-1 then
--Write("Number of music - "..k.."\nNow we are going to play music number - "..m.."\n",true)
    playfile(play[m],false,true);
--Write("play[m] = "..play[m].."\n")
    timer_time=dlinap[m]+zader[m]
    StartTimer(12542,timer_time,"PlayMusic",true)
    play[m]=-1;
  else
    is_list_emty=true
    for i,v in pairs(play) do
      if play[i]~=-1 then
        is_list_emty=false
      end;
    end;
    if not is_list_emty then
      PlayMusic()
    else
      PlayList()   
      PlayMusic()
    end;
  end;
  --end;
end;
--[[local tbPlayList={};

function PlayMusic()
  local n=table.getn(tbPlayList);

  Write("n="..n.."\n")
  if n>0 then
    playfile(tbPlayList[n].name,false,true);
    Write("tbPlayList["..n.."].name="..tbPlayList[m].name.."\n")
    StartTimer(12542,tbPlayList[n].length+tbvPlayList[n].silence,"PlayMusic",true)
    table.remove(tbPlayList)
    return;
  end
  tbPlayList=play
  return PlayMusic()
end]]
--// The Load Function
function table.load( sfile )
  -- catch marker for stringtable
  if string.sub( sfile,-3,-1 ) == "--|" then
    tables,err = loadstring( sfile )
  else
    tables,err = loadfile( sfile )
  end
  if err then return _,err
  end
  tables = tables()
  for idx = 1,#tables do
    local tolinkv,tolinki = {},{}
    for i,v in pairs( tables[idx] ) do
      if type( v ) == "table" and tables[v[1]] then
        table.insert( tolinkv,{ i,tables[v[1]] } )
      end
      if type( i ) == "table" and tables[i[1]] then
        table.insert( tolinki,{ i,tables[i[1]] } )
      end
    end
    -- link values, first due to possible changes of indices
    for _,v in ipairs( tolinkv ) do
      tables[idx][v[1]] = v[2]
    end
    -- link indices
    for _,v in ipairs( tolinki ) do
      tables[idx][v[2]],tables[idx][v[1]] =  tables[idx][v[1]],nil
    end
  end
  return tables[1]
end
end; -- close do
-- End table.save/table.load ------------------------------------------------------------------------


------------------------------------------------------------
--  function: setInputFunction
--  устанавливает функцию обработки ввода
--  работает как LIFO стек
--  если "name" пусто, то восстанавливается предыдущий гейминпут
------------------------------------------------------------
function setInputFunction(name)
  if name == nil then
    table.remove(GI_table)
    name = GI_table[table.maxn(GI_table)]
  else
    table.insert(GI_table,name)
  end
  set_inpun_fun(name)
  Write("Current Input Func: "..tostring(name).."\n")
end


------------------------------------------------------------
--  function: SaveGame
------------------------------------------------------------
function SaveGame()
  savepath = GetSavePath() .. tostring(username) .. ".sav";
  gamedata.flags = flags
  gamedata.neighbors = neighbors
  gamedata.obj = obj
  gamedata.journal = Journal.pages
  gamedata.currentPage = Journal.currentPage
  gamedata.journalID = Journal.id
  Write("\n\nSAVE GAME: "..tostring(savepath).."\n")
  table.save( gamedata, savepath );
end;


------------------------------------------------------------
--  function: LoadGame
------------------------------------------------------------
function LoadGame()
  savepath = GetSavePath() .. tostring(username) .. ".sav";
  if io.open( savepath, "r" ) then --загрузка после сохранения  
    gamedata = table.load( savepath );
    flags = gamedata.flags;
    neighbors = gamedata.neighbors
    obj = gamedata.obj;
    Journal.pages = gamedata.journal;
    Journal.currentPage = gamedata.currentPage
    Journal.id = gamedata.journalID
  end;
  for i,v in pairs(Journal.pages) do
    Journal.pages[i].thread = 0
    Journal.pages[i].loaded = false
  end  
  for i, v in pairs(neighbors) do --сброс флагов, определяющих загрузку локаций
    if type(v) == "table" then
      v.loaded = false;
      v.obj_created=false;
      v.thread = 0;
    end;
  end;
  --новый профиль
    rendering=false
  hiddenending=false
  tutorial_window=false
  jump(gamedata.current_level)
  pages_loaded=false
  PlayList()   
    PlayMusic()
  
    StartTimer(timerID,0.2,"CheckHint")
end;


------------------------------------------------------------
--  function: jump
------------------------------------------------------------
function jump(level)
  if neighbors[level].lock then    -- если локация закрыта
    return              -- выходим вон
  else
    if NOW_ATTACHED then      -- убираем итем из руки
      removeFromMouse(NOW_ATTACHED)
    end
    StopAllEffects()   
    lvl = level
    if not alfa then
      Write("\n\t\tJump "..lvl.."\n\n")
      BlockCursor(true)
      fTeleportation=true
      SetAlfa(9090,0,1,g_jumptime,"SetAlfaCallback")      -- затемняем экран
      return
    end
    if not (neighbors[level].loaded and neighbors[level].thread == 0) then  -- если локация не загружена и не грузится,
      checkLocation()                            -- то грузим её,
      return                                -- а до тех пор ничего не делаем
    end
    -- здесь непосредственно создание уровня
    gamedata.cur_lev_number = neighbors[level].level
    gamedata.cur_sub_lev_number = neighbors[level].sublevel
    ClearCursor()  -- очищаем курсоры
    StopEmiter(hintEmiter)  -- выключаем эммитер-подсказку
    hintRuning = false
    if neighbors[level].obj_created then         --переход на локацию, если ее объекты и лист созданы
      setcurentleaf(level,gamedata.cur_lev_number,gamedata.cur_sub_lev_number)
    else                        --переход на локацию, если ее лист и объекты не созданы
      delete_tree_leaf("Root",level);          --на всякий случай удаляем лист
      add_tree_leaf("Root",level,gamedata.cur_lev_number,gamedata.cur_sub_lev_number)  -- добавляем лист
      -- cursors = {}  
      dofile("./data/"..gamedata.cur_lev_number.."/"..gamedata.cur_sub_lev_number.."/res.lua")
      neighbors[level].obj_created = true;      
      if level == gamedata.current_level then        --если мы загрузились
        for i,v in pairs( obj ) do             --восстанавливаем объекты инвентаря
          if type( obj[i] ) == "table" then
            if obj[i].is_stored then
              local a = GetObjectSize(obj[i].id)
              if a == -1 then -- если объект не создался на уровне
                --out("\t"..tostring(i)..": "..tostring(obj[i].id)..","..tostring(obj[i].resname).."\n")
                loadresource(invent_source[obj[i].resname], obj[i].resname)
                addactivobjecttogame(obj[i].id, obj[i].resname, 0-2048, 0+2048, "", obj[i].notice)
                AddElement("gr", obj[i].id)
                MoveObjectToTree(obj[i].id)
              end
            end
          end
        end
      end
      if flags.is_hidden_loc then --рисование вкладок на новой локации
        SetDrawSheet("gr",false);
        SwitchToSheet("re");
      else
        SwitchToSheet("gr");
        SetDrawSheet("gr",true);
      end;
      ShowMenu(true);
      dofile("./data/"..gamedata.cur_lev_number.."/"..gamedata.cur_sub_lev_number.."/level.lua")
    end
    processNeighbors(level)          --обрабатываем соседей: грузим нужных, удаляем ненужных
    gamedata.current_level = level
    if alfa then
      SetAlfa(9090,1,0,g_jumptime,"SetAlfaCallback")    -- растемняем экран
    end
    jumpEmiter = nil
    if not flags.is_comics then SaveGame() end  -- автосейв при каждом переходе
  end
end


------------------------------------------------------------
--  function: checkLocation
-- эта функция проверяет загружена ли локация,
-- на которую переходим, и, если не загружена, то грузит её
------------------------------------------------------------
function checkLocation()          -- Loaded? ORLY?
  if neighbors[lvl].thread == 0 then
    if not neighbors[lvl].loaded then        
      neighbors[lvl].thread = PreLoadResource("data//0//global_res.lua",lvl,"PreLoadCallback") -- грузим их!
      Write("__loading "..lvl..";    thread="..neighbors[lvl].thread.."\n")
      threads[neighbors[lvl].thread] = lvl      -- длаем запись в таблицу потоков
      StartTimer(7891,g_jumptime,"checkLocation")
    else
      jump(lvl)
    end
  else
    StartTimer(7890,g_jumptime,"checkLocation")
  end
end


------------------------------------------------------------
--  function: SetAlfaCallback
-- это callback для джамп-эффекта
------------------------------------------------------------
function SetAlfaCallback()
  if alfa == false then
    alfa = true      -- тру: экран затемнен
    jump(lvl)
  else
    alfa = false
      if not flags.CursorBlocking then
    BlockCursor(false)
    end;
    fTeleportation=false
-- Block_Show_Cur(false)
  end
end


------------------------------------------------------------
--  function: processNeighbors
-- обрабатываем соседей: грузим нужных, удаляем ненужных.
-- подгрузку соседей PreLoad-ом закоментировал; без неё меньше тормозит
------------------------------------------------------------
function processNeighbors(level)
  -- for i = 1,neighbors[level].neighbors_count do      -- проходим по всем соседним локациям
    -- if not neighbors[neighbors[level][i]].loaded and neighbors[neighbors[level][i]].thread == 0 and not neighbors[neighbors[level][i]].lock then
      -- neighbors[neighbors[level][i]].thread = PreLoadResource("./data/0/global_res.lua",neighbors[level][i],"PreLoadCallback")  -- грузим незагруженные
      -- Write("loading "..neighbors[level][i]..";   thread="..neighbors[neighbors[level][i]].thread.."\n")
      -- threads[neighbors[neighbors[level][i]].thread] = neighbors[level][i]      -- длаем запись в таблицу потоков
    -- end
  --end
  for i = 1,neighbors[gamedata.current_level].neighbors_count do              -- проходим по всем локациям.
    a = neighbors[gamedata.current_level][i]
    if neighbors[a].loaded and neighbors[a].thread == 0 and a ~= level then        -- те, которые зугружены и не в процессе удаления
      local thread = DeleteResources("./data/0/global_res.lua",a,"DeleteResourceCallback") -- удаляем!
      Write("\tdeleting "..a..";   thread="..thread.."\n")
      neighbors[a].thread = thread
      threads[thread] = a            -- длаем запись в таблицу потоков
    end
  end
end


------------------------------------------------------------
--  function: PreLoadCallback
------------------------------------------------------------
function PreLoadCallback(thread)
  if threads[thread] then
    neighbors[threads[thread]].loaded = true
    neighbors[threads[thread]].thread = 0
    Write("LOADED "..threads[thread]..";   thread="..thread.."\n")
    table.remove(threads,thread)
  end
end


------------------------------------------------------------
--  function: DeleteResourceCallback
------------------------------------------------------------
function DeleteResourceCallback(thread)
  if threads[thread] then
    neighbors[threads[thread]].loaded = false
    neighbors[threads[thread]].thread = 0
    delete_tree_leaf("Root",threads[thread]);
    neighbors[threads[thread]].obj_created=false;
    Write("\tDELETED "..threads[thread]..";   thread="..thread.."\n")
    table.remove(threads,thread)
  end
end


------------------------------------------------------------
--  function: NewId
-- создание уникального айдишника
------------------------------------------------------------
function NewId(name) -- name must be string
  if type(name) ~= "string" then 
    --out("Wrong type(" .. type(name) ..") of name param");
  return; end;
  if obj[name] == nil then
    obj[name] = {};
  end;
  if not obj[name].id then
    gamedata.id_index = gamedata.id_index + 1;
    obj[name].id = gamedata.id_index;
  end;
  return obj[name].id;
end;
-- End of Auto id -----------------------------------------------------------------------------------


------------------------------------------------------------
--  function: NewObj
-- создание нового объекта
------------------------------------------------------------
function NewObj(name, resname, x, y, notice, ...) --создание активных объектов -- name не больше 6 символов (маленькие английские)
  if obj[name] then --если объект уже был создан...
    if obj[name].deleted then
      return
    end
    if obj[name].is_collapsed then --если объект коллапсился...
      if flags.is_hidden_loc then
        if obj[name].is_stored then
          loadresource(invent_source[obj[name].resname], obj[name].resname)
          obj[name].id = obj[name].id - 100000
        end
        addactivobjecttogame(obj[name].id, obj[name].resname, x+2048, y+2048, "", notice, unpack(arg))
        collaps_obj(obj[name].id, 0, 0, 0, 0)
        flags.collapsed = flags.collapsed + 1
      end
    else
      addactivobjecttogame(obj[name].id, resname, x, y, "", notice, unpack(arg))
    end
    if notice ~= "" then
      if flags.is_hidden_loc then
        AddElement("re",obj[name].id);
      end
    end
  else
    obj[name] = {};
    obj[name].name = name;
    obj[name].id = NewId(name);
    obj[name].resname = resname;
    obj[name].notice = notice;
    addactivobjecttogame(obj[name].id, resname, x, y, "", notice, unpack(arg));  
    if notice ~= "" then
      if flags.is_hidden_loc then
        AddElement("re",obj[name].id);
      end
    end
  end;
  set_pixel_check(obj[name].id,false)
end;


------------------------------------------------------------
--  function: CollapseObj
-- коллапс
------------------------------------------------------------
function CollapseObj(obj_id)
    if collapsingobj==0 then
    collapsingobj=obj_id
    end;
  if hintprocessing then
    hideHint()

    StartTimer(timerID,0.1,"CollapseObj")
  else
    for i,v in pairs(obj) do
      if obj[i].id == collapsingobj then
        if obj[i].shadow then
          DeleteObj(obj[i].shadow)
        end
        StopEmiter(hintEmiter)
        hintRuning = false
        playeffect("collapse")
        local param = {0.8,0.3,2,700,1,0.2,0.1}
        -- local param = {0.6, 0.4, 1.4, 15, 1, 0.1, 1}
        Fadeaway(collapsingobj,nil,nil,"COLLAPSE_FTW","farShootStyle",7,param)
        obj[i].is_collapsed = true
        flags.collapsed = flags.collapsed + 1
        collapsingobj=0
        Write(flags.collapsed.." "..i.."\n")
      end
    end
  end;
end


------------------------------------------------------------
--  function: StoreObj
-- добавление в инвентарь состоит из двух частей:
-- 1. функцией StoreObj() рисуем окошко с наградой
-- 2. по клику закрываем окошко, и добавляем итем функцией addToInventory().
-- если выйти из игры, пока висит окошко с наградой,
-- то итем всё равно добавится при следующей загрузке
------------------------------------------------------------
function StoreObj(obj_id)
  for i,v in pairs(obj) do
    if obj[i].id == obj_id then
      SetObjectPosition(obj_id,2000,2000)
      ClearCursor1()
      removeFromMouse()
      if obj[i].shadow then
        DeleteObj(obj[i].shadow)
      end
      local resource = ""
      storeId = obj_id + 100000
      obj[i].is_collapsed = true
      obj[i].is_stored = true
      resource = i.."_i"
      if invent_source[resource] then
        --out("invent_source["..tostring(resource).."]="..tostring(invent_source[resource]).."\n")
        out(tostring(loadresource(invent_source[resource], resource)).."\n")
        obj[i].resname = resource
      end
      addactivobjecttogame(storeId,obj[i].resname,2427,2261,"",obj[i].notice)
      obj[i].id = storeId
      --out("obj[i].resname="..tostring(obj[i].resname).."\n")
      CreateWindow(obj[i].notice,-1,"okno",obj[i].resname,2)
    end
  end
end


------------------------------------------------------------
--  function: addToInventory
------------------------------------------------------------
function addToInventory()
  if storeId then
    AddElement("gr",storeId)
    MoveObjectToTree(storeId)
  --  ShowSheet("gr","move",2000,true);
    storeId = nil
  end
end


------------------------------------------------------------
--  function: UnStoreObj
------------------------------------------------------------
function UnStoreObj(obj_id)
  for i,v in pairs(obj) do
    if obj[i].id == obj_id then
      DeleteElement(sheet,obj_id)
      obj[i].is_stored = false
      obj[i].is_collapsed = true
      obj[i].deleted = true
      del_object_from_game(obj_id)
      DeleteResource(obj[i].resname)
    end
  end
end


------------------------------------------------------------
--  function: DeleteObj
------------------------------------------------------------
function DeleteObj(obj_id)
  set_visible_object(obj_id,false)
  for i,v in pairs(obj) do
    if obj[i].id == obj_id then
      obj[i].deleted = true
      del_object_from_game(obj[i].id)
    end
  end
end


------------------------------------------------------------
--  function: AddShadow
-- этой функцией можно добавить объекту тень,
-- которая исчезнет, когда мы подберём или отколлапсим объект
------------------------------------------------------------
function AddShadow(obj_id,shadow_id)
  ActivateObject(shadow_id,false)
  for i,v in pairs(obj) do
    if obj[i].id == obj_id then
      obj[i].shadow = shadow_id
    end
  end
end


------------------------------------------------------------
--  function: CreateSatelite
-- создание сателлита
------------------------------------------------------------
function CreateSatelite(name)
  if neighbors[name].lock then    -- если локация закрыта
    return              -- выходим вон
  else
    dop = name
    if not (neighbors[name].loaded and neighbors[name].thread == 0) then
      checkDopLocation()
      return
    end
    ClearCursor1()
    cursors = {}
    hintRuning = false
    flags.IsSatellite=true
    GetRenderTarget(renderTarget,"renderTargetSateliteCB")
    objectsToRender = {renderTarget}
  end
end


------------------------------------------------------------
--  function: renderTargetSateliteCB
-- callback для РендерТаргета для сателлита
------------------------------------------------------------
function renderTargetSateliteCB(texName,texID)
  --out("renderTargetSateliteCB("..tostring(texName)..","..tostring(texID)..")\n")
  -- FlipVertical(renderTarget)
  -- SetObjectPosition(renderTarget,0,-256)
  SetAlfa(renderTarget,0,1,0)
  LeaveObjectsOnReder("objectsToRender")
  --Postprocess(renderTarget,1)
  BlockCursor(false)
  mini_Button = nil
  level = neighbors[dop].level
  sublevel = neighbors[dop].sublevel
  add_free_leaf("Root",dop,level,sublevel)
  set_satelite_leaf(gamedata.current_level)
  UpdateStack()
  AddObjForCur()
  dofile("./data/"..level.."/"..sublevel.."/res.lua")
  dofile("./data/"..level.."/"..sublevel.."/level.lua")
  -- showFPS(true)
  function SelectRandom()
  end;
end


------------------------------------------------------------
--  function: checkDopLocation
-- проверка загружена ли допка
------------------------------------------------------------
function checkDopLocation()          -- Loaded? ORLY?
  BlockCursor(true)
  if neighbors[dop].thread == 0 then
    if not neighbors[dop].loaded then        
      neighbors[dop].thread = PreLoadResource("data//0//global_res.lua",dop,"PreLoadCallback") -- грузим их!
      Write("__loading "..dop..";    thread="..neighbors[dop].thread.."\n")
      threads[neighbors[dop].thread] = dop      -- длаем запись в таблицу потоков
      StartTimer(7893,g_jumptime,"checkDopLocation")
    else
      BlockCursor(false)
      CreateSatelite(dop)
    end
  else
    StartTimer(7892,g_jumptime,"checkDopLocation")
  end
end


------------------------------------------------------------
--  function: CloseSatelite
-- закрытие сателлита
------------------------------------------------------------
function CloseSatelite()
  Write("clear_satelite_leaf \n")
  cursors = {}
  skipActive = nil
  ACTIVE3 = nil
  StopEmiter(hintEmiter)
  flags.IsSatellite=false
  removeFromMouse()
  clear_satelite_leaf(gamedata.current_level)
end;


------------------------------------------------------------
--  function: miniCreate
-- создание мини-игры
------------------------------------------------------------
function miniCreate()
  mini_create()
  NOW_MINI = true
  CreateMiniOutfit()  -- рисованик кнопок "хелп" и "скип"
  CreatePlashechka(helpID)  -- рисовани плашечки с заданием
end


------------------------------------------------------------
--  function: AddEmiter
-- добавление эмиттера к объекта
-- если флаг "тру", то лепим эмитер снизу объекта (для хидденов),
-- а если "фалсе" то лепим эмиттер по центру (для всего остального)
------------------------------------------------------------
function AddEmiter(obj_id, emiter, flag,x1,y1,ignoreflag)
if  flags.StandartMode or  ignoreflag then
  local a,b = GetObjectSize(obj_id);
  AddParticleToObject(obj_id,emiter);
  if x1~=nil then
   --out("move to coord \n")
    MoveEmiter(emiter,x1,y1)
  else
    local x,y = GetObjectPosition(obj_id)
    if flag then
      MoveEmiter(emiter,x+a/2,y+b)
    else
      MoveEmiter(emiter,x+a/2,y+b/2)
    end
  end;
end;  
  -- --out("("..(x+a/2).." ,"..(y+b/2)..")\n")
end;


------------------------------------------------------------
--  function: addToMouse
-- лепим объект к курсору
------------------------------------------------------------
function addToMouse(id)
  AddObjectToCursor(10000001,id,-6,28)
  NOW_ATTACHED = id
end


------------------------------------------------------------
--  function: removeFromMouse
-- отлепляем от курсора
------------------------------------------------------------
function removeFromMouse(id)
  if not id then
    id = NOW_ATTACHED
  end
  if not id then
    return
  end
  RemoveFromMouse(id)
  FreeObjectFromCursor()
  NOW_ATTACHED = nil
end


------------------------------------------------------------
--  function: setCursor
-- устанавливаем пользовательский курсор
------------------------------------------------------------
function setCursor(id, cursor)
  if cursor == 3 then
    for i,v in pairs(cursors) do
      if i == id then
        sendersProcessing(39,id,-1)
        break
      end
    end
    cursors[id] = nil
    StopOnMouseOver(id)
  else
    if cursors[id] then
      cursors[id][1] = cursor
    else
      cursors[id] = {cursor}
    end
    OnMouseOver(id)
  end
end


------------------------------------------------------------
--  function: twoStateButton
-- обработка кнопки с двумя состояниями.
-- пассивное состояние кнопки здесь не участвует (например, слито с фоном)
-- active - это наведение, ему предварительно нужно сделать SetAlfaValue(active,0.01) и OnMouseOver()
------------------------------------------------------------
function twoStateButton(sender,obj_id,attachedID,active)
  if sender == 1 then
    if obj_id == active then
      if STATE==0 then
        playeffect("btn_press")
      end;
      SetAlfaValue(active,0.01)
      return true
    end
  end
  if sender == 35 then
    if obj_id == active then
      if STATE==0 then
        playeffect("btn_on")
      end;
      SetAlfaValue(active,1)
    end
  end
  if sender == 39 then
    if obj_id == active then
      SetAlfaValue(active,0.01)
    end  
  end
end


------------------------------------------------------------
--  function: threeStateButton
-- обработка кнопки с тремя состояниями.
-- пассивное состояние кнопки здесь не участвует (например, слито с фоном)
-- active - это наведение, ему предварительно нужно сделать SetAlfaValue(active,0.01) и OnMouseOver()
-- pressed - это нажатие, ему предварительно нужно сделать set_visible_object(pressed,false)
-- нажатая должна быть сверху наведённой
------------------------------------------------------------
ACTIVE3 = nil
function threeStateButton(sender,obj_id,attachedID,active,pressed)
--  Write("threeStateButton("..tostring(sender)..","..tostring(obj_id)..","..tostring(attachedID)..","..tostring(active)..","..tostring(pressed)..")\n",true)
  if sender == 5 then
    local x1,y1 = GetCursorPos()
    local x,y = GetObjectPosition(active)
    local w,h = GetObjectSize(active)

    if x1 >= x and x1 <= x + w and y1 >= y and y1 <= y + h then
      set_visible_object(pressed,true)
      ACTIVE3 = pressed
    end
  end
  if sender == 1 or sender == 6 then
    set_visible_object(pressed,false)
    if ACTIVE3 and ACTIVE3 == pressed then
      ACTIVE3 = nil
      if STATE==0 then
        playeffect("btn_press")
      end;
      SetAlfaValue(active,0.01)
      return true
    end
  end
  if sender == 35 then
    if obj_id == active then
      if STATE==0 then
        playeffect("btn_on")
      end;    
      SetAlfaValue(obj_id,1)
    else
      ACTIVE3=nil
    end
  end
  if sender == 39 then
    if obj_id == active then
      SetAlfaValue(obj_id,0.01)
      ACTIVE3 = nil
    end
  end
end


------------------------------------------------------------
--  function: unBlock_Show_Cur
-- разблокировать курсор
-- я повсеместно вызываю эту функцию как callback
------------------------------------------------------------
function unBlock_Show_Cur()
  -- BlockCursor(false)
  Block_Show_Cur(false)
end






