--[[#######################################################################
#  File     :  /hook/lua/ui/game/avatars.lua
#  Author(s):  Ted Snook
#  Summary  :  In Game Avatar Icons
#  -----------------------------
#  Modif.by :  Manimal
#  Mod.Date :  18 novembre 2009
#  -----------------------------
#  Revis.by :  Manimal
#  Rev.Date :  02 mars 2010
#  Rev.Date :  28 janvier 2011 14:28 -> Ajout Avatar des ACUs SCUs CEs et QGs
#  Rev.Date :  06 février 2011 08:17 -> Ajout Avatar des Portails et des Labos
#  Rev.Date :  27 février 2011 00:19 -> Mises au point.
#  Rev.Date :  09 mars 2011 16:47 -> Dernier réglage.
#  Rev.Date :  31 juillet 2011 -> Nouveau Panneau d'Avatars pour Labos.
#  Rev.Date :  01 aout 2011 -> Debug.
#  Rev.Date :  02 aout 2011 -> Debug.
#  Rev.Date :  08 aout 2011 -> Correction mineure.
#  Rev.Date :  15 aout 2011 -> Correction mineure (import Factions).
#  ----------------------------------------------------------
#  Copyright © 2005 Gas Powered Games, Inc.  All rights reserved.
#######################################################################]]--

# Nbr Lignes Original = 777

#############################################################################################
# NOTES DE MANIMAL :
# ==================
# GPG a DÉFINI LES <IDLE TEXTURES> DANS faction.lua => PAS DU TOUT GÉNÉRIQUE !!!
# LES TEXTURES PAR DÉFAUT DOIENT ÊTRE LISTÉES DANS UNE LUA DÉDIÉE ! (DefaultTextures.lua)
# DANS LE CAS DES AVATARS :
# GPG DEVAIT CRÉER AFFICHAGE DYNAMIQUE DES ICONES D'UNITÉS DE [ /textures ] !
#############################################################################################

#############################################################################################
# À FAIRE :
# ~~~~~~~~~
# ¤ REVOIR TOUTES LES FONCTIONS IDLETAB : 
#   => SUPPRIMER AFFICHAGE DES ICÔNES PRÉDÉFINIES PAR faction.lua
#   => CRÉER AFFICHAGE DYNAMIQUE DES ICONES D'UNITÉS DE [ /textures ] !
# ¤ SÉPARER CHAQUE HÉROS COMME AVEC DES UNITÉS DIFFÉRENTES !
# ¤ SÉPARER CHAQUE TYPE DE SUBCOMM (INGÉ, GUERRIER)
# ¤ REVOIR RAFRAICHISSEMENT ICONES TECH DES LABOS APRÈS LEURS UPGRADES (COMPLIQUÉ !)
# 
# ¤ CONTROLER :
# ~~~~~~~~~~~~~
# TROUVÉ DANS UEL0301 'REBUILDER' : RÉUTILISABLE SUR UBC POUR RENCONSTRUCTION DES UNIQUES ?
#############################################################################################


# ==================================================================================
# AJOUT PAR MANIMAL :  MANIMAL's MOD LOCATOR
# ==================================================================================
local Game = import( '/lua/game.lua' )

# VARIABLE ''GLOBALE'' ( par Manimal )
local MyModPath = Game.MyModPath
# ==================================================================================


local UIUtil = import( '/lua/ui/uiutil.lua' )
--local LayoutHelpers = import( '/lua/maui/layouthelpers.lua' )
local Bitmap = import( '/lua/maui/bitmap.lua' ).Bitmap
local Button = import( '/lua/maui/button.lua' ).Button
local Group = import( '/lua/maui/group.lua' ).Group
local Checkbox = import( '/lua/maui/checkbox.lua' ).Checkbox
local StatusBar = import( '/lua/maui/statusbar.lua' ).StatusBar
local GameCommon = import( '/lua/ui/game/gamecommon.lua' )
local GameMain = import( '/lua/ui/game/gamemain.lua' )
local ToolTip = import( '/lua/ui/game/tooltip.lua' )
local TooltipInfo = import( '/lua/ui/help/tooltips.lua' ).Tooltips
local Prefs = import( '/lua/user/prefs.lua' )

--local Factions = import( '/lua/factions.lua' ).Factions
local Factions = import( MyModPath .. '/hook/lua/factions.lua' ).Factions

local LayoutHelpers = import( MyModPath .. '/hook/lua/maui/layouthelpers.lua' )

--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  MODIF PAR MANIMAL :
	#  POUR PRISE EN COMPTE DES NOUVEAUX AVATARS DU MOD :P
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

controls = {
    avatars = {},
    idleLabos      = false,
    idlePortails   = false,
    idleHeros      = false,
    idleQuantGates = false,
    idleSCUs       = false,
    idleFactories  = false,
    idleEngineers  = false,
}


local recievingBeatUpdate = false
local currentFaction = GetArmiesTable().armiesTable[GetFocusArmy()].faction
local expandedCheck = false
local currentIndex = 1


####  ####  ####  ####  ####  ####  ####

--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  AJOUTS PAR MANIMAL :
	#  NOUVEAUX AVATARS DU MOD : ACUs en trop, SCUs, CEs et QGs ( src = SupCivs )
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

local initialACU = false


####  ####  ####  ####  ####  ####  ####


function GetCommanders()
	local ArmyAvatars = GetArmyAvatars()
    if  ArmyAvatars == false  or  ArmyAvatars == nil  or  table.getn( ArmyAvatars ) <= 0  then  return false  end

    local ACU = EntityCategoryFilterDown( categories.COMMAND, ArmyAvatars )
    if  ACU == false  or  ACU == nil  or  table.getn( ACU ) <= 0  then  return false  end

	return ACU
end


####  ####  ####  ####  ####  ####  ####


function GetIdleLabos()
	local idleLabos = GetIdleEngineers() or false  --# ASTUCE POUR RÉCUP LES LABOS
	if idleLabos == false  or  table.getn( idleLabos ) <= 0  then  return false  end

	idleLabos = EntityCategoryFilterDown( categories.LABO, idleLabos )
	if idleLabos == false  or  table.getn( idleLabos ) <= 0  then  return false  end

	return idleLabos
end


function GetIdlePortails()
	local idlePortails = GetIdleFactories() or false
	if idlePortails == false  or  table.getn( idlePortails ) <= 0  then  return false  end

	idlePortails = EntityCategoryFilterDown( categories.HEROPORTAL, idlePortails )
	if idlePortails == false  or  table.getn( idlePortails ) <= 0  then  return false  end

	return idlePortails
end


function GetSecondaryCommanders()
	local secACU = GetArmyAvatars() or false
	if secACU == false  or  table.getn( secACU ) <= 0  then  return false  end

	secACU = EntityCategoryFilterDown( categories.COMMAND, secACU )
	if secACU == false  or  table.getn( secACU ) <= 0  then  return false  end

	local secondaryACU = {}
	for i, unit in secACU do
		--# unit:IsBeingBuilt() PROVOQUE UNE ERREUR => warning: Error running '/lua/ui/game/gamemain.lua:OnBeat': ...ed alliance\gamedata\lua.scd\lua\ui\game\avatars.lua(895): attempt to call method `IsBeingBuilt' (a nil value)
		if  not unit:IsDead()  and  initialACU ~= false  and  unit:GetEntityId() ~= initialACU  then
			table.insert( secondaryACU, unit )
		end
	end
	if table.getn( secondaryACU ) <= 0  then  return false  end

	return secondaryACU
end


function GetIdleQuantumGates()
	local idleQuantumGates = GetIdleFactories() or false
	if idleQuantumGates == false  or  table.getn( idleQuantumGates ) <= 0  then  return false  end

	idleQuantumGates = EntityCategoryFilterOut( categories.HEROPORTAL, idleQuantumGates )
	if idleQuantumGates == false  or  table.getn( idleQuantumGates ) <= 0  then  return false  end

	idleQuantumGates = EntityCategoryFilterDown( categories.GATE, idleQuantumGates )
	if idleQuantumGates == false  or  table.getn( idleQuantumGates ) <= 0  then  return false  end

	return idleQuantumGates
end


function GetIdleSubCommanders()
	local idleSubCommanders = GetIdleEngineers() or false
	if idleSubCommanders == false  or  table.getn( idleSubCommanders ) <= 0  then  return false  end

	idleSubCommanders = EntityCategoryFilterDown( categories.SUBCOMMANDER, idleSubCommanders )
	if idleSubCommanders == false  or  table.getn( idleSubCommanders ) <= 0  then  return false  end

	return idleSubCommanders
end


####  ####  ####  ####  ####  ####  ####


function GetIdleFactoriesONLY()
	local idleFactories = GetIdleFactories() or false
	if idleFactories == false  or  table.getn( idleFactories ) <= 0  then  return false  end

	local exclus = categories.GATE + categories.HEROPORTAL
	idleFactories = EntityCategoryFilterOut( exclus, idleFactories )
	if idleFactories == false  or  table.getn( idleFactories ) <= 0  then  return false  end

	return idleFactories
end


function GetIdleEngineersONLY()
	local idleEngineers = GetIdleEngineers() or false
	if idleEngineers == false  or  table.getn( idleEngineers ) <= 0  then  return false  end

	local exclus = categories.COMMAND + categories.SUBCOMMANDER + categories.LABO
	idleEngineers = EntityCategoryFilterOut( exclus, idleEngineers )
	if idleEngineers == false  or  table.getn( idleEngineers ) <= 0  then  return false  end

	return idleEngineers
end


####  ####  ####  ####  ####  ####  ####


--# GetEngineerGeneric() UTILISÉ DANS /lua/keymap/keyactions.lua
function GetEngineerGeneric()
    local idleEngineers = GetIdleEngineers()
    if idleEngineers then
        local selEngineer = idleEngineers[currentIndex] or idleEngineers[1]
        currentIndex = currentIndex + 1
        if currentIndex > table.getn( idleEngineers ) then
            currentIndex = 1
        end
        UISelectAndZoomTo( selEngineer )
    end
end



function CreateAvatarUI( parent )
    controls.parent = parent
    
    controls.avatarGroup = Group( controls.parent )
    controls.avatarGroup.Depth:Set( 100 )
    
    controls.bgTop = Bitmap( controls.avatarGroup )
    controls.bgBottom = Bitmap( controls.avatarGroup )
    controls.bgStretch = Bitmap( controls.avatarGroup )
    controls.collapseArrow = Checkbox( controls.parent )
    controls.collapseArrow.OnCheck = function( self, checked )
        ToggleAvatars( checked )
    end
    ToolTip.AddCheckboxTooltip( controls.collapseArrow, 'avatars_collapse' )
    
    controls.avatarGroup:DisableHitTest()
    controls.bgTop:DisableHitTest()
    controls.bgBottom:DisableHitTest()
    controls.bgStretch:DisableHitTest()
    
    SetLayout()
    
    if GetFocusArmy() != -1 then
        recievingBeatUpdate = true
        GameMain.AddBeatFunction( AvatarUpdate )
    end
end


function ToggleAvatars( checked )
    # disable when in Screen Capture mode
    if import( '/lua/ui/game/gamemain.lua' ).gameUIHidden then
        return
    end
    
    if UIUtil.GetAnimationPrefs() then
        if controls.avatarGroup:IsHidden() then
            PlaySound( Sound( {Cue = "UI_Score_Window_Open", Bank = "Interface"} ) )
            controls.collapseArrow:SetCheck( false, true )
            controls.avatarGroup:Show()
            controls.avatarGroup:SetNeedsFrameUpdate( true )
            controls.avatarGroup.OnFrame = function( self, delta )
                local newRight = self.Right() - ( 1000*delta )
                if newRight < controls.parent.Right() - 0 then
                    newRight = function() return controls.parent.Right() - 0 end
                    self:SetNeedsFrameUpdate( false )
                end
                self.Right:Set( newRight )
            end
        else
            PlaySound( Sound( {Cue = "UI_Score_Window_Close", Bank = "Interface"} ) )
            controls.avatarGroup:SetNeedsFrameUpdate( true )
            controls.avatarGroup.OnFrame = function( self, delta )
                local newRight = self.Right() + ( 1000*delta )
                if newRight > controls.parent.Right() + self.Width() then
                    newRight = function() return controls.parent.Right() + self.Width() end
                    self:Hide()
                    self:SetNeedsFrameUpdate( false )
                end
                self.Right:Set( newRight )
            end
            controls.collapseArrow:SetCheck( true, true )
        end
    else
        if checked or not controls.avatarGroup:IsHidden() then
            controls.avatarGroup:Hide()
            controls.collapseArrow:SetCheck( true, true )
        else
            controls.avatarGroup:Show()
            controls.collapseArrow:SetCheck( false, true )
        end
    end
end


function SetLayout()
    import( UIUtil.GetLayoutFilename( 'avatars' ) ).SetLayout()
end



--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  MODIF PAR MANIMAL :
	#  POUR PRISE EN COMPTE DES NOUVELLES UNITÉS DU MOD
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function CreateAvatar( unit )
    local bg = Bitmap( controls.avatarGroup, UIUtil.SkinnableFile( '/game/avatar/avatar_bmp.dds' ) )
    bg.ID = unit:GetEntityId()
    bg.Blueprint = unit:GetBlueprint()
    bg.tooltipKey = 'avatar_Avatar_ACU'
    
    bg.units = { unit }
    
    bg.icon = Bitmap( bg )
    LayoutHelpers.AtLeftTopIn( bg.icon, bg, 5, 5 )

	if  DiskGetFileInfo( '/textures/ui/common/icons/units/'..bg.Blueprint.BlueprintId..'_icon.dds' )  then
		bg.icon:SetTexture( '/textures/ui/common/icons/units/'..bg.Blueprint.BlueprintId..'_icon.dds' )
	elseif  DiskGetFileInfo( MyModPath .. '/textures/ui/common/icons/units/'..bg.Blueprint.BlueprintId..'_icon.dds' )  then
		bg.icon:SetTexture( MyModPath .. '/textures/ui/common/icons/units/'..bg.Blueprint.BlueprintId..'_icon.dds' )
	else
		bg.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
	end

	bg.icon.Height:Set( 44 )
    bg.icon.Width:Set( 44 )
    bg.icon:DisableHitTest()
    
    bg.healthbar = StatusBar( bg, 0, 1, false, false,
        UIUtil.SkinnableFile( '/game/avatar/health-bar-back_bmp.dds' ),
        UIUtil.SkinnableFile( '/game/avatar/health-bar-green.dds' ),
        true, "avatar RO Health Status Bar" )
    bg.healthbar.Left:Set( function() return bg.Left() + 8 end )
    bg.healthbar.Right:Set( function() return bg.Right() - 14 end )
    bg.healthbar.Bottom:Set( function() return bg.Bottom() - 5 end )
    bg.healthbar.Top:Set( function() return bg.healthbar.Bottom() - 10 end )
    bg.healthbar.Height:Set( function() return bg.healthbar.Bottom() - bg.healthbar.Top() end )
    bg.healthbar.Width:Set( function() return bg.healthbar.Right() - bg.healthbar.Left() end )
    bg.healthbar:DisableHitTest( true )
    
    
    bg.curIndex = 1
    bg.HandleEvent = ClickFunc
    bg.idleAnnounced = true
    bg.lastAlert = 0
    
    bg.Update = function( self )
        if bg.units[1]:IsIdle() and not bg.idle then
            if not bg.idle then
                bg.idle = Bitmap( bg.icon, UIUtil.SkinnableFile( '/game/idle_mini_icon/idle_icon.dds' ) )
                LayoutHelpers.AtLeftTopIn( bg.idle, bg.icon, -2, -2 )
                bg.idle:DisableHitTest()
                bg.idle.cycles = 0
                bg.idle.dir = 1
                bg.idle:SetNeedsFrameUpdate( true )
                bg.idle:SetAlpha( 0 )
                bg.idle.OnFrame = function( self, delta )
                    local newAlpha = self:GetAlpha() + ( delta * 3 * self.dir )
                    if newAlpha > 1 then
                        newAlpha = 1
                        self.dir = -1
                        self.cycles = self.cycles + 1
                        if self.cycles >= 5 then
                            self:SetNeedsFrameUpdate( false )
                        end
                    elseif newAlpha < 0 then
                        newAlpha = 0
                        self.dir = 1
                    end
                    self:SetAlpha( newAlpha )
                end
            end
        elseif not bg.units[1]:IsIdle() then
            if bg.idle then
                bg.idle:Destroy()
                bg.idle = false
            end
        end
        local tempPrevHealth = bg.healthbar._value()
        local tempHealth = self.units[1]:GetHealth()
        bg.healthbar:SetRange( 0, self.units[1]:GetMaxHealth() )
        bg.healthbar:SetValue( tempHealth )
        if tempPrevHealth != tempHealth then
            SetHealthbarColor( bg.healthbar, self.units[1]:GetHealth() / self.units[1]:GetMaxHealth() )
        end
    end
    
    return bg
end



function SetHealthbarColor( control, value )
    if  value > .75  then
        control._bar:SetTexture( UIUtil.SkinnableFile( '/game/avatar/health-bar-green.dds' ) )
    elseif  value > .25  then
        control._bar:SetTexture( UIUtil.SkinnableFile( '/game/avatar/health-bar-yellow.dds' ) )
    elseif  value > 0  then
        control._bar:SetTexture( UIUtil.SkinnableFile( '/game/avatar/health-bar-red.dds' ) )
    end
end



--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  MODIF PAR MANIMAL :
	#  POUR PRISE EN COMPTE DES NOUVEAUX AVATARS DU MOD
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function CreateIdleTab( unitData, id, expandFunc )

    local bg = Bitmap( controls.avatarGroup, UIUtil.SkinnableFile( '/game/avatar/avatar-s-e-f_bmp.dds' ) )
    bg.id = id
    bg.tooltipKey = 'mfd_idle_'..id

    bg.allunits = unitData
    bg.units = unitData

    bg.icon = Bitmap( bg )
    LayoutHelpers.AtLeftTopIn( bg.icon, bg, 7, 8 )
    bg.icon:SetSolidColor( '00000000' )
    bg.icon.Height:Set( 34 )
    bg.icon.Width:Set( 34 )
    bg.icon:DisableHitTest()

    bg.count = UIUtil.CreateText( bg.icon, '', 18, UIUtil.bodyFont )
    bg.count:DisableHitTest()
    bg.count:SetDropShadow( true )
    LayoutHelpers.AtBottomIn( bg.count, bg.icon )
    LayoutHelpers.AtRightIn( bg.count, bg.icon )

	--# FLÈCHE CLIQUABLE EXPAND !
	if  expandFunc  and  expandFunc ~= nil  then --# AJOUTÉ TEST POUR ZAPPER LA FLECHE CLIQUABLE SI BESOIN
		bg.expandCheck = Checkbox( bg,
			UIUtil.SkinnableFile( '/game/avatar-arrow_btn/tab-open_btn_up.dds' ),
			UIUtil.SkinnableFile( '/game/avatar-arrow_btn/tab-close_btn_up.dds' ),
			UIUtil.SkinnableFile( '/game/avatar-arrow_btn/tab-open_btn_over.dds' ),
			UIUtil.SkinnableFile( '/game/avatar-arrow_btn/tab-close_btn_over.dds' ),
			UIUtil.SkinnableFile( '/game/avatar-arrow_btn/tab-open_btn_dis.dds' ),
			UIUtil.SkinnableFile( '/game/avatar-arrow_btn/tab-close_btn_dis.dds' ) )
		bg.expandCheck.Right:Set( function()  return bg.Left() + 4  end )
		LayoutHelpers.AtVerticalCenterIn( bg.expandCheck, bg )

		bg.expandCheck.OnCheck = function( self, checked )
			if  checked  then
				if  expandedCheck  and  expandedCheck != bg.id  and  GetCheck( expandedCheck )  then
					GetCheck( expandedCheck ):SetCheck( false )
				end
				expandedCheck = bg.id
				self.expandList = expandFunc( self, bg.units )
			else
				expandedCheck = false
				if self.expandList then
					self.expandList:Destroy()
					self.expandList = nil
				end
			end
		end
	else
		bg.expandCheck = nil --# ZAPPER LA FLECHE CLIQUABLE + LA LISTE SI BESOIN
	end
    bg.curIndex = 1
    bg.HandleEvent = ClickFunc

    bg.Update = function( self, units )
        self.allunits = units
        self.units = {}

		--#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		--# AJOUTÉ PAR MANIMAL POUR AFFICHAGE DES LABOS DE RECHERCHE SEULS
		--#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        if self.id == 'labo' then

            local categoryTable = { 'LAND', 'AIR', 'NAVAL' }

            local sortedLabos = {}
            for iC, curCat in categoryTable do
                sortedLabos[iC] = {}
				local cat = categories[curCat] * categories.LABO
                sortedLabos[iC][3] = EntityCategoryFilterDown( categories.TECH3 * cat, self.allunits )
                sortedLabos[iC][2] = EntityCategoryFilterDown( categories.TECH2 * cat, self.allunits )
                sortedLabos[iC][1] = EntityCategoryFilterDown( categories.TECH1 * cat, self.allunits )
            end

			local iC = table.getn( categoryTable )

			local keyToIcon = { 'T1', 'T2', 'T3' }
			local dernTech = table.getn( keyToIcon )  --# ORIGINAL local i = table.getn( sortedUnits )

            local needIcon = true
            while iC > 0 do
                for  iT = 1, dernTech  do
					if table.getn( sortedLabos[iC][iT] ) > 0 then
						if needIcon then
							local iCat = categoryTable[iC]
							local iIcone = keyToIcon[iT]
							local IdleLaboTex = Factions[currentFaction].IdleLaboTextures[iCat][iIcone]
							if  IdleLaboTex  and  DiskGetFileInfo( '/textures/ui/common'..IdleLaboTex )  then
								self.icon:SetTexture( '/textures/ui/common'..IdleLaboTex )
							elseif  IdleLaboTex  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..IdleLaboTex )  then
								self.icon:SetTexture( MyModPath .. '/textures/ui/common'..IdleLaboTex )
							else
								self.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
							end
							needIcon = false
						end
						for _, unit in sortedLabos[iC][iT] do
							table.insert( self.units, unit )
						end
					end
				end
                iC = iC - 1
            end  --# END WHILE

		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		# AJOUTÉ PAR MANIMAL POUR AFFICHAGE DES PORTAILS HÉROS
		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        elseif self.id == 'heroportal' then

			local sortedPortals = {}
			sortedPortals[1] = EntityCategoryFilterDown( categories.TECH1 * categories.HEROPORTAL, self.allunits )

            local keyToIcon = { 'T1' }

            local i = table.getn( sortedPortals )
            local needIcon = true
            while  i > 0  do
                if table.getn( sortedPortals[i] ) > 0 then
                    if needIcon then
                        local IdlePortailTex = Factions[currentFaction].IdlePortailTextures[keyToIcon[i]]
                        if IdlePortailTex  and  DiskGetFileInfo( '/textures/ui/common'..IdlePortailTex )  then
                            self.icon:SetTexture( '/textures/ui/common'..IdlePortailTex )
                        elseif IdlePortailTex  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..IdlePortailTex )  then
                            self.icon:SetTexture( MyModPath .. '/textures/ui/common'..IdlePortailTex )
                        else
                            elf.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
                        end
                        needIcon = false
                    end
                    for _, unit in sortedPortals[i] do
                        table.insert( self.units, unit )
                    end
                end
                i = i - 1
            end

		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		# AJOUTÉ PAR MANIMAL POUR AFFICHAGE DES HÉROS & DES AUTRES COMMANDEURS.  GÈRE NBR ACU > 1 !!!
		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# => À FAIRE : SÉPARER CHAQUE HÉROS COMME AVEC DES UNITÉS DIFFÉRENTES !

        elseif self.id == 'hero' then

			local sortedHeros = {}
			sortedHeros[2] = EntityCategoryFilterDown( categories.TECH1 * categories.HERO, self.allunits )
			sortedHeros[1] = EntityCategoryFilterDown( categories.COMMAND - categories.HERO, self.allunits )

			--# PREMIER INDEX POUR COMMANDEURS, INDEX + FORT POUR HÉROS
            local indexToIcon = {  '1',  '1' }
            local keyToIcon   = { 'ACU', 'T1' }

            local i = table.getn( sortedHeros )
            local needIcon = true
            while  i > 0  do
                if table.getn( sortedHeros[i] ) > 0 then
                    if needIcon then
						local IdleHeroTex = Factions[currentFaction].IdleACUTextures[keyToIcon[i]]
						if IdleHeroTex  and  DiskGetFileInfo( '/textures/ui/common'..IdleHeroTex )  then
							self.icon:SetTexture( '/textures/ui/common'..IdleHeroTex )
						elseif IdleHeroTex  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..IdleHeroTex )  then
							self.icon:SetTexture( MyModPath .. '/textures/ui/common'..IdleHeroTex )
						else
							self.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
						end
                        needIcon = false
                    end
                    for _, unit in sortedHeros[i] do
                        table.insert( self.units, unit )
                    end
                end
                i = i - 1
            end

		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		# AJOUTÉ PAR MANIMAL POUR AFFICHAGE DES PORTES QUANTIQUES SEULES
		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        elseif self.id == 'quantumgate' then

			local sortedGates = {}
			--sortedGates[3] = EntityCategoryFilterDown( categories.TECH3 * categories.GATE, self.allunits )
			--sortedGates[2] = EntityCategoryFilterDown( categories.TECH2 * categories.GATE, self.allunits )
			--sortedGates[1] = EntityCategoryFilterDown( categories.TECH1 * categories.GATE, self.allunits )

           --local keyToIcon = { 'T1', 'T2', 'T3' } -- 'T1' ET 'T2' POUR USAGE FUTUR

			sortedGates[1] = EntityCategoryFilterDown( categories.TECH3 * categories.GATE, self.allunits )

            local keyToIcon = { 'T3' }

            local i = table.getn( sortedGates )
            local needIcon = true
            while  i > 0  do
                if table.getn( sortedGates[i] ) > 0 then
                    if needIcon then
						local IdleQuGateTex = Factions[currentFaction].IdleQuGateTextures[keyToIcon[i]]
                        if IdleQuGateTex  and  DiskGetFileInfo( '/textures/ui/common'..IdleQuGateTex )  then
                            self.icon:SetTexture( '/textures/ui/common'..IdleQuGateTex )
                        elseif IdleQuGateTex  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..IdleQuGateTex )  then
                            self.icon:SetTexture( MyModPath .. '/textures/ui/common'..IdleQuGateTex )
                        else
                            elf.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
                        end
                        needIcon = false
                    end
                    for _, unit in sortedGates[i] do
                        table.insert( self.units, unit )
                    end
                end
                i = i - 1
            end

		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		# AJOUTÉ PAR MANIMAL POUR AFFICHAGE DES SOUS-COMMANDEURS
		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

		elseif self.id == 'subcommander' then

            local sortedUnits = {}
            sortedUnits[1] = EntityCategoryFilterDown( categories.TECH3 * categories.SUBCOMMANDER, self.allunits )

            local keyToIcon = { 'T3' }
            
            local i = table.getn( sortedUnits )
            local needIcon = true
            while i > 0 do
                if table.getn( sortedUnits[i] ) > 0 then
                    if needIcon then
						local IdleSCUTex = Factions[currentFaction].IdleSCUTextures[keyToIcon[i]]
						if  IdleSCUTex  and  DiskGetFileInfo( '/textures/ui/common'..IdleSCUTex )  then
							self.icon:SetTexture( '/textures/ui/common'..IdleSCUTex )
						elseif  IdleSCUTex  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..IdleSCUTex )  then
							self.icon:SetTexture( MyModPath .. '/textures/ui/common'..IdleSCUTex )
						else
							self.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
						end --# END IF Factions
                        needIcon = false
                    end
                    for _, unit in sortedUnits[i] do
                        table.insert( self.units, unit )
                    end
                end
                i = i - 1
            end

		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		# MODIFIÉ PAR MANIMAL POUR AFFICHAGE DES 4 TYPES D'USINES
		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        elseif self.id == 'factory' then

			--# AJOUT DU NOUVEAU TYPE D'USINE
			local categoryTable = { 'LAND', 'AIR', 'NAVAL', 'SUBMERSIBLE' }

            local sortedFactories = {}
            for iC, cat in categoryTable do
                sortedFactories[iC] = {}
				local curCat = categories[cat] * categories.FACTORY
				if  cat == 'NAVAL'  then
					curCat = curCat - categories.SUBMERSIBLE
				end
				sortedFactories[iC][3] = EntityCategoryFilterDown( categories.TECH3 * curCat, self.allunits )
				sortedFactories[iC][2] = EntityCategoryFilterDown( categories.TECH2 * curCat, self.allunits )
				sortedFactories[iC][1] = EntityCategoryFilterDown( categories.TECH1 * curCat, self.allunits )
            end

			local dernCat = table.getn( categoryTable )

			local keyToIcon = { 'T1', 'T2', 'T3' }
			local iT = table.getn( keyToIcon )

            local needIcon = true
            while iT > 0 do
                for  curCat = 1, dernCat  do
                    if table.getn( sortedFactories[curCat][iT] ) > 0 then
                        if needIcon then
							local laCat = categoryTable[curCat]
							local iIcone = keyToIcon[iT]
                            local IdleFactoryTex = Factions[currentFaction].IdleFactoryTextures[laCat][iIcone]
                            if  IdleFactoryTex  and  DiskGetFileInfo( '/textures/ui/common'..IdleFactoryTex )  then
                            	self.icon:SetTexture( '/textures/ui/common'..IdleFactoryTex )
							elseif  IdleFactoryTex  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..IdleFactoryTex )  then
								self.icon:SetTexture( MyModPath .. '/textures/ui/common'..IdleFactoryTex )
                            else
                                self.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
                            end
                            needIcon = false
                        end
                        for _, unit in sortedFactories[curCat][iT] do
                            table.insert( self.units, unit )
                        end
                    end
                end
                iT = iT - 1
            end

		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		# MODIFIÉ PAR MANIMAL POUR AFFICHAGE DES INGÉNIEURS SEULS
		#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

		elseif self.id == 'engineer' then

			--# AJOUT DZE 3 NOUVEAUX TYPES D'INGÉS
			local categoryTable = { 'LAND', 'AIR', 'NAVAL' }

			local sortedUnits = {}
			for iC, cat in categoryTable do
				sortedUnits[iC] = {}
				sortedUnits[iC][4] = EntityCategoryFilterDown( categories.TECH3 * categories[cat], self.allunits )
				sortedUnits[iC][3] = EntityCategoryFilterDown( categories.TECH2 * categories[cat] * categories.FIELDENGINEER, self.allunits )
				sortedUnits[iC][2] = EntityCategoryFilterDown( ( categories.TECH2 * categories[cat] ) - categories.FIELDENGINEER, self.allunits )
				sortedUnits[iC][1] = EntityCategoryFilterDown( categories.TECH1 * categories[cat], self.allunits )
			end

			local dernCat = table.getn( categoryTable )

			--# local indexToIcon = {  '1',  '2',   '2',  '3' }
			local keyToIcon = { 'T1', 'T2', 'T2F', 'T3' }

			local iT = table.getn( keyToIcon )  --# ORIGINAL local i = table.getn( sortedUnits )
            local needIcon = true
            while iT > 0 do
                for  curCat = 1, dernCat  do
					if table.getn( sortedUnits[curCat][iT] ) > 0 then
                        if needIcon then
							local laCat = categoryTable[curCat]
							local iIcone = keyToIcon[iT]
							local IdleEngTex = Factions[currentFaction].IdleEngTextures[laCat][iIcone]
							if  IdleEngTex  and  DiskGetFileInfo( '/textures/ui/common'..IdleEngTex )  then
								self.icon:SetTexture( '/textures/ui/common'..IdleEngTex )
							elseif  IdleEngTex  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..IdleEngTex )  then
								self.icon:SetTexture( MyModPath .. '/textures/ui/common'..IdleEngTex )
							else
								--# ICONE PAR DÉFAUT = INGÉ TECH 2 <=> PAS DU TOUT LOGIQUE !!!
								--self.icon:SetTexture(  UIUtil.UIFile( Factions[currentFaction].IdleEngTextures[laCat]['T2'] )  )
								self.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
							end  --# END IF Factions
                            needIcon = false
                        end  --# END IF needIcon
                        for _, unit in sortedUnits[curCat][iT] do
                            table.insert( self.units, unit )
                        end
                    end  --# END IF table.getn
                end  --# END FOR 
                iT = iT - 1
            end  --# END WHILE


        end  --# END IF self.id
        self.count:SetText( table.getsize( self.allunits ) )
        
        if self.expandCheck.expandList then
            self.expandCheck.expandList:Update( self.allunits )
        end
    end
    
    return bg
