class a_MapOptimizer extends a_ActorBase
  config(HideMut);

struct MyZone
{
  var int ZoneKey;  //zone key
  var string ZoneName;  //Zone name
  var array<Vector> VectorsCoord; //Coordinates of zone borders. Drawing from 0 to 1, 1 to 2 and etc.
  var float MinX, MinY, MaxX, MaxY; //Minimal coords for setting zoned actors
  var array<int> PortalActorsRefs; //Actors that are visible through "portal" aka hole between neighbouring zones. Neighbouring zones may have same set of this
  var array<int> DecorativeActorsRefs; //Decorative stuff between zones
  var bool IgnoreXAxis; //Ignore this axis when setting active zone
  var bool IgnoreYAxis;
  var bool IgnoreZAxis;
  var bool HideDecorativeActors;
  var bool HidePortalActors;
};
var config array<MyZone> MyZones;

struct MyZonedMap
{
  //Struct for map zoning
  var string MapName;
  var array<int> MyZoneRef; //reference to my zone structure
};
var config array<MyZonedMap> ZonedMaps;

struct ZonedStaticMeshes
{
  var int ZoneRef;
  var array<StaticMeshActor> SMA;
};
var array<ZonedStaticMeshes> ZonedSMA;

var PlayerController PC;
var int ActiveZonedMap;
var int ActiveZone, PrevActiveZone;
var int i, k;

simulated function StartMapOptimizer()
{
  local StaticMeshActor SMA;

  PC = Level.GetLocalPlayerController();
  if(ZonedMaps.length == 0 || MyZones.length == 0 || PC == none || PC.Pawn == none)
    return;

  ActiveZonedMap = -1;
  for(i=0; i<ZonedMaps.length;i++)      //Let's find map profile
  {
    if(PC.Level.GetURLMap() ~= ZonedMaps[i].MapName);
      ActiveZonedMap = i;            //and save it
  }

  if(ActiveZonedMap == -1)    //no profiles for this map
    return;

  for(i=0;i<ZonedMaps[ActiveZonedMap].MyZoneRef.length;i++) //Let's cache static meshes
  {
    ZonedSMA.length = ZonedSMA.length + 1;
    ZonedSMA[ZonedSMA.length-1].ZoneRef = ZonedMaps[ActiveZonedMap].MyZoneRef[i];

    ForEach PC.AllActors(class'StaticMeshActor', SMA)
    {
      if(Sma.bHidden)
        continue;
      if((SMA.Location.X <= MyZones[ZonedMaps[ActiveZonedMap].MyZoneRef[i]].MaxX && SMA.Location.Y <= MyZones[ZonedMaps[ActiveZonedMap].MyZoneRef[i]].MaxY)
                && (SMA.Location.X >= MyZones[ZonedMaps[ActiveZonedMap].MyZoneRef[i]].MinX && SMA.Location.Y >= MyZones[ZonedMaps[ActiveZonedMap].MyZoneRef[i]].MinY))
      {
        ZonedSMA[ZonedSMA.length-1].SMA.length = ZonedSMA[ZonedSMA.length-1].SMA.length + 1;
        ZonedSMA[ZonedSMA.length-1].SMA[ZonedSMA[ZonedSMA.length-1].SMA.length-1] = SMA;
        SMA.bHidden = true;
        SMA.ResetStaticFilterState();
      }
    }
  }
  Enable('Tick');
}

simulated function StopMapOptimizer()
{
  Disable('Tick');
  for(i=0; i<ZonedSMA.length; i++)
  {
    for(k=0;k<ZonedSMA[i].SMA.length;k++)    //show our hided static meshes
    {
      ZonedSMA[i].SMA[k].bHidden=false;
      ZonedSMA[i].SMA[k].ResetStaticFilterState();
    }
  }
  ZonedSMA.length = 0;
}

function Timer(){}

simulated function Tick(float Delta)
{
  if(PC.Pawn == none)      //No pawn no optimizer
    StopMapOptimizer();

  ActiveZone = -1;
  for(i=0;i<ZonedMaps[ActiveZonedMap].MyZoneRef.length;i++)      //Let's find our active zone == where are we now?
  {
    if(PC.Pawn.Location.X > MyZones[ZonedMaps[ActiveZonedMap].MyZoneRef[i]].MinX  && PC.Pawn.Location.Y > MyZones[ZonedMaps[ActiveZonedMap].MyZoneRef[i]].MinY)
    {
      if(PC.Pawn.Location.X < MyZones[ZonedMaps[ActiveZonedMap].MyZoneRef[i]].MaxX && PC.Pawn.Location.Y < MyZones[ZonedMaps[ActiveZonedMap].MyZoneRef[i]].MaxY)
      {
        ActiveZone = ZonedMaps[ActiveZonedMap].MyZoneRef[i];
        break;
      }
    }
  }

  if(ActiveZone == -1 || ZonedSMA.length == 0)    //No active zones - seems like we are out of rectangle borders
    return;

  for(i=0; i<ZonedSMA.length; i++)
  {
    if(ZonedSMA[i].ZoneRef == ActiveZone)    //Let's show our static meshes that situated in our active zone
    {
      if(ZonedSMA[i].SMA[0]!=none && !ZonedSMA[i].SMA[0].bHidden)
        continue;

      For(k=0;k<ZonedSMA[i].SMA.length;k++)
      {
        if(ZonedSMA[i].SMA[k] != none)
        {
          ZonedSMA[i].SMA[k].bHidden=false;
          ZonedSMA[i].SMA[k].ResetStaticFilterState();
        }
        else
        {
          ZonedSMA[i].SMA.Remove(k,1);
        }
      }
    }

    else  //hide statics that was in previous active zone
    {
      if(!ZonedSMA[i].SMA[0].bHidden)
      {
        For(k=0;k<ZonedSMA[i].SMA.length;k++)
        {
          ZonedSMA[i].SMA[k].bHidden=true;
          ZonedSMA[i].SMA[k].ResetStaticFilterState();
        }
      }
    }
  }
}


// self cleanup
function Termination()
{
  pc = none;
  ZonedSMA.length = 0;
  super.Termination();
}

defaultproperties
{
     bUnlit=True
}
