Ryan F. Mercer
Whys
NotificationPanel.lua is a cleaned-up version of the original with a CustomNotificationPanel.lua include, which allows for the easy creation of additional custom notifications. The 2 example custom notifications are from my Building Resources mod.
NotificationPanel.lua:
CustomNotificationPanel.lua:
NotificationPanel.xml: (snippet)
The entire NotificationPanel.xml is too long to post, but the only modifications are shown here.
------------------------
Here are some different approaches offered by others:
- Sneaks'
- alpaca's
- Moaf's
_
NotificationPanel.lua:
Spoiler :
Code:
-- vymdt.01.2010.11.12.1515
-- Created by: Whys Alives -Open source
--===========================================================================
-- NotificationPanel.lua
--===========================================================================
--[[
Notifications manager. For custom notifications use CustomNotificatonPanel.
]]
include( "IconSupport" );
include( "InstanceManager" );
include( "CustomNotificationPanel" );
--===========================================================================
--[[
Global Variables.
]]
local g_ActiveNotifications = {};
local g_Instances = {};
--for dynamically sizing small notification stack.
local DIPLO_SIZE_GUESS = 120;
local _, screenY = UIManager:GetScreenSizeVal();
local _, offsetY = Controls.OuterStack:GetOffsetVal();
local g_SmallScrollMax = screenY - offsetY - DIPLO_SIZE_GUESS;
--handled notification types.
local g_NameTable = {};
g_NameTable[-1] = "Generic";
g_NameTable[NotificationTypes.NOTIFICATION_POLICY] = "SocialPolicy";
g_NameTable[NotificationTypes.NOTIFICATION_MET_MINOR] = "MetCityState";
g_NameTable[NotificationTypes.NOTIFICATION_MINOR] = "CityState";
g_NameTable[NotificationTypes.NOTIFICATION_MINOR_QUEST] = "CityState";
g_NameTable[NotificationTypes.NOTIFICATION_ENEMY_IN_TERRITORY] = "EnemyInTerritory";
g_NameTable[NotificationTypes.NOTIFICATION_CITY_RANGE_ATTACK] = "Generic";
g_NameTable[NotificationTypes.NOTIFICATION_BARBARIAN] = "Barbarian";
g_NameTable[NotificationTypes.NOTIFICATION_GOODY] = "AncientRuins";
g_NameTable[NotificationTypes.NOTIFICATION_BUY_TILE] = "BuyTile";
g_NameTable[NotificationTypes.NOTIFICATION_CITY_GROWTH] = "CityGrowth";
g_NameTable[NotificationTypes.NOTIFICATION_CITY_TILE] = "CityTile";
g_NameTable[NotificationTypes.NOTIFICATION_DEMAND_RESOURCE] = "BonusResource";
g_NameTable[NotificationTypes.NOTIFICATION_UNIT_PROMOTION] = "UnitPromoted";
--g_NameTable[NotificationTypes.NOTIFICATION_WONDER_STARTED] = "WonderConstructed";
g_NameTable[NotificationTypes.NOTIFICATION_WONDER_COMPLETED_ACTIVE_PLAYER] = "WonderConstructed";
g_NameTable[NotificationTypes.NOTIFICATION_WONDER_COMPLETED] = "WonderConstructed";
g_NameTable[NotificationTypes.NOTIFICATION_WONDER_BEATEN] = "WonderConstructed";
g_NameTable[NotificationTypes.NOTIFICATION_GOLDEN_AGE_BEGUN_ACTIVE_PLAYER] = "GoldenAge";
--g_NameTable[NotificationTypes.NOTIFICATION_GOLDEN_AGE_BEGUN] = "GoldenAge";
g_NameTable[NotificationTypes.NOTIFICATION_GOLDEN_AGE_ENDED_ACTIVE_PLAYER] = "GoldenAge";
--g_NameTable[NotificationTypes.NOTIFICATION_GOLDEN_AGE_ENDED] = "GoldenAge";
g_NameTable[NotificationTypes.NOTIFICATION_GREAT_PERSON_ACTIVE_PLAYER] = "GreatPerson";
--g_NameTable[NotificationTypes.NOTIFICATION_GREAT_PERSON] = "GreatPerson";
g_NameTable[NotificationTypes.NOTIFICATION_STARVING] = "Starving";
g_NameTable[NotificationTypes.NOTIFICATION_WAR_ACTIVE_PLAYER] = "War";
g_NameTable[NotificationTypes.NOTIFICATION_WAR] = "WarOther";
g_NameTable[NotificationTypes.NOTIFICATION_PEACE_ACTIVE_PLAYER] = "Peace";
g_NameTable[NotificationTypes.NOTIFICATION_PEACE] = "PeaceOther";
g_NameTable[NotificationTypes.NOTIFICATION_VICTORY] = "Victory";
g_NameTable[NotificationTypes.NOTIFICATION_UNIT_DIED] = "UnitDied";
g_NameTable[NotificationTypes.NOTIFICATION_CITY_LOST] = "CapitalLost";
g_NameTable[NotificationTypes.NOTIFICATION_CAPITAL_LOST_ACTIVE_PLAYER] = "CapitalLost";
g_NameTable[NotificationTypes.NOTIFICATION_CAPITAL_LOST] = "CapitalLost";
g_NameTable[NotificationTypes.NOTIFICATION_CAPITAL_RECOVERED] = "CapitalRecovered";
g_NameTable[NotificationTypes.NOTIFICATION_PLAYER_KILLED] = "CapitalLost";
g_NameTable[NotificationTypes.NOTIFICATION_DISCOVERED_LUXURY_RESOURCE] = "LuxuryResource";
g_NameTable[NotificationTypes.NOTIFICATION_DISCOVERED_STRATEGIC_RESOURCE] = "StrategicResource";
g_NameTable[NotificationTypes.NOTIFICATION_DISCOVERED_BONUS_RESOURCE] = "BonusResource";
--g_NameTable[NotificationTypes.NOTIFICATION_POLICY_ADOPTION] = "Generic";
g_NameTable[NotificationTypes.NOTIFICATION_DIPLO_VOTE] = "Generic";
g_NameTable[NotificationTypes.NOTIFICATION_RELIGION_RACE] = "Generic";
g_NameTable[NotificationTypes.NOTIFICATION_EXPLORATION_RACE] = "NaturalWonder";
g_NameTable[NotificationTypes.NOTIFICATION_DIPLOMACY_DECLARATION] = "Diplomacy";
g_NameTable[NotificationTypes.NOTIFICATION_DEAL_EXPIRED_GPT] = "DiplomacyX";
g_NameTable[NotificationTypes.NOTIFICATION_DEAL_EXPIRED_RESOURCE] = "DiplomacyX";
g_NameTable[NotificationTypes.NOTIFICATION_DEAL_EXPIRED_OPEN_BORDERS] = "DiplomacyX";
g_NameTable[NotificationTypes.NOTIFICATION_DEAL_EXPIRED_DEFENSIVE_PACT] = "DiplomacyX";
g_NameTable[NotificationTypes.NOTIFICATION_DEAL_EXPIRED_RESEARCH_AGREEMENT] = "DiplomacyX";
g_NameTable[NotificationTypes.NOTIFICATION_DEAL_EXPIRED_TRADE_AGREEMENT] = "DiplomacyX";
g_NameTable[NotificationTypes.NOTIFICATION_TECH_AWARD] = "TechAward";
g_NameTable[NotificationTypes.NOTIFICATION_PLAYER_DEAL] = "Diplomacy";
g_NameTable[NotificationTypes.NOTIFICATION_PLAYER_DEAL_RECEIVED] = "Diplomacy";
g_NameTable[NotificationTypes.NOTIFICATION_PLAYER_DEAL_RESOLVED] = "Diplomacy";
g_NameTable[NotificationTypes.NOTIFICATION_PROJECT_COMPLETED] = "ProjectConstructed";
g_NameTable[NotificationTypes.NOTIFICATION_TECH] = "Tech";
g_NameTable[NotificationTypes.NOTIFICATION_PRODUCTION] = "Production";
g_NameTable[NotificationTypes.NOTIFICATION_FREE_TECH] = "FreeTech";
--===========================================================================
--[[
handles mouse left-click for standard notifications.
]]
function GenericLeftClick( Id )
UI.ActivateNotification( Id )
end
--===========================================================================
--[[
handles mouse right-click for standard notifications.
]]
function GenericRightClick( Id )
UI.RemoveNotification( Id )
end
--===========================================================================
--[[
Activates notification.
]]
function OnNotificationAdded( id, iType, toolTip, summary, iGameValue, iExtraGameData )
--[[print( "OnNotificationAdded(): "
..tostring( id ) .."|"..tostring( iType ) .."|"
..tostring( iGameValue ).."|"..tostring( iExtraGameData ).."|"
..tostring( summary ) .."|"..tostring( toolTip )
);--]]
if g_ActiveNotifications[id] ~= nil then
print( "Redundant Notification Type: "..tostring( iType ) ); return;
end
local instance = {};
local name = g_NameTable[iType];
local button = nil;
if name == "Production" or name == "Tech" or name == "FreeTech" then
--local frame = Controls[name.."Frame"];
--local title = Controls[name.."Title"];
local bg = Controls[name.."BG"];
local text = Controls[name.."Text"];
button = Controls[name.."Button"];
--title:SetText( name );
--text:SetText( toolTip );
else
ContextPtr:BuildInstanceForControl( name.."Item", instance, Controls.SmallStack );
g_Instances[id] = instance;
local root = instance[name.."Container"];
button = instance[name.."Button"];
instance.FingerTitle:SetText( summary );
root:BranchResetAnimation();
--if iType == NotificationTypes.NOTIFICATION_WONDER_STARTED
if iType == NotificationTypes.NOTIFICATION_WONDER_COMPLETED_ACTIVE_PLAYER or
iType == NotificationTypes.NOTIFICATION_WONDER_COMPLETED or
iType == NotificationTypes.NOTIFICATION_WONDER_BEATEN then
if iGameValue ~= -1 then
local portraitIndex = GameInfo.Buildings[iGameValue].PortraitIndex;
if portraitIndex ~= -1 then
IconHookup( portraitIndex, 80, GameInfo.Buildings[iGameValue].IconAtlas, instance.WonderConstructedAlphaAnim );
end
end
if iExtraGameData ~= -1 then
CivIconHookup( iExtraGameData, 45, instance.CivIcon, instance.CivIconBG, instance.CivIconShadow, false, true );
instance.WonderSmallCivFrame:SetHide(false);
else
CivIconHookup( 22, 45, instance.CivIcon, instance.CivIconBG, instance.CivIconShadow, false, true );
instance.WonderSmallCivFrame:SetHide(true);
end
elseif iType == NotificationTypes.NOTIFICATION_PROJECT_COMPLETED then
if iGameValue ~= -1 then
local portraitIndex = GameInfo.Projects[iGameValue].PortraitIndex;
if portraitIndex ~= -1 then
IconHookup( portraitIndex, 80, GameInfo.Projects[iGameValue].IconAtlas, instance.ProjectConstructedAlphaAnim );
end
end
if iExtraGameData ~= -1 then
CivIconHookup( iExtraGameData, 45, instance.CivIcon, instance.CivIconBG, instance.CivIconShadow, false, true );
instance.ProjectSmallCivFrame:SetHide(false);
else
CivIconHookup( 22, 45, instance.CivIcon, instance.CivIconBG, instance.CivIconShadow, false, true );
instance.ProjectSmallCivFrame:SetHide(true);
end
elseif iType == NotificationTypes.NOTIFICATION_DISCOVERED_LUXURY_RESOURCE or
iType == NotificationTypes.NOTIFICATION_DISCOVERED_STRATEGIC_RESOURCE or
iType == NotificationTypes.NOTIFICATION_DISCOVERED_BONUS_RESOURCE or
iType == NotificationTypes.NOTIFICATION_DEMAND_RESOURCE then
local thisResourceInfo = GameInfo.Resources[iGameValue];
local portraitIndex = thisResourceInfo.PortraitIndex;
if portraitIndex ~= -1 then
IconHookup( portraitIndex, 80, thisResourceInfo.IconAtlas, instance.ResourceImage );
end
elseif iType == NotificationTypes.NOTIFICATION_EXPLORATION_RACE then
local thisFeatureInfo = GameInfo.Features[iGameValue];
local portraitIndex = thisFeatureInfo.PortraitIndex;
if portraitIndex ~= -1 then
IconHookup( portraitIndex, 80, thisFeatureInfo.IconAtlas, instance.NaturalWonderImage );
end
elseif iType == NotificationTypes.NOTIFICATION_TECH_AWARD then
local thisTechInfo = GameInfo.Technologies[iExtraGameData];
local portraitIndex = thisTechInfo.PortraitIndex;
if portraitIndex ~= -1 then
IconHookup( portraitIndex, 80, thisTechInfo.IconAtlas, instance.TechAwardImage );
else
instance.TechAwardImage:SetHide( true );
end
elseif iType == NotificationTypes.NOTIFICATION_UNIT_PROMOTION or
iType == NotificationTypes.NOTIFICATION_UNIT_DIED or
iType == NotificationTypes.NOTIFICATION_GREAT_PERSON_ACTIVE_PLAYER or
iType == NotificationTypes.NOTIFICATION_ENEMY_IN_TERRITORY then
local thisUnitType = iGameValue;
local thisUnitInfo = GameInfo.Units[thisUnitType];
local portraitIndex = thisUnitInfo.PortraitIndex;
if portraitIndex ~= -1 then
IconHookup( portraitIndex, 80, thisUnitInfo.IconAtlas, instance.UnitImage );
end
elseif iType == NotificationTypes.NOTIFICATION_WAR_ACTIVE_PLAYER then
local index = iGameValue;
CivIconHookup( index, 80, instance.WarImage, instance.CivIconBG, instance.CivIconShadow, false, true );
elseif iType == NotificationTypes.NOTIFICATION_WAR then
local index = iGameValue;
CivIconHookup( index, 45, instance.War1Image, instance.Civ1IconBG, instance.Civ1IconShadow, false, true );
index = iExtraGameData;
CivIconHookup( index, 45, instance.War2Image, instance.Civ2IconBG, instance.Civ2IconShadow, false, true );
elseif iType == NotificationTypes.NOTIFICATION_PEACE_ACTIVE_PLAYER then
local index = iGameValue;
CivIconHookup( index, 80, instance.PeaceImage, instance.CivIconBG, instance.CivIconShadow, false, true );
elseif iType == NotificationTypes.NOTIFICATION_PEACE then
local index = iGameValue;
CivIconHookup( index, 45, instance.Peace1Image, instance.Civ1IconBG, instance.Civ1IconShadow, false, true );
index = iExtraGameData;
CivIconHookup( index, 45, instance.Peace2Image, instance.Civ2IconBG, instance.Civ2IconShadow, false, true );
end
end
button:SetHide( false );
button:SetVoid1( id );
button:RegisterCallback( Mouse.eLClick, GenericLeftClick );
button:RegisterCallback( Mouse.eRClick, GenericRightClick );
button:SetToolTipString( toolTip );
g_ActiveNotifications[id] = iType;
ProcessStackSizes();
end
Events.NotificationAdded.Add( OnNotificationAdded );
--===========================================================================
--[[
Deactivates notification.
]]
function OnNotificationRemoved( id )
--[[print( "NotificationRemoved(): "
..tostring( id ).."|"..tostring( g_ActiveNotifications[id] ).."|"
..tostring( g_NameTable[ g_ActiveNotifications[id] ] )
);]]
if g_ActiveNotifications[id] == nil then
print( "Unknown Notification Id: "..tostring( id ) ); return;
end
local name = g_NameTable[g_ActiveNotifications[id]];
if name == "Production" or name == "Tech" or name == "FreeTech" then
Controls[name.."Button"]:SetHide( true );
else
if name == nil then name = "Generic"; end
local instance = g_Instances[id];
if instance ~= nil then
Controls.SmallStack:ReleaseChild( instance[name.."Container"] );
g_Instances[id] = nil;
end
end
ProcessStackSizes();
end
Events.NotificationRemoved.Add( OnNotificationRemoved );
--===========================================================================
--[[
Processes stack sizes.
]]
function ProcessStackSizes()
Controls.BigStack:CalculateSize();
local bigY = Controls.BigStack:GetSizeY();
Controls.SmallScrollPanel:SetSizeY( g_SmallScrollMax - bigY );
Controls.SmallStack:CalculateSize();
Controls.SmallStack:ReprocessAnchoring();
Controls.SmallScrollPanel:CalculateInternalSize();
if Controls.SmallScrollPanel:GetRatio() ~= 1 then
Controls.SmallScrollPanel:SetOffsetVal( 20, 0 );
else
Controls.SmallScrollPanel:SetOffsetVal( 0, 0 );
end
Controls.OuterStack:CalculateSize();
Controls.OuterStack:ReprocessAnchoring();
--[[
--for autosized background grids.
local _, y = Controls.BigStack:GetSizeVal();
if y > 0 then
Controls.BigGrid:DoAutoSize();
Controls.BigGrid:SetHide( false );
else
Controls.BigGrid:SetHide( true );
end
local _, y = Controls.SmallStack:GetSizeVal();
if y > 0 then
Controls.SmallGrid:DoAutoSize();
Controls.SmallGrid:SetHide( false );
else
Controls.SmallGrid:SetHide( true );
end
--]]
end
--===========================================================================
--exceptions.
Controls["TechButton"] :RegisterCallback( Mouse.eLClick, GenericLeftClick );
Controls["TechButton"] :RegisterCallback( Mouse.eRClick, GenericRightClick );
Controls["ProductionButton"]:RegisterCallback( Mouse.eLClick, GenericLeftClick );
Controls["ProductionButton"]:RegisterCallback( Mouse.eRClick, GenericRightClick );
Controls["FreeTechButton"] :RegisterCallback( Mouse.eLClick, GenericLeftClick );
Controls["FreeTechButton"] :RegisterCallback( Mouse.eRClick, GenericRightClick );
UI.RebroadcastNotifications();
ProcessStackSizes();
--===========================================================================
--END NotificationPanel.lua
--===========================================================================
-- Created by: Whys Alives -Open source
Spoiler :
Code:
-- vymdt.01.2010.11.12.1515
-- Created by: Whys Alives -Open source
--===========================================================================
-- CustomNotificationPanel.lua
--===========================================================================
--[[
Custom notifications manager.
Add unique integer keys greater than 1000 in g_customNameTable and assign
notification names. The integer corresponds to the first argument in
LuaEvents.CustomNotification() and the name corresponds to context instance
name+"Item" in NotificationPanel.xml, ie: <Instance Name="{name}Item" >.
Then add desired behavior to "Custom Notification Handling" section below.
Reassign mouse left-click and mouse right-click functions if desired.
]]
--include( "WhysUtils" ); --provides: out().
--===========================================================================
--[[
Global Variables.
]]
local g_customActiveNotifications = {};
local g_customInstances = {};
local g_customData = {};
local g_customId = 0;
--handled custom notification types.
local g_customNameTable = {};
g_customNameTable[ 1001 ] = "BuildingResourcesGain";
g_customNameTable[ 1002 ] = "BuildingResourcesLoss";
--===========================================================================
--[[
handles default mouse left-click for custom notifications. Uses fourth
argument in LuaEvents.CustomNotification() to goto {x,y} map location.
]]
function customLeftClick( id )
if type( g_customData[id] ) == "table" and
type( g_customData[id]["location"] ) == "table" then
local plot = Map.GetPlot( g_customData[id]["location"][1]
, g_customData[id]["location"][2] );
if plot ~= nil then UI.LookAt( plot, 0 ); end
end
end
--===========================================================================
--[[
handles default mouse right-click for custom notifications. Deactivates
custom notification.
]]
function customRightClick( id )
if g_customActiveNotifications[id] == nil then
print( "Unknown Custom Notification Id: "..tostring( id ) ); return;
end
local name = g_customNameTable[g_customActiveNotifications[id]];
local instance = g_customInstances[id];
if instance ~= nil then
Controls.SmallStack:ReleaseChild( instance[name.."Container"] );
g_customInstances[id] = nil;
end
ProcessStackSizes();
end
--===========================================================================
--[[
Activates custom notification.
]]
function onCustomNotificationAdded( iType, summary, toolTip, data )
g_customId = g_customId +1;
--[[print( "OnNotificationAdded(): "
..tostring( g_customId ).."|"..tostring( iType ).."|"..out( data ).."|"
..tostring( summary ).."|"..tostring( toolTip )
);--]]
if g_customActiveNotifications[g_customId] ~= nil then
print( "Redundant Custom Notification Type: "..tostring( iType ) ); return;
end
local instance = {};
local name = g_customNameTable[iType];
ContextPtr:BuildInstanceForControl( name.."Item", instance, Controls.SmallStack );
g_customInstances[g_customId] = instance;
g_customData[g_customId] = data;
local root = instance[name.."Container"];
local button = instance[name.."Button"];
instance.FingerTitle:SetText( summary );
root:BranchResetAnimation();
local leftClick, rightClick = nil, nil;
--.........................................................................
-- Custom Notification Handling
--BuildingResourcesGain, BuildingResourcesLoss.
if iType == 1001 or iType == 1002 then
--leftClick = --replacement function.
--rightClick = --replacement function.
local image = instance["BuildingImage"];
if type( g_customData[g_customId] ) == "table" then
local buildingType = g_customData[g_customId]["buildingType"];
local index = GameInfo.Buildings[buildingType].PortraitIndex;
local atlas = GameInfo.Buildings[buildingType].IconAtlas;
if index ~= -1 then IconHookup( index, 80, atlas, image ); end
end
--???
--elseif iType == ??? then
--do something.
end
--END Custom Notification Handling
--.........................................................................
if type( leftClick ) ~= "function" then leftClick = customLeftClick; end
if type( rightClick ) ~= "function" then rightClick = customRightClick; end
button:SetHide( false );
button:SetVoid1( g_customId );
button:RegisterCallback( Mouse.eLClick, leftClick );
button:RegisterCallback( Mouse.eRClick, rightClick );
button:SetToolTipString( toolTip );
g_customActiveNotifications[g_customId] = iType;
ProcessStackSizes();
end
LuaEvents.CustomNotification.Add( onCustomNotificationAdded );
--===========================================================================
--[[
Deactivates all custom notifications on end of turn.
]]
function onTurnEnd()
for id,type in pairs( g_customInstances ) do customRightClick( id ); end
end
Events.ActivePlayerTurnEnd.Add( onTurnEnd );
--===========================================================================
--END CustomNotificationPanel.lua
--===========================================================================
-- Created by: Whys Alives -Open source
Spoiler :
Code:
<!--=======================================================================================================================-->
<!-- Building Resources Gain -->
<!--=======================================================================================================================-->
<Instance Name="BuildingResourcesGainItem" >
<Container Anchor="R,C" Size="80,80" Offset="0,0" Hidden="0" ID="BuildingResourcesGainContainer" ConsumeMouseButton="1" >
<SlideAnim Anchor="L,T" Style="NotificationSlide" ID="NotificationSlide" >
<AlphaAnim Style="NewFinger" />
<Button Anchor="C,C" Size="80,80" Offset="0,0" Texture="assets\UI\Art\Notification\NotificationFrameBase.dds" ID="BuildingResourcesGainButton" Hidden="0" >
<ShowOnMouseOver>
<Image Anchor="C,C" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationFrameBase.dds" />
<AlphaAnim Anchor="C,C" AnchorSide="O.O" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationFrameGlow2.dds" Pause="0" Cycle="Bounce" Speed="1" AlphaStart="1" AlphaEnd="0" Hidden="0" />
</ShowOnMouseOver>
<Image Anchor="C,C" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationYellow.dds" />
<AlphaAnim Anchor="C,C" Offset="0,-1" Size="80,80" Texture="assets\UI\Art\Icons\BuildingAtlas512.dds" ID="BuildingImage" Pause="0" Cycle="Bounce" Speed="1" AlphaStart=".5" AlphaEnd="1" />
<Label Anchor="C,C" Offset="0,0" String="" Font="TwCenMT20" ColorSet="Beige_Black_Alpha" FontStyle="Shadow" ID="BuildingResourcesGainCount" />
</Button>
</SlideAnim>
</Container>
</Instance>
<!--=======================================================================================================================-->
<!-- Building Resources Loss -->
<!--=======================================================================================================================-->
<Instance Name="BuildingResourcesLossItem" >
<Container Anchor="R,C" Size="80,80" Offset="0,0" Hidden="0" ID="BuildingResourcesLossContainer" ConsumeMouseButton="1" >
<SlideAnim Anchor="L,T" Style="NotificationSlide" ID="NotificationSlide" >
<AlphaAnim Style="NewFinger" />
<Button Anchor="C,C" Size="80,80" Offset="0,0" Texture="assets\UI\Art\Notification\NotificationFrameBase.dds" ID="BuildingResourcesLossButton" Hidden="0" >
<ShowOnMouseOver>
<Image Anchor="C,C" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationFrameBase.dds" />
<AlphaAnim Anchor="C,C" AnchorSide="O.O" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationFrameGlow2.dds" Pause="0" Cycle="Bounce" Speed="1" AlphaStart="1" AlphaEnd="0" Hidden="0" />
</ShowOnMouseOver>
<Image Anchor="C,C" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationBlack.dds" />
<AlphaAnim Anchor="C,C" Offset="0,-1" Size="80,80" Texture="assets\UI\Art\Icons\BuildingAtlas512.dds" ID="BuildingImage" Pause="0" Cycle="Bounce" Speed="1" AlphaStart=".5" AlphaEnd="1" />
<Label Anchor="C,C" Offset="0,0" String="" Font="TwCenMT20" ColorSet="Beige_Black_Alpha" FontStyle="Shadow" ID="BuildingResourcesLossCount" />
</Button>
</SlideAnim>
</Container>
</Instance>
------------------------
Here are some different approaches offered by others:
- Sneaks'
- alpaca's
- Moaf's
_