end



--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  MODIF PAR MANIMAL :
	#  POUR PRISE EN COMPTE DES NOUVEAUX AVATARS DU MOD ( PORTAILS ET LABOS )
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function GetCheck( id )
    if id == 'labo' and controls.idleLabos then
        return controls.idleLabos.expandCheck
    --elseif id == 'heroportal' and controls.idlePortails then
    --    return controls.idlePortails.expandCheck
    elseif id == 'hero' and controls.idleHeros then
        return controls.idleHeros.expandCheck
    elseif id == 'quantumgate' and controls.idleQuantGates then
        return controls.idleQuantGates.expandCheck
    elseif id == 'subcommander' and controls.idleSCUs then
        return controls.idleSCUs.expandCheck
    elseif id == 'factory' and controls.idleFactories then
        return controls.idleFactories.expandCheck
    elseif id == 'engineer' and controls.idleEngineers then
        return controls.idleEngineers.expandCheck
    end
end


function ClickFunc( self, event )
    if event.Type == 'MouseEnter' then
        if self.tooltipKey and not self.tooltip then
            self.tooltip = ToolTip.CreateExtendedToolTip( self, TooltipInfo[self.tooltipKey].title, TooltipInfo[self.tooltipKey].description )
            LayoutHelpers.LeftOf( self.tooltip, self )
            self.tooltip:SetAlpha( 0, true )
            self.tooltip:SetNeedsFrameUpdate( true )
            self.tooltip.OnFrame = function( self, deltaTime )
                self:SetAlpha( math.min( self:GetAlpha() + ( deltaTime * 3 ), 1 ), true )
                if self:GetAlpha() == 1 then
                    self:SetNeedsFrameUpdate( false )
                end
            end
        end
    elseif event.Type == 'MouseExit' then
        if self.tooltip then
            self.tooltip:Destroy()
            self.tooltip = nil
        end
        self.curIndex = 1
    elseif event.Type == 'ButtonPress' then
        if self.units then
            if not self.units[self.curIndex] then
                self.curIndex = 1
            end
            if event.Modifiers.Left then
                local selectUnits = {self.units[self.curIndex]}
                if event.Modifiers.Shift then
                    selectUnits = GetSelectedUnits() or {}
                    table.insert( selectUnits, self.units[self.curIndex] )
                end
                SelectUnits( selectUnits )
            elseif event.Modifiers.Right then
                if event.Modifiers.Shift then
                    local selection = GetSelectedUnits() or {}
                    table.insert( selection, self.units[self.curIndex] )
                    UISelectAndZoomTo( self.units[self.curIndex] )
                    SelectUnits( selection )
                else
                    UISelectAndZoomTo( self.units[self.curIndex] )
                end
            end
            self.curIndex = self.curIndex + 1
        end
        return true
    elseif event.Type == 'ButtonDClick' then
        if self.units then
            if not self.units[self.curIndex] then
                self.curIndex = 1
            end
            if event.Modifiers.Left then
                local selectUnits = self.units
                if event.Modifiers.Shift then
                    selectUnits = GetSelectedUnits() or {}
                    for _, unit in self.units do
                        table.insert( selectUnits, unit )
                    end
                end
                SelectUnits( selectUnits )
            elseif event.Modifiers.Right then
                if event.Modifiers.Shift then
                    local selection = GetSelectedUnits() or {}
                    for _, unit in self.units do
                        table.insert( selection, unit )
                    end
                    UISelectAndZoomTo( self.units[self.curIndex] )
                    SelectUnits( selection )
                else
                    UISelectAndZoomTo( self.units[self.curIndex] )
                    SelectUnits( self.units )
                end
            end
            self.curIndex = self.curIndex + 1
        end
        return true
    end
