VRAMEditorLayeredGraphicScene::VRAMEditorLayeredGraphicScene(
                  LevelVRAMEditor& parentEditor__,
                  EditableLevelGraphicsData& levelGraphicsData__,
                  EditableLevelPaletteHeaders& paletteHeaders__,
                  EditableStandardPalettes& palettes__,
                  EditableLeafGraphicsTable& leafGraphicsTable__,
                  EditableSmokePuffGraphicTable& smokePuffGraphicTable__,
                  EditableWaterSplashGraphicTable& waterSplashGraphicTable__)
  : LayeredGraphicScene(),
    parentEditor_(parentEditor__),
    levelGraphicsData_(levelGraphicsData__),
    paletteHeaders_(paletteHeaders__),
    palettes_(palettes__),
    leafGraphicsTable_(leafGraphicsTable__),
    smokePuffGraphicTable_(smokePuffGraphicTable__),
    waterSplashGraphicTable_(waterSplashGraphicTable__),
    g_(nativeWidth(),
       nativeHeight()),
    grid_(8,
          1,
          Color(160, 160, 160, Color::fullAlphaOpacity),
          false),
    gridEnabled_(true),
    areaNum_(1),
    mapNum_(1),
    selectionBoxEnabled_(false),
    selectionBoxX_(0),
    selectionBoxY_(0),
    fullSelectionBoxEnabled_(false),
    fullSelectionBoxGraphicIndex_(0),
    tilePickerPreviewEnabled_(false),
    tilePickerPreviewIndex_(0),
    tilePickerPreviewLength_(0),
    showLeaf_(true),
    showSmokePuff_(true),
    showWaterSplash_(true) { };