end



--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  AJOUT PAR MANIMAL :
	#  NOUVEL AVATAR ET NOUVEL ONGLET POUR LES LABORATOIRES
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function CreateIdleLabosList( parent, units )  --# GROUP
    local bg = Bitmap( parent, UIUtil.SkinnableFile('/game/avatar-labs-panel/labs-panel_bmp.dds') )
    
    bg.Right:Set( function() return parent.Left() - 9 end )
    bg.Top:Set( function() return math.max(controls.avatarGroup.Top()+10, (parent.Top() + (parent.Height() / 2)) - (bg.Height() / 2)) end )
    
    local connector = Bitmap( bg, UIUtil.SkinnableFile('/game/avatar-labs-panel/bracket_bmp.dds') )
    LayoutHelpers.AtVerticalCenterIn(connector, parent)
    connector.Right:Set( function() return parent.Left() + 7 end )
    
    bg:DisableHitTest( true )
    
    bg.icons = {}
    
    local iconData = { 'LAND', 'AIR', 'NAVAL' }
    
	local idleTextures = Factions[currentFaction].IdleLaboTextures
    
    local prevIcon = false
    for type, category in iconData do
        local function CreateIcon( texture )
            local icon = Bitmap( bg )

			if  texture  and  texture != nil  and  DiskGetFileInfo( '/textures/ui/common'..texture )  then
				icon:SetTexture( '/textures/ui/common'..texture )
			elseif  texture  and  texture != nil  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..texture )  then
				icon:SetTexture( MyModPath .. '/textures/ui/common'..texture )
			else
				icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
			end

            icon.Height:Set( 40 )
            icon.Width:Set( 40 )
            
            icon.count = UIUtil.CreateText( icon, '', 20, UIUtil.bodyFont )
            icon.count:SetColor( 'ffffffff' )
            LayoutHelpers.AtRightIn( icon.count, icon )
            LayoutHelpers.AtBottomIn( icon.count, icon )
            
            icon.countBG = Bitmap( icon )
            icon.countBG:SetSolidColor( '77000000' )
            icon.countBG.Top:Set( function() return icon.count.Top() - 1 end )
            icon.countBG.Left:Set( function() return icon.count.Left() - 1 end )
            icon.countBG.Right:Set( function() return icon.count.Right() + 1 end )
            icon.countBG.Bottom:Set( function() return icon.count.Bottom() + 1 end )
            
            icon.countBG.Depth:Set( function() return icon.Depth() + 1 end )
            icon.count.Depth:Set( function() return icon.countBG.Depth() + 1 end )
            
            icon.curIndex = 1
            icon.HandleEvent = ClickFunc
            
            return icon
        end
        bg.icons[category] = {}
        local labo = bg.icons[category]
        for index = 1, 3 do
            local i = index
            labo[i] = CreateIcon( idleTextures[category][i] )
            if i == 1 then
                if prevIcon then
                    LayoutHelpers.RightOf( labo[i], prevIcon, 4 )
                else
                    LayoutHelpers.AtLeftIn( labo[i], bg, 38 )
                    LayoutHelpers.AtBottomIn( labo[i], bg, 10 )
                end
                prevIcon = labo[i]
            else
                LayoutHelpers.Above( labo[i], labo[i-1], 4 )
            end
        end
    end
    
    bg.Update = function(self, unitData)
        local lesLabos = { LAND = {}, AIR = {}, NAVAL = {} }
        for type, labos in lesLabos do
			local cat = categories[type] * categories.LABO
			labos[3] = EntityCategoryFilterDown( categories.TECH3 * cat, unitData )
			labos[2] = EntityCategoryFilterDown( categories.TECH2 * cat, unitData )
			labos[1] = EntityCategoryFilterDown( categories.TECH1 * cat, unitData )
        end
        for type, icons in bg.icons do
            for index=1,3 do
                local i = index
                if table.getn( lesLabos[type][i] ) > 0 then
                    bg.icons[type][i].units = lesLabos[type][i]
                    bg.icons[type][i]:SetAlpha(1)
                    bg.icons[type][i].countBG:Show()
                    bg.icons[type][i].count:SetText(  table.getn( lesLabos[type][i] )  )
                else
                    bg.icons[type][i]:SetAlpha(.2)
                    bg.icons[type][i].countBG:Hide()
                    bg.icons[type][i].count:SetText('')
                end
            end
        end
    end
    
    bg:Update( units )
    
    return bg
end


--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  AJOUT PAR MANIMAL :
	#  NOUVEL AVATAR ET NOUVEL ONGLET POUR LES PORTAILS HÉROS ( mod=SupCivs )
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function CreateIdlePortailsList( parent, units )  --# GROUP
    local group = Group( parent )
    
    local bgTop = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_t.dds' ) )
    local bgBottom = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_b.dds' ) )
    local bgStretch = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_m.dds' ) )
    
    group.Width:Set( bgTop.Width )
    group.Height:Set( 1 )
    
    bgTop.Bottom:Set( group.Top )
    bgBottom.Top:Set( group.Bottom )
    bgStretch.Top:Set( group.Top )
    bgStretch.Bottom:Set( group.Bottom )
    
    LayoutHelpers.AtHorizontalCenterIn( bgTop, group )
    LayoutHelpers.AtHorizontalCenterIn( bgBottom, group )
    LayoutHelpers.AtHorizontalCenterIn( bgStretch, group )
    
    group.connector = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/bracket_bmp.dds' ) )
    group.connector.Right:Set( function() return parent.Left() + 8 end )
    LayoutHelpers.AtVerticalCenterIn( group.connector, parent )
    
    LayoutHelpers.LeftOf( group, parent, 10 )
    group.Top:Set( function() return math.max( controls.avatarGroup.Top()+10, ( parent.Top() + ( parent.Height() / 2 ) ) - ( group.Height() / 2 ) ) end )
    
    group:DisableHitTest( true )
    
    group.icons = {}
    
    group.Update = function( self, unitData )

        local function CreateUnitEntry( techLevel, userUnits, icontexture )
            local entry = Group( self )
            
            entry.icon = Bitmap( entry )

			if  icontexture  and  icontexture != nil  and  DiskGetFileInfo( '/textures/ui/common'..icontexture ) then
                entry.icon:SetTexture( '/textures/ui/common'..icontexture )
			elseif  icontexture  and  icontexture != nil  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..icontexture )  then
				entry.icon:SetTexture( MyModPath .. '/textures/ui/common'..icontexture )
            else
                entry.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
            end

            entry.icon.Height:Set( 34 )
            entry.icon.Width:Set( 34 )
            LayoutHelpers.AtRightIn( entry.icon, entry, 22 )
            LayoutHelpers.AtVerticalCenterIn( entry.icon, entry )
            
            entry.iconBG = Bitmap( entry, UIUtil.SkinnableFile( '/game/avatar-factory-panel/avatar-s-e-f_bmp.dds' ) )
            LayoutHelpers.AtCenterIn( entry.iconBG, entry.icon )
            entry.iconBG.Depth:Set( function() return entry.icon.Depth() - 1 end )
            
            entry.techIcon = Bitmap( entry, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/tech-'..techLevel..'_bmp.dds' ) )
            LayoutHelpers.AtLeftIn( entry.techIcon, entry )
            LayoutHelpers.AtVerticalCenterIn( entry.techIcon, entry.icon )
            
            entry.count = UIUtil.CreateText( entry, '', 20, UIUtil.bodyFont )
            entry.count:SetColor( 'ffffffff' )
            entry.count:SetDropShadow( true )
            LayoutHelpers.AtRightIn( entry.count, entry.icon )
            LayoutHelpers.AtBottomIn( entry.count, entry.icon )
            
            entry.countBG = Bitmap( entry )
            entry.countBG:SetSolidColor( '77000000' )
            entry.countBG.Top:Set( function() return entry.count.Top() - 1 end )
            entry.countBG.Left:Set( function() return entry.count.Left() - 1 end )
            entry.countBG.Right:Set( function() return entry.count.Right() + 1 end )
            entry.countBG.Bottom:Set( function() return entry.count.Bottom() + 1 end )
            
            entry.countBG.Depth:Set( function() return entry.Depth() + 1 end )
            entry.count.Depth:Set( function() return entry.countBG.Depth() + 1 end )
            
            entry.Height:Set( function() return entry.iconBG.Height() end )
            entry.Width:Set( self.Width )
            
            entry.icon:DisableHitTest()
            entry.iconBG:DisableHitTest()
            entry.techIcon:DisableHitTest()
            entry.count:DisableHitTest()
            entry.countBG:DisableHitTest()
            
            entry.curIndex = 1
            entry.units = userUnits
            entry.HandleEvent = ClickFunc
            
            return entry
        end

        local portails = {}
        portails[1] = EntityCategoryFilterDown( categories.TECH1 * categories.HEROPORTAL, unitData )
        
        local indexToIcon = {  '1' }
        local keyToIcon   = { 'T1' }

        for index, units in portails do
            local i = index
            if not self.icons[i] then
                self.icons[i] = CreateUnitEntry( indexToIcon[i], units, Factions[currentFaction].IdlePortailTextures[keyToIcon[index]] )
                self.icons[i].priority = i
            end
            if table.getn( units ) > 0 and not self.icons[i]:IsHidden() then
                self.icons[i].units = units
                self.icons[i].count:SetText( table.getn( units ) )
                self.icons[i].count:Show()
                self.icons[i].countBG:Show()
                self.icons[i].icon:SetAlpha( 1 )
            else
                self.icons[i].units = {}
                self.icons[i].count:Hide()
                self.icons[i].countBG:Hide()
                self.icons[i].icon:SetAlpha( .2 )
            end
        end

        local prevGroup = false
        local groupHeight = 0
        for index, portailsGroup in portails do
            local i = index
            if not self.icons[i] then continue end
            if prevGroup then
                LayoutHelpers.Above( self.icons[i], prevGroup )
            else
                LayoutHelpers.AtLeftIn( self.icons[i], self, 7 )
                LayoutHelpers.AtBottomIn( self.icons[i], self, 2 )
            end
            groupHeight = groupHeight + self.icons[i].Height()
            prevGroup = self.icons[i]
        end
        group.Height:Set( groupHeight )
    end
    
    group:Update( units )
    
    return group
end


--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  AJOUTS PAR MANIMAL :
	#  NOUVEAUX AVATARS DU MOD : ACUs ( src=SupCivs )
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function CreateIdleHerosList( parent, units )  --# GROUP
    local group = Group( parent )
    
    local bgTop = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_t.dds' ) )
    local bgBottom = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_b.dds' ) )
    local bgStretch = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_m.dds' ) )
    
    group.Width:Set( bgTop.Width )
    group.Height:Set( 1 )
    
    bgTop.Bottom:Set( group.Top )
    bgBottom.Top:Set( group.Bottom )
    bgStretch.Top:Set( group.Top )
    bgStretch.Bottom:Set( group.Bottom )
    
    LayoutHelpers.AtHorizontalCenterIn( bgTop, group )
    LayoutHelpers.AtHorizontalCenterIn( bgBottom, group )
    LayoutHelpers.AtHorizontalCenterIn( bgStretch, group )
    
    group.connector = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/bracket_bmp.dds' ) )
    group.connector.Right:Set( function() return parent.Left() + 8 end )
    LayoutHelpers.AtVerticalCenterIn( group.connector, parent )
    
    LayoutHelpers.LeftOf( group, parent, 10 )
    group.Top:Set( function() return math.max( controls.avatarGroup.Top()+10, ( parent.Top() + ( parent.Height() / 2 ) ) - ( group.Height() / 2 ) ) end )
    
    group:DisableHitTest( true )
    
    group.icons = {}
    
    group.Update = function( self, unitData )

        local function CreateUnitEntry( techLevel, userUnits, icontexture )
            local entry = Group( self )
            
            entry.icon = Bitmap( entry )

            if  icontexture  and  icontexture != nil  and  DiskGetFileInfo( '/textures/ui/common'..icontexture ) then
                entry.icon:SetTexture( '/textures/ui/common'..icontexture )
			elseif  icontexture  and  icontexture != nil  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..icontexture )  then
				entry.icon:SetTexture( MyModPath .. '/textures/ui/common'..icontexture )
            else
                entry.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
            end

            entry.icon.Height:Set( 34 )
            entry.icon.Width:Set( 34 )
            LayoutHelpers.AtRightIn( entry.icon, entry, 22 )
            LayoutHelpers.AtVerticalCenterIn( entry.icon, entry )
            
            entry.iconBG = Bitmap( entry, UIUtil.SkinnableFile( '/game/avatar-factory-panel/avatar-s-e-f_bmp.dds' ) )
            LayoutHelpers.AtCenterIn( entry.iconBG, entry.icon )
            entry.iconBG.Depth:Set( function() return entry.icon.Depth() - 1 end )
            
            entry.techIcon = Bitmap( entry, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/tech-'..techLevel..'_bmp.dds' ) )
            LayoutHelpers.AtLeftIn( entry.techIcon, entry )
            LayoutHelpers.AtVerticalCenterIn( entry.techIcon, entry.icon )
            
            entry.count = UIUtil.CreateText( entry, '', 20, UIUtil.bodyFont )
            entry.count:SetColor( 'ffffffff' )
            entry.count:SetDropShadow( true )
            LayoutHelpers.AtRightIn( entry.count, entry.icon )
            LayoutHelpers.AtBottomIn( entry.count, entry.icon )
            
            entry.countBG = Bitmap( entry )
            entry.countBG:SetSolidColor( '77000000' )
            entry.countBG.Top:Set( function() return entry.count.Top() - 1 end )
            entry.countBG.Left:Set( function() return entry.count.Left() - 1 end )
            entry.countBG.Right:Set( function() return entry.count.Right() + 1 end )
            entry.countBG.Bottom:Set( function() return entry.count.Bottom() + 1 end )
            
            entry.countBG.Depth:Set( function() return entry.Depth() + 1 end )
            entry.count.Depth:Set( function() return entry.countBG.Depth() + 1 end )
            
            entry.Height:Set( function() return entry.iconBG.Height() end )
            entry.Width:Set( self.Width )
            
            entry.icon:DisableHitTest()
            entry.iconBG:DisableHitTest()
            entry.techIcon:DisableHitTest()
            entry.count:DisableHitTest()
            entry.countBG:DisableHitTest()
            
            entry.curIndex = 1
            entry.units = userUnits
            entry.HandleEvent = ClickFunc
            
            return entry
        end

        local Heros = {}
        Heros[2] = EntityCategoryFilterDown( categories.TECH1 * categories.HERO, unitData )
        Heros[1] = EntityCategoryFilterDown( categories.COMMAND - categories.HERO, unitData )
        
        local indexToIcon = {   '1',  '1' }
        local keyToIcon   = { 'ACU', 'T1' }

        for index, units in Heros do
            local i = index
			local iTech = indexToIcon[i] --# POUR LISTER TOUS HÉROS
			local iIcon = keyToIcon[i]   --# POUR LISTER TOUS UBCs
            if not self.icons[i] then
                --self.icons[i] = CreateUnitEntry( indexToIcon[i], units, Factions[currentFaction].IdleACUTextures[keyToIcon[index]] )
				### LISTER TOUS HÉROS SUR UNE SEULE COLONE !!!
                self.icons[i] = CreateUnitEntry( iTech, units, Factions[currentFaction].IdleACUTextures[iIcon] )
                self.icons[i].priority = i
            end
            if table.getn( units ) > 0 and not self.icons[i]:IsHidden() then
                self.icons[i].units = units
                self.icons[i].count:SetText( table.getn( units ) )
                self.icons[i].count:Show()
                self.icons[i].countBG:Show()
                self.icons[i].icon:SetAlpha( 1 )
            else
                self.icons[i].units = {}
                self.icons[i].count:Hide()
                self.icons[i].countBG:Hide()
                self.icons[i].icon:SetAlpha( .2 )
            end
        end

        local prevGroup = false
        local groupHeight = 0
        for index, acuGroup in Heros do
            local i = index
            if not self.icons[i] then continue end
            if prevGroup then
                LayoutHelpers.Above( self.icons[i], prevGroup )
            else
                LayoutHelpers.AtLeftIn( self.icons[i], self, 7 )
                LayoutHelpers.AtBottomIn( self.icons[i], self, 2 )
            end
            groupHeight = groupHeight + self.icons[i].Height()
            prevGroup = self.icons[i]
        end
        group.Height:Set( groupHeight )
    end
    
    group:Update( units )
    
    return group
end


--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  AJOUT PAR MANIMAL :
	#  NOUVEL AVATAR ET NOUVEL ONGLET POUR LES PORTES QUANTIQUES ( mod=SupCivs )
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function CreateIdleQuantumGatesList( parent, units )  --# GROUP
    local group = Group( parent )
    
    local bgTop = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_t.dds' ) )
    local bgBottom = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_b.dds' ) )
    local bgStretch = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_m.dds' ) )
    
    group.Width:Set( bgTop.Width )
    group.Height:Set( 1 )
    
    bgTop.Bottom:Set( group.Top )
    bgBottom.Top:Set( group.Bottom )
    bgStretch.Top:Set( group.Top )
    bgStretch.Bottom:Set( group.Bottom )
    
    LayoutHelpers.AtHorizontalCenterIn( bgTop, group )
    LayoutHelpers.AtHorizontalCenterIn( bgBottom, group )
    LayoutHelpers.AtHorizontalCenterIn( bgStretch, group )
    
    group.connector = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/bracket_bmp.dds' ) )
    group.connector.Right:Set( function() return parent.Left() + 8 end )
    LayoutHelpers.AtVerticalCenterIn( group.connector, parent )
    
    LayoutHelpers.LeftOf( group, parent, 10 )
    group.Top:Set( function() return math.max( controls.avatarGroup.Top()+10, ( parent.Top() + ( parent.Height() / 2 ) ) - ( group.Height() / 2 ) ) end )
    
    group:DisableHitTest( true )
    
    group.icons = {}
    
    group.Update = function( self, unitData )

        local function CreateUnitEntry( techLevel, userUnits, icontexture )
            local entry = Group( self )
            
            entry.icon = Bitmap( entry )

			if  icontexture  and  icontexture != nil  and  DiskGetFileInfo( '/textures/ui/common'..icontexture ) then
                entry.icon:SetTexture( '/textures/ui/common'..icontexture )
			elseif  icontexture  and  icontexture != nil  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..icontexture )  then
				entry.icon:SetTexture( MyModPath .. '/textures/ui/common'..icontexture )
            else
                entry.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
            end

            entry.icon.Height:Set( 34 )
            entry.icon.Width:Set( 34 )
            LayoutHelpers.AtRightIn( entry.icon, entry, 22 )
            LayoutHelpers.AtVerticalCenterIn( entry.icon, entry )
            
            entry.iconBG = Bitmap( entry, UIUtil.SkinnableFile( '/game/avatar-factory-panel/avatar-s-e-f_bmp.dds' ) )
            LayoutHelpers.AtCenterIn( entry.iconBG, entry.icon )
            entry.iconBG.Depth:Set( function() return entry.icon.Depth() - 1 end )
            
            entry.techIcon = Bitmap( entry, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/tech-'..techLevel..'_bmp.dds' ) )
            LayoutHelpers.AtLeftIn( entry.techIcon, entry )
            LayoutHelpers.AtVerticalCenterIn( entry.techIcon, entry.icon )
            
            entry.count = UIUtil.CreateText( entry, '', 20, UIUtil.bodyFont )
            entry.count:SetColor( 'ffffffff' )
            entry.count:SetDropShadow( true )
            LayoutHelpers.AtRightIn( entry.count, entry.icon )
            LayoutHelpers.AtBottomIn( entry.count, entry.icon )
            
            entry.countBG = Bitmap( entry )
            entry.countBG:SetSolidColor( '77000000' )
            entry.countBG.Top:Set( function() return entry.count.Top() - 1 end )
            entry.countBG.Left:Set( function() return entry.count.Left() - 1 end )
            entry.countBG.Right:Set( function() return entry.count.Right() + 1 end )
            entry.countBG.Bottom:Set( function() return entry.count.Bottom() + 1 end )
            
            entry.countBG.Depth:Set( function() return entry.Depth() + 1 end )
            entry.count.Depth:Set( function() return entry.countBG.Depth() + 1 end )
            
            entry.Height:Set( function() return entry.iconBG.Height() end )
            entry.Width:Set( self.Width )
            
            entry.icon:DisableHitTest()
            entry.iconBG:DisableHitTest()
            entry.techIcon:DisableHitTest()
            entry.count:DisableHitTest()
            entry.countBG:DisableHitTest()
            
            entry.curIndex = 1
            entry.units = userUnits
            entry.HandleEvent = ClickFunc
            
            return entry
        end

        local qGates = {}
        --qGates[2] = EntityCategoryFilterDown( categories.TECH3 * cat, unitData )
        --qGates[1] = EntityCategoryFilterDown( categories.TECH2 * cat, unitData )
        
        --local indexToIcon = {  '2',  '3' }
        --local keyToIcon   = { 'T2', 'T3' }

		--# HEROPORTAL est une GATE
        qGates[1] = EntityCategoryFilterDown( categories.TECH3 * categories.GATE, unitData )
        
        local indexToIcon = {  '3' }
        local keyToIcon   = { 'T3' }

        for index, units in qGates do
            local i = index
            if not self.icons[i] then
                self.icons[i] = CreateUnitEntry( indexToIcon[i], units, Factions[currentFaction].IdleQuGateTextures[keyToIcon[i]] )
                self.icons[i].priority = i
            end
            if table.getn( units ) > 0 and not self.icons[i]:IsHidden() then
                self.icons[i].units = units
                self.icons[i].count:SetText( table.getn( units ) )
                self.icons[i].count:Show()
                self.icons[i].countBG:Show()
                self.icons[i].icon:SetAlpha( 1 )
            else
                self.icons[i].units = {}
                self.icons[i].count:Hide()
                self.icons[i].countBG:Hide()
                self.icons[i].icon:SetAlpha( .2 )
            end
        end

        local prevGroup = false
        local groupHeight = 0
        for index, gateGroup in qGates do
            local i = index
            if not self.icons[i] then continue end
            if prevGroup then
                LayoutHelpers.Above( self.icons[i], prevGroup )
            else
                LayoutHelpers.AtLeftIn( self.icons[i], self, 7 )
                LayoutHelpers.AtBottomIn( self.icons[i], self, 2 )
            end
            groupHeight = groupHeight + self.icons[i].Height()
            prevGroup = self.icons[i]
        end
        group.Height:Set( groupHeight )
    end
    
    group:Update( units )
    
    return group
end


--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  AJOUTS PAR MANIMAL :
	#  NOUVEAUX AVATARS DU MOD : SCUs ( src=SupCivs )
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function CreateIdleSCUList( parent, units )  --# GROUP
    local group = Group( parent )
    
    local bgTop = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_t.dds' ) )
    local bgBottom = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_b.dds' ) )
    local bgStretch = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/panel-eng_bmp_m.dds' ) )
    
    group.Width:Set( bgTop.Width )
    group.Height:Set( 1 )
    
    bgTop.Bottom:Set( group.Top )
    bgBottom.Top:Set( group.Bottom )
    bgStretch.Top:Set( group.Top )
    bgStretch.Bottom:Set( group.Bottom )
    
    LayoutHelpers.AtHorizontalCenterIn( bgTop, group )
    LayoutHelpers.AtHorizontalCenterIn( bgBottom, group )
    LayoutHelpers.AtHorizontalCenterIn( bgStretch, group )
    
    group.connector = Bitmap( group, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/bracket_bmp.dds' ) )
    group.connector.Right:Set( function() return parent.Left() + 8 end )
    LayoutHelpers.AtVerticalCenterIn( group.connector, parent )
    
    LayoutHelpers.LeftOf( group, parent, 10 )
    group.Top:Set( function() return math.max( controls.avatarGroup.Top()+10, ( parent.Top() + ( parent.Height() / 2 ) ) - ( group.Height() / 2 ) ) end )
    
    group:DisableHitTest( true )
    
    group.icons = {}
    
    group.Update = function( self, unitData )

        local function CreateUnitEntry( techLevel, userUnits, icontexture )
            local entry = Group( self )
            
            entry.icon = Bitmap( entry )

            if  icontexture  and  icontexture != nil  and  DiskGetFileInfo( '/textures/ui/common'..icontexture ) then
                entry.icon:SetTexture( '/textures/ui/common'..icontexture )
			elseif  icontexture  and  icontexture != nil  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..icontexture )  then
				entry.icon:SetTexture( MyModPath .. '/textures/ui/common'..icontexture )
            else
                entry.icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
            end

            entry.icon.Height:Set( 34 )
            entry.icon.Width:Set( 34 )
            LayoutHelpers.AtRightIn( entry.icon, entry, 22 )
            LayoutHelpers.AtVerticalCenterIn( entry.icon, entry )
            
            entry.iconBG = Bitmap( entry, UIUtil.SkinnableFile( '/game/avatar-factory-panel/avatar-s-e-f_bmp.dds' ) )
            LayoutHelpers.AtCenterIn( entry.iconBG, entry.icon )
            entry.iconBG.Depth:Set( function() return entry.icon.Depth() - 1 end )
            
            entry.techIcon = Bitmap( entry, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/tech-'..techLevel..'_bmp.dds' ) )
            LayoutHelpers.AtLeftIn( entry.techIcon, entry )
            LayoutHelpers.AtVerticalCenterIn( entry.techIcon, entry.icon )
            
            entry.count = UIUtil.CreateText( entry, '', 20, UIUtil.bodyFont )
            entry.count:SetColor( 'ffffffff' )
            entry.count:SetDropShadow( true )
            LayoutHelpers.AtRightIn( entry.count, entry.icon )
            LayoutHelpers.AtBottomIn( entry.count, entry.icon )
            
            entry.countBG = Bitmap( entry )
            entry.countBG:SetSolidColor( '77000000' )
            entry.countBG.Top:Set( function() return entry.count.Top() - 1 end )
            entry.countBG.Left:Set( function() return entry.count.Left() - 1 end )
            entry.countBG.Right:Set( function() return entry.count.Right() + 1 end )
            entry.countBG.Bottom:Set( function() return entry.count.Bottom() + 1 end )
            
            entry.countBG.Depth:Set( function() return entry.Depth() + 1 end )
            entry.count.Depth:Set( function() return entry.countBG.Depth() + 1 end )
            
            entry.Height:Set( function() return entry.iconBG.Height() end )
            entry.Width:Set( self.Width )
            
            entry.icon:DisableHitTest()
            entry.iconBG:DisableHitTest()
            entry.techIcon:DisableHitTest()
            entry.count:DisableHitTest()
            entry.countBG:DisableHitTest()
            
            entry.curIndex = 1
            entry.units = userUnits
            entry.HandleEvent = ClickFunc
            
            return entry
        end

        local subCommanders = {}
        subCommanders[1] = EntityCategoryFilterDown( categories.TECH3 * categories.SUBCOMMANDER, unitData )
        
        local indexToIcon = {  '3'  }
        local keyToIcon   = { 'T3' }

        for index, units in subCommanders do
            local i = index
            if not self.icons[i] then
                self.icons[i] = CreateUnitEntry( indexToIcon[i], units, Factions[currentFaction].IdleSCUTextures[keyToIcon[i]] )
                self.icons[i].priority = i
            end
            if table.getn( units ) > 0 and not self.icons[i]:IsHidden() then
                self.icons[i].units = units
                self.icons[i].count:SetText( table.getn( units ) )
                self.icons[i].count:Show()
                self.icons[i].countBG:Show()
                self.icons[i].icon:SetAlpha( 1 )
            else
                self.icons[i].units = {}
                self.icons[i].count:Hide()
                self.icons[i].countBG:Hide()
                self.icons[i].icon:SetAlpha( .2 )
            end
        end

        local prevGroup = false
        local groupHeight = 0
        for index, scuGroup in subCommanders do
            local i = index
            if not self.icons[i] then continue end
            if prevGroup then
                LayoutHelpers.Above( self.icons[i], prevGroup )
            else
                LayoutHelpers.AtLeftIn( self.icons[i], self, 7 )
                LayoutHelpers.AtBottomIn( self.icons[i], self, 2 )
            end
            groupHeight = groupHeight + self.icons[i].Height()
            prevGroup = self.icons[i]
        end
        group.Height:Set( groupHeight )
    end
    
    group:Update( units )
    
    return group
end


--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  MODIF PAR MANIMAL :
	#  POUR PRISE EN COMPTE DES NOUVELLES UNITÉS DU MOD + NOUVEAU TYPE USINE
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function CreateIdleFactoryList( parent, units )  --# BG

    local bg = Bitmap( parent, UIUtil.SkinnableFile( '/game/avatar-factory-panel/factory-panel_bmp.dds' ) )
    
    bg.Right:Set( function() return parent.Left() - 9 end )
    bg.Top:Set( function() return math.max( controls.avatarGroup.Top()+10, ( parent.Top() + ( parent.Height() / 2 ) ) - ( bg.Height() / 2 ) ) end )
    
    local connector = Bitmap( bg, UIUtil.SkinnableFile( '/game/avatar-factory-panel/bracket_bmp.dds' ) )
    LayoutHelpers.AtVerticalCenterIn( connector, parent )
    connector.Right:Set( function() return parent.Left() + 7 end )
    
    bg:DisableHitTest( true )
    
    bg.icons = {}
    
	--# FONCTION DÉPLACÉE ICI CAR PLACE ORIGINALE INUTILE DANS BOUCLE 
    local function CreateIcon( texture )
        local icon = Bitmap( bg )

		if  texture  and  texture != nil  and  DiskGetFileInfo( '/textures/ui/common'..texture )  then
			icon:SetTexture( '/textures/ui/common'..texture )
		elseif  texture  and  texture != nil  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..texture )  then
			icon:SetTexture( MyModPath .. '/textures/ui/common'..texture )
		else
			icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
		end

        icon.Height:Set( 40 )
        icon.Width:Set( 40 )

        icon.count = UIUtil.CreateText( icon, '', 20, UIUtil.bodyFont )
        icon.count:SetColor( 'ffffffff' )
        LayoutHelpers.AtRightIn( icon.count, icon )
        LayoutHelpers.AtBottomIn( icon.count, icon )

        icon.countBG = Bitmap( icon )
        icon.countBG:SetSolidColor( '77000000' )
        icon.countBG.Top:Set( function() return icon.count.Top() - 1 end )
        icon.countBG.Left:Set( function() return icon.count.Left() - 1 end )
        icon.countBG.Right:Set( function() return icon.count.Right() + 1 end )
        icon.countBG.Bottom:Set( function() return icon.count.Bottom() + 1 end )

        icon.countBG.Depth:Set( function() return icon.Depth() + 1 end )
        icon.count.Depth:Set( function() return icon.countBG.Depth() + 1 end )

		icon.count:DisableHitTest()  --# AJOUTÉ PAR MANIMAL
		icon.countBG:DisableHitTest()  --# AJOUTÉ PAR MANIMAL

        icon.curIndex = 1
        icon.HandleEvent = ClickFunc

        return icon
    end


	--# AJOUTÉ LES USINES SOUS-MARINES
	local iconData = { 'LAND', 'AIR', 'NAVAL', 'SUBMERSIBLE' }

    local idleFactoryTextures = Factions[currentFaction].IdleFactoryTextures

    local prevIcon = false
    for type, category in iconData do
		--# ANCIENNE PLACE DE LA FONCTION CreateIcon( texture )

		local indexIcone = { 'T1', 'T2', 'T3' }
		local dernTech = table.getn( indexIcone )

        bg.icons[category] = {}
        local table = bg.icons[category]
        for i = 1, dernTech do
            local tech = indexIcone[i]
            table[i] = CreateIcon( idleFactoryTextures[category][tech] )
            if i == 1 then
                if prevIcon then
                    LayoutHelpers.RightOf( table[i], prevIcon, 4 )
                else
                    LayoutHelpers.AtLeftIn( table[i], bg, 38 )
                    LayoutHelpers.AtBottomIn( table[i], bg, 10 )
                end
                prevIcon = table[i]
            else
                LayoutHelpers.Above( table[i], table[i-1], 4 )
            end
        end
    end


    bg.Update = function( self, unitData )

		--# AJOUTÉ LES USINES SOUS-MARINES
        local usines = { LAND = {}, AIR = {}, NAVAL = {}, SUBMERSIBLE = {} }
        for type, liste in usines do
			local cat = categories[type] * categories.FACTORY
			if  type == 'NAVAL'  then
				cat = cat - categories.SUBMERSIBLE
			end
            liste[3] = EntityCategoryFilterDown( categories.TECH3 * cat, unitData )
            liste[2] = EntityCategoryFilterDown( categories.TECH2 * cat, unitData )
            liste[1] = EntityCategoryFilterDown( categories.TECH1 * cat, unitData )
        end

        for type, icons in bg.icons do
            for index = 1, 3 do
                local i = index
				if usines[type][i] and  usines[type][i] != nil then  -- AVOID ERROR MESSAGES
					if table.getn( usines[type][i] ) > 0 then
						bg.icons[type][i].units = usines[type][i]
						bg.icons[type][i]:SetAlpha( 1 )
						bg.icons[type][i].countBG:Show()
						bg.icons[type][i].count:SetText( table.getn( usines[type][i] ) )
					else
						bg.icons[type][i]:SetAlpha( .2 )
						bg.icons[type][i].countBG:Hide()
						bg.icons[type][i].count:SetText( '' )
					end
				end
            end
        end
    end
    
    bg:Update( units )
    
    return bg
end



--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  MODIF PAR MANIMAL :
	#  POUR PRISE EN COMPTE DES NOUVELLES UNITÉS DU MOD
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function CreateIdleEngineerList( parent, units )  --# BG

    local bg = Bitmap( parent, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/engineers-panel_bmp.dds' ) )
    
    bg.Right:Set( function() return parent.Left() - 9 end )
    bg.Top:Set( function() return math.max( controls.avatarGroup.Top()+10, ( parent.Top() + ( parent.Height() / 2 ) ) - ( bg.Height() / 2 ) ) end )
    
    local connector = Bitmap( bg, UIUtil.SkinnableFile( '/game/avatar-engineers-panel/bracket_bmp.dds' ) )
    LayoutHelpers.AtVerticalCenterIn( connector, parent )
    connector.Right:Set( function() return parent.Left() + 7 end )
    
    bg:DisableHitTest( true )
    
    bg.icons = {}
    
    local function CreateIcon( texture )
        local icon = Bitmap( bg )

		if  texture  and  texture != nil  and  DiskGetFileInfo( '/textures/ui/common'..texture )  then
			icon:SetTexture( '/textures/ui/common'..texture )
		elseif  texture  and  texture != nil  and  DiskGetFileInfo( MyModPath .. '/textures/ui/common'..texture )  then
			icon:SetTexture( MyModPath .. '/textures/ui/common'..texture )
		else
			icon:SetTexture( UIUtil.UIFile( '/icons/units/default_icon.dds' ) )
		end

        icon.Height:Set( 40 )
        icon.Width:Set( 40 )

        icon.count = UIUtil.CreateText( icon, '', 20, UIUtil.bodyFont )
        icon.count:SetColor( 'ffffffff' )
        LayoutHelpers.AtRightIn( icon.count, icon )
        LayoutHelpers.AtBottomIn( icon.count, icon )

        icon.countBG = Bitmap( icon )
        icon.countBG:SetSolidColor( '77000000' )
        icon.countBG.Top:Set( function() return icon.count.Top() - 1 end )
        icon.countBG.Left:Set( function() return icon.count.Left() - 1 end )
        icon.countBG.Right:Set( function() return icon.count.Right() + 1 end )
        icon.countBG.Bottom:Set( function() return icon.count.Bottom() + 1 end )

        icon.countBG.Depth:Set( function() return icon.Depth() + 1 end )
        icon.count.Depth:Set( function() return icon.countBG.Depth() + 1 end )

		icon.count:DisableHitTest()  --# AJOUTÉ PAR MANIMAL
		icon.countBG:DisableHitTest()  --# AJOUTÉ PAR MANIMAL

        icon.curIndex = 1
        icon.HandleEvent = ClickFunc

        return icon
    end

	--# AJOUTÉ LES NOUVEAUX TYPES D'INGÉNIEURS !
	local iconData = { 'LAND', 'AIR', 'NAVAL' }

    local idleEngTextures = Factions[currentFaction].IdleEngTextures

	local indexIcone = { 'T1', 'T2', 'T2F', 'T3' }
	local dernTech = table.getn( indexIcone )

    local prevIcon = false
    for type, category in iconData do
        --# PLACE ORIGINALE DE local function CreateIcon( texture )

        bg.icons[category] = {}
        local table = bg.icons[category]
        for i = 1, dernTech do
            local tech = indexIcone[i]
            table[i] = CreateIcon( idleEngTextures[category][tech] )
            if i == 1 then
                if prevIcon then
                    LayoutHelpers.RightOf( table[i], prevIcon, 4 )
                else
                    LayoutHelpers.AtLeftIn( table[i], bg, 38 )
                    --# Ancien panneau : LayoutHelpers.AtBottomIn( table[i], bg, 10 )
                    LayoutHelpers.AtBottomIn( table[i], bg, 14 )
                end
                prevIcon = table[i]
            else
                LayoutHelpers.Above( table[i], table[i-1], 4 )
            end
        end
    end

    bg.Update = function( self, unitData )
		--# AJOUTÉ LES TYPES D'INGÉNIEURS
        local engineers = { LAND = {}, AIR = {}, NAVAL = {} }
        for type, liste in engineers do
            liste[4] = EntityCategoryFilterDown( categories.TECH3 * categories[type], unitData )
            liste[3] = EntityCategoryFilterDown( categories.TECH2 * categories[type] * categories.FIELDENGINEER, unitData )
            liste[2] = EntityCategoryFilterDown( ( categories.TECH2 * categories[type] ) - categories.FIELDENGINEER, unitData )
            liste[1] = EntityCategoryFilterDown( categories.TECH1 * categories[type], unitData )
        end
        for type, icons in bg.icons do
            for index = 1, dernTech do
                local i = index
				if engineers[type][i] and  engineers[type][i] != nil then  -- AVOID ERROR MESSAGES
					if table.getn( engineers[type][i] ) > 0 then
						bg.icons[type][i].units = engineers[type][i]
						bg.icons[type][i]:SetAlpha( 1 )
						bg.icons[type][i].countBG:Show()
						bg.icons[type][i].count:SetText( table.getn( engineers[type][i] ) )
					else
						bg.icons[type][i]:SetAlpha( .2 )
						bg.icons[type][i].countBG:Hide()
						bg.icons[type][i].count:SetText( '' )
					end
				end
            end
        end
    end
    
    bg:Update( units )
    
    return bg
end



--[[
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#  MODIF PAR MANIMAL :
	#  POUR PRISE EN COMPTE DES NOUVEAUX AVATARS DU MOD ( PORTAILS ET LABOS )
	#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]--

function AvatarUpdate()
    if import( '/lua/ui/game/gamemain.lua' ).IsNISMode() then  return  end

	local avatars         = GetCommanders()				--#local avatars = GetArmyAvatars()
	local labos           = GetIdleLabos()				--#  AJOUT PAR MANIMAL :-)
	local portails        = GetIdlePortails()			--#  AJOUT PAR MANIMAL :-)
	local heros           = GetSecondaryCommanders()	--#  AJOUT PAR MANIMAL :-)
	local quantumGates    = GetIdleQuantumGates()		--#  AJOUT PAR MANIMAL :-)
	local subcommanders   = GetIdleSubCommanders()		--#  AJOUT PAR MANIMAL :-)
    local factories       = GetIdleFactoriesONLY()
    local engineers       = GetIdleEngineersONLY()

    local needsAvatarLayout = false
    local validAvatars = {}
    
	local armee = GetFocusArmy()
    currentFaction = GetArmiesTable().armiesTable[armee].faction + 1
    
    if avatars then
        for _, unit in avatars do
            local un_Id = unit:GetEntityId()
            if controls.avatars[un_Id] then			--si Avatar ( son control )  existe
                controls.avatars[un_Id]:Update()    -- Mise à Jour des Avatars déjà créés
            else
                if initialACU == false then             -- CREER L'AVATAR pour COMMANDER INITIAL SEULEMENT
					controls.avatars[un_Id] = CreateAvatar( unit )
                    needsAvatarLayout = true
					initialACU = un_Id
				end
            end
			if  initialACU == un_Id  then --# AJOUT TEST
				validAvatars[un_Id] = true --# ORIGINAL EST INCONDITIONNEL
			end
        end
        for entID, control in controls.avatars do
            local i = entID
            if not validAvatars[i] then    -- Destruction des Avatars déjà créés mais pas validés
                controls.avatars[i]:Destroy()
                controls.avatars[i] = nil
                needsAvatarLayout = true
				if initialACU == i then initialACU = false end
            end
        end
    elseif controls.avatars then    -- PAS d'AVATAR mais control résiduel = Destruction des Avatars déjà créés
        for entID, control in controls.avatars do
            local i = entID
            controls.avatars[i]:Destroy()
            controls.avatars[i] = nil
            needsAvatarLayout = true
			if initialACU == i then initialACU = false end
        end
    end


    if labos then
        if controls.idleLabos then
            controls.idleLabos:Update( labos )
        else
            controls.idleLabos = CreateIdleTab( labos, 'labo', CreateIdleLabosList )
            if expandedCheck == 'labo' then
                controls.idleLabos.expandCheck:SetCheck( true )
            end
            needsAvatarLayout = true
        end
    else
        if controls.idleLabos then
            controls.idleLabos:Destroy()
            controls.idleLabos = nil
            needsAvatarLayout = true
        end
    end


    if portails then
        if controls.idlePortails then
            controls.idlePortails:Update( portails )
        else
			--# ZAPPER LA LISTE ET LA FLECHE
			--[[
            controls.idlePortails = CreateIdleTab( portails, 'heroportal', CreateIdlePortailsList )
            if expandedCheck == 'heroportal' then
                controls.idlePortails.expandCheck:SetCheck( true )
            end
			]]--
            controls.idlePortails = CreateIdleTab( portails, 'heroportal', nil )
            needsAvatarLayout = true
        end
    else
        if controls.idlePortails then
            controls.idlePortails:Destroy()
            controls.idlePortails = nil
            needsAvatarLayout = true
        end
    end


    if heros then
        if controls.idleHeros then
            controls.idleHeros:Update( heros )
        else
            controls.idleHeros = CreateIdleTab( heros, 'hero', CreateIdleHerosList )
            if expandedCheck == 'hero' then
                controls.idleHeros.expandCheck:SetCheck( true )
            end
            needsAvatarLayout = true
        end
    else
        if controls.idleHeros then
            controls.idleHeros:Destroy()
            controls.idleHeros = nil
            needsAvatarLayout = true
        end
    end


    if quantumGates then
        if controls.idleQuantGates then
            controls.idleQuantGates:Update( quantumGates )
        else
            controls.idleQuantGates = CreateIdleTab( quantumGates, 'quantumgate', CreateIdleQuantumGatesList )
            if expandedCheck == 'quantumgate' then
                controls.idleQuantGates.expandCheck:SetCheck( true )
            end
            needsAvatarLayout = true
        end
    else
        if controls.idleQuantGates then
            controls.idleQuantGates:Destroy()
            controls.idleQuantGates = nil
            needsAvatarLayout = true
        end
    end


	if subcommanders then
        if controls.idleSCUs then
            controls.idleSCUs:Update( subcommanders )    -- Mise à Jour de la liste des subcommanders
        else    -- CREER un SCU TAB
            controls.idleSCUs = CreateIdleTab( subcommanders, 'subcommander', CreateIdleSCUList )
            if expandedCheck == 'subcommander' then
                controls.idleSCUs.expandCheck:SetCheck( true )
            end
            needsAvatarLayout = true
        end
    else
        if controls.idleSCUs then    -- PAS de SCUs mais control résiduel = Destruction des idleSCUs déjà créés
            controls.idleSCUs:Destroy()
            controls.idleSCUs = nil
            needsAvatarLayout = true
        end
    end


    if factories then
        if controls.idleFactories then
            controls.idleFactories:Update( factories )
        else
            controls.idleFactories = CreateIdleTab( factories, 'factory', CreateIdleFactoryList )
            if expandedCheck == 'factory' then
                controls.idleFactories.expandCheck:SetCheck( true )
            end
            needsAvatarLayout = true
        end
    else
        if controls.idleFactories then
            controls.idleFactories:Destroy()
            controls.idleFactories = nil
            needsAvatarLayout = true
        end
    end


    if engineers  then
        if controls.idleEngineers then
            controls.idleEngineers:Update( engineers )
        else
            controls.idleEngineers = CreateIdleTab( engineers, 'engineer', CreateIdleEngineerList )
            if expandedCheck == 'engineer' then
                controls.idleEngineers.expandCheck:SetCheck( true )
            end
            needsAvatarLayout = true
        end
    else
        if controls.idleEngineers then
            controls.idleEngineers:Destroy()
            controls.idleEngineers = nil
            needsAvatarLayout = true
        end
    end


    if needsAvatarLayout then
        import( UIUtil.GetLayoutFilename( 'avatars' ) ).LayoutAvatars()
    end
end



function FocusArmyChanged()
    for i, control in controls.avatars do
        local index = i
        if controls.avatars[index] then
            controls.avatars[index]:Destroy()
            controls.avatars[index] = nil
        end
    end
    if GetFocusArmy() == -1 then
        GameMain.RemoveBeatFunction( AvatarUpdate )
        recievingBeatUpdate = false
    elseif not recievingBeatUpdate then
        recievingBeatUpdate = true
        GameMain.AddBeatFunction( AvatarUpdate )
    end
end


local preContractState = false

function Contract()
    preContractState = controls.avatarGroup:IsHidden()
    controls.avatarGroup:Hide()
    controls.collapseArrow:Hide()
end

function Expand()
    controls.avatarGroup:SetHidden( preContractState )
    controls.collapseArrow:Show()
end


function InitialAnimation()
    controls.avatarGroup:Show()
    controls.avatarGroup.Left:Set( controls.parent.Left()-controls.avatarGroup.Width() )
    controls.avatarGroup:SetNeedsFrameUpdate( true )
    controls.avatarGroup.OnFrame = function( self, delta )
        local newLeft = self.Left() + ( 1000*delta )
        if newLeft > controls.parent.Left()-3 then
            newLeft = function() return controls.parent.Left()-3 end
            self:SetNeedsFrameUpdate( false )
        end
        self.Left:Set( newLeft )
    end
    controls.collapseArrow:Show()
    controls.collapseArrow:SetCheck( false, true )
end