void ConfigOptions::init()
{
	//Opening ini file
	CSimpleIniA ini;
	ini.SetUnicode();
	ini.SetMultiKey();
	if (ini.LoadFile("Config.ini") == SI_OK)
	{
		/////////////////////GAMEPLAY///////////////////////////////
		//Difficulty
		m_aiThinkingTime = atoi(ini.GetValue("Gameplay", "Difficulty", "1"));
		m_p1AI = ini.GetBoolValue("Gameplay", "Player1AI", 0);
		m_p2AI = ini.GetBoolValue("Gameplay", "Player2AI", 0);
		m_dialogOn = ini.GetBoolValue("Gameplay", "ShowDialog", 0);
		m_autoReset = ini.GetBoolValue("Gameplay", "AutoReset", 0);

		/////////////////////GRAPHICS///////////////////////////////
		//Resoltion
		m_resolution = sf::Vector2i(atoi(ini.GetValue("Graphics", "ScreenWidth", "1920")), atoi(ini.GetValue("Graphics", "ScreenHeight", "1080")));
		m_inFullscreen = ini.GetBoolValue("Graphics", "FullScreen", 0);
		m_view.SetFromRect(sf::FloatRect(0, 0, (float) nativeWidth(), (float) nativeHeight()));

		//////////////////////CONTROLS/////////////////////////////
		std::string item;
		std::string val;

		//Keys
		std::map<std::string, sf::Key::Code> allKeys = getNamedKeys();

		// if there are keys and values...
		const CSimpleIniA::TKeyVal* keys = ini.GetSection("KeyboardControls");
		if (keys)
		{
			// iterate over all keys and dump the key name and value
			for (CSimpleIniA::TKeyVal::const_iterator it = keys->begin() ; it != keys->end() ; ++it)
			{
				item = it->first.pItem;
				val = it->second;
				m_iHandler.map(item, allKeys[val]);
			}
		}

		//Mouse buttons
		std::map<std::string, sf::Mouse::Button> allButtons = getNamedButtons();

		// if there are keys and values...
		const CSimpleIniA::TKeyVal* buttons = ini.GetSection("MouseControls");
		if (keys)
		{
			// iterate over all keys and dump the key name and value
			for (CSimpleIniA::TKeyVal::const_iterator it = buttons->begin() ; it != buttons->end() ; ++it)
			{
				item = it->first.pItem;
				val = it->second;
				m_iHandler.map(item, allButtons[val]);
			}
		}

		//////////////////////OTHER/////////////////////////////

		m_theme = ini.GetValue("Graphics", "Theme", "");
		if (m_theme == "Default") //default theme
			m_theme = "";
	}
	else
	{
		std::cerr << "Unable to load file : Config.ini" << std::endl;
	}
}
void VRAMEditorLayeredGraphicScene::render(
                    Graphic& dst,
                    Box srcbox,
                    double scale) {
  // Create empty graphic with white background (TODO: selectable BG color)
  // The normal background color is black, so unused tiles will show up
  // as white
//  Graphic g(nativeWidth(), nativeHeight());
//  g.clear(Color(0, 0, 0, 0));
  g_.clear();
  
  // Get level graphics header containing graphics to render
  int levelGraphicsHeaderIndex
    = levelGraphicsData_.levelHeaderIndexByMapnum(areaNum_,
                                                  mapNum_);
  LevelGraphicsHeader& levelGraphicsHeader
    = levelGraphicsData_.levelGraphicsHeader(levelGraphicsHeaderIndex);
    
  // Look up palette header for this level
  LevelPaletteHeader& levelPaletteHeader
    = paletteHeaders_.headerByIndex(
        paletteHeaders_.indexOfMapNum(areaNum_,
                                      mapNum_));
  
  // Get level palettes
  GGPalette palette0
    = palettes_.palette(levelPaletteHeader.palette0Index());
  GGPalette palette1
    = palettes_.palette(levelPaletteHeader.palette1Index());
  
  // Get map graphic index
  int mapGraphicIndex = levelGraphicsHeader.mapGraphicIndex();
  
  // Get map graphic
  GGTileSet mapGraphic
    = levelGraphicsData_.compressedGraphic(mapGraphicIndex);
  
  // Get index of the start of the map tiles
  int mapTileIndex
    = vramAddressToTileIndex(levelGraphicsHeader.vdpWriteAddress());
    
  // Render map graphic
  renderTiles(g_,
              mapTileIndex,
              mapGraphic,
              palette0,
              Graphic::noTileTrans);
    
  // Get object graphics header index
  int objectGraphicsHeaderIndex
    = levelGraphicsHeader.objectGraphicsHeaderIndex();
    
  // Get object graphics header
  ObjectGraphicsHeader& objectGraphicsHeader
    = levelGraphicsData_.objectGraphicsHeader(objectGraphicsHeaderIndex);
    
  // Iterate over graphics subheaders and add object graphics to render
  for (int i = 0; i < objectGraphicsHeader.size(); i++) {
    ObjectGraphicSubheader& subheader
      = objectGraphicsHeader.subheader(i);
    
    int objectGraphicIndex = subheader.objectGraphicIndex();
    
    // Get graphic
    GGTileSet objectGraphic
      = levelGraphicsData_.compressedGraphic(objectGraphicIndex);
      
    // Flip tiles if horizontal flip flag is set
    if (subheader.substitutionOption()
          == ObjectGraphicSubheader::substitutionEnabled) {
      for (int j = 0; j < objectGraphic.numTiles(); j++) {
        objectGraphic[j].flipHorizontal();
      }
    }
    
    // Get index of the tile
    int tileIndex = vramAddressToTileIndex(subheader.vdpWriteAddress());
    
    // Render object graphic.
    // Use palette 1 (sprite palette) for objects.
    // Technically we "should" use transparency here, but it's possible
    // to overwrite one graphic with another and we don't want to leave
    // scraps of the previous graphic visible when that happens.
    // TODO: add some concept of background color (maybe change color 0
    // in palette?)
    renderTiles(g_,
                tileIndex,
                objectGraphic,
                palette1,
                Graphic::noTileTrans);
    
    // Draw full graphic selection box if enabled and needed
    // (this will be scaled with the graphic, negating the benefits of vector-
    // based drawing!)
    if ((i == fullSelectionBoxGraphicIndex_)
        && fullSelectionBoxEnabled_) {
        
/*      // Draw line on left side of first tile
      int firstXPos = tileIndexToXPos(tileIndex);
      int firstYPos = tileIndexToYPos(tileIndex);
      g.drawLine(firstXPos, firstYPos,
                 firstXPos, firstYPos + GGTile::height,
                 Color(255, 255, 255, Color::fullAlphaOpacity),
                 2,
                 Graphic::noTransUpdate);
        
      // Draw line on right side of last tile
      int lastXPos = tileIndexToXPos(tileIndex + objectGraphic.numTiles());
      int lastYPos = tileIndexToYPos(tileIndex + objectGraphic.numTiles());
      g.drawLine(lastXPos + GGTile::width, lastYPos,
                 lastXPos + GGTile::width, lastYPos + GGTile::height,
                 Color(255, 255, 255, Color::fullAlphaOpacity),
                 2,
                 Graphic::noTransUpdate);
      
      // Box each tile in the graphic
      for (int j = 0; j < objectGraphic.numTiles(); j++) {
        // Calculate position in Graphic
        int xPos = tileIndexToXPos(tileIndex);
        int yPos = tileIndexToYPos(tileIndex);
        
        // Draw lines above and below tile
        g.drawLine(xPos, yPos,
                   xPos + GGTile::width, yPos,
                   Color(255, 255, 255, Color::fullAlphaOpacity),
                   2,
                   Graphic::noTransUpdate);
        g.drawLine(xPos, yPos + GGTile::height,
                   xPos + GGTile::width, yPos + GGTile::height,
                   Color(255, 255, 255, Color::fullAlphaOpacity),
                   2,
                   Graphic::noTransUpdate);
        
        // Move to next tile position
        ++tileIndex;
      } */
      
/*      for (int j = 0; j < objectGraphic.numTiles(); j++) {
        // Calculate position in Graphic
        int xPos = tileIndexToXPos(tileIndex + j);
        int yPos = tileIndexToYPos(tileIndex + j);
        BoxGraphicSceneObject box(Color(255, 0, 255, Color::fullAlphaOpacity),
                                  2,
                                  GGTile::width,
                                  GGTile::height,
                                  xPos,
                                  yPos,
                                  true);
        
        box.render(g,
                   Box(0, 0, dst.w(), dst.h()),
                   1.00);
      } */
    }
  }
    
/*  GenericGraphicSceneLayer graphics;
  Graphic testG(nativeWidth(), nativeHeight());
  renderTiles(testG,
              0,
              mapGraphic,
              palette0,
              Graphic::noTileTrans);
  BitmapGraphicSceneObject* testBitmap
    = new BitmapGraphicSceneObject(testG,
                           0,
                           0,
                           true);
  graphics.addObject(testBitmap);
  graphics.render(g,
                  Box(0, 0, nativeWidth(), nativeHeight()),
                  1.00,
                  1.00); */
                  
/*  GenericGraphicSceneLayer graphics;
  BoxGraphicSceneObject* testBox
    = new BoxGraphicSceneObject(Color(255, 0, 0, 0),
                                3,
                                45,
                                45,
                                20,
                                20,
                                true);
  graphics.addObject(testBox);
  graphics.render(g,
                  Box(0, 0, nativeWidth(), nativeHeight()),
                  3.00,
                  1.00); */
              
  int width = srcbox.w();
  int height = srcbox.h();
  
  // If width or height parameter is zero, replace with maximum
  if (width == 0) {
    width = nativeWidth();
  }
  
  if (height == 0) {
    height = nativeHeight();
  }
              
  // Crop if necessary
  if ((srcbox.x() != 0) || (srcbox.y() != 0)) {
    Graphic tmp(width, height);
    
    // Copy desired portion to temp graphic
    tmp.copy(g_,
             Box(0, 0, width, height),
             Box(srcbox.x(),
                 srcbox.y(),
                 width,
                 height),
             Graphic::noTransUpdate);
             
    // Copy temp graphic to primary
    g_ = tmp;
  }
  
  // Scale graphic if necessary
  if (scale == 1.00) {
    dst = g_;
  }
  else {
//    dst = Graphic(width * scale, height * scale);
    g_.scale(dst,
             Box(0, 0, width * scale, height * scale),
             Graphic::noTransUpdate);
  }
    
  // Draw grid if enabled
  if (gridEnabled_) {
    grid_.render(dst,
                 Box(srcbox.x(),
                     srcbox.y(),
                     width * scale,
                     height * scale),
                 scale);
  }
  
  if (EditorMetadata::areaNumHasVRAMIndices(areaNum_)) {
//    std::cerr << areaNum_ << " " << mapNum_ << std::endl;
    // Draw leaf box if enabled
    if (showLeaf_) {
      boxGenericLength(dst,
                       leafGraphicsTable_.entry(areaNum_),
                       EditableLeafGraphicsTable::numGraphicTiles,
                       leafBoxColor,
                       2,
                       scale);
    }
    
    // Draw water splash box if enabled
    if (showWaterSplash_) {
      boxGenericLength(dst,
                       waterSplashGraphicTable_.entry(areaNum_, mapNum_)
                        .leftTileIndex(),
                       EditableWaterSplashGraphicTable::numGraphicTiles,
                       waterSplashBoxColor,
                       2,
                       scale);
    }
    
    // Draw smoke puff box if enabled
    if (showSmokePuff_) {
      boxGenericLength(dst,
                       smokePuffGraphicTable_.entry(areaNum_, mapNum_)
                        .leftTileIndex(),
                       EditableSmokePuffGraphicTable::numGraphicTiles,
                       smokePuffBoxColor,
                       2,
                       scale);
    }
  }
  
  // Draw full graphic selection box if enabled
  if (fullSelectionBoxEnabled_) {
    ObjectGraphicSubheader& subheader
      = objectGraphicsHeader.subheader(fullSelectionBoxGraphicIndex_);
    
    int tileIndex = vramAddressToTileIndex(subheader.vdpWriteAddress());
    GGTileSet objectGraphic
      = levelGraphicsData_.compressedGraphic(
          subheader.objectGraphicIndex());
    
    // Box each tile in the graphic
    for (int i = 0; i < objectGraphic.numTiles(); i++) {
      // Calculate position in Graphic
      int xPos = tileIndexToXPos(tileIndex);
      int yPos = tileIndexToYPos(tileIndex);
    
      BoxGraphicSceneObject box(fullGraphicSelectionBoxColor,
                                2,
                                GGTile::width * scale,
                                GGTile::height * scale,
                                xPos * scale,
                                yPos * scale,
                                true);
      
      box.render(dst,
                 Box(0, 0, dst.w(), dst.h()),
                 1.00);
      
      // Move to next tile position
      ++tileIndex;
    }
  }
  
  // Draw selection box if enabled
  if (selectionBoxEnabled_) {
    BoxGraphicSceneObject box(selectionBoxColor,
                              3,
                              GGTile::width * scale,
                              GGTile::height * scale,
                              (selectionBoxX_ - srcbox.x())
                                * GGTile::width * scale,
                              (selectionBoxY_ - srcbox.y())
                                * GGTile::height * scale,
                              true);
    
    box.render(dst,
               Box(0, 0, dst.w(), dst.h()),
               1.00);
  }
  
  // Draw tile picker selection box if enabled
  if (tilePickerPreviewEnabled_) {
      boxGenericLength(dst,
                       tilePickerPreviewIndex_,
                       tilePickerPreviewLength_,
                       tilePickerPreviewColor_,
                       2,
                       scale);
  }
}