Subversion Repositories Games.Chess Giants

Rev

Rev 11 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. // main.cpp
  2.  
  3. #include "common.h"
  4.  
  5.  
  6. bool Themes_Init (void)
  7. {
  8.    // this function (re)builds the themes array and loads all the themes' data
  9.  
  10.    wchar_t search_pattern[256];
  11.    WIN32_FIND_DATA wfd;
  12.    HANDLE hFind;
  13.    int selectedtheme_index;
  14.  
  15.    // start by resetting the themes array
  16.    themes = NULL;
  17.    theme_count = 0;
  18.  
  19.    // the selected them isn't known yet
  20.    selectedtheme_index = -1;
  21.  
  22.    // build the search pattern string out of the path and initiate the search from that point
  23.    swprintf_s (search_pattern, WCHAR_SIZEOF (search_pattern), L"%s\\themes\\*.*", app_path);
  24.    hFind = FindFirstFile (search_pattern, &wfd);
  25.    if (hFind != INVALID_HANDLE_VALUE)
  26.    {
  27.       // start doing this...
  28.       do
  29.       {
  30.          // is it this directory or the parent directory ?
  31.          if ((wcscmp (wfd.cFileName, L".") == 0) || (wcscmp (wfd.cFileName, L"..") == 0))
  32.             continue; // skip that entry
  33.  
  34.          // is it a directory ?
  35.          if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  36.          {
  37.             // reallocate space for one theme more (zero out the allocated space) and copy it in place
  38.             themes = (theme_t *) SAFE_realloc (themes, theme_count, theme_count + 1, sizeof (theme_t), true);
  39.             wcscpy_s (themes[theme_count].name, WCHAR_SIZEOF (themes[theme_count].name), wfd.cFileName);
  40.             theme_count++; // we know now one theme more
  41.  
  42.             // is it the selected theme ?
  43.             if (_wcsicmp (wfd.cFileName, wantedtheme_name) == 0)
  44.             {
  45.                Theme_Load (&themes[theme_count - 1], true); // load ALL the theme data from this directory
  46.                selectedtheme_index = theme_count - 1; // remember the selected theme is this one
  47.             }
  48.          }
  49.       } while (FindNextFile (hFind, &wfd)); // ...and don't stop as long as there are files to go
  50.  
  51.       FindClose (hFind); // close the search handle
  52.    }
  53.  
  54.    // consistency check: we need at least one theme
  55.    if (theme_count == 0)
  56.    {
  57.       MessageBox (NULL, LOCALIZE (L"Error_UnableToLoadThemes"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK);
  58.       return (false); // if none of these extensions match, bomb out
  59.    }
  60.  
  61.    // have we found the selected theme ?
  62.    if (selectedtheme_index != -1)
  63.       theme = &themes[selectedtheme_index]; // found it, so link it
  64.    else
  65.    {
  66.       Theme_Load (&themes[0], true); // not found, so load the first available theme
  67.       theme = &themes[0]; // and link selected theme to it
  68.    }
  69.  
  70.    // if we have a custom background specified, load it too
  71.    if (custombackground_pathname[0] != 0)
  72.       Background_LoadImage (&custombg, custombackground_pathname);
  73.  
  74.    return (true); // at least one theme has been loaded successfully, return TRUE
  75. }
  76.  
  77.  
  78. void Themes_Shutdown (void)
  79. {
  80.    // helper function to release the themes structures array
  81.  
  82.    int theme_index;
  83.  
  84.    // before freeing the themes array, backup our theme's name
  85.    wcscpy_s (wantedtheme_name, WCHAR_SIZEOF (wantedtheme_name), theme->name);
  86.  
  87.    // for each theme, free its mallocated data
  88.    for (theme_index = 0; theme_index < theme_count; theme_index++)
  89.    {
  90.       SAFE_free ((void **) &theme->description); // free its description
  91.  
  92.       SAFE_free ((void **) &themes[theme_index].illum.lights); // free the lights array
  93.       themes[theme_index].illum.light_count = 0;
  94.    }
  95.  
  96.    // free the themes array
  97.    SAFE_free ((void **) &themes);
  98.    theme_count = 0;
  99.  
  100.    return; // nothing to do
  101. }
  102.  
  103.  
  104. void Theme_Load (theme_t *theme, bool want_all)
  105. {
  106.    // this function loads a particular theme out of a theme subdirectory's files
  107.  
  108.    #define THEME_LOAD_STEP(id) if ((theme->load_index == (id)) || (want_all && (theme->load_index < ((id) + 1))))
  109.    #define THEME_LOAD_TEXTURE(varname,texture_name) \
  110.    { \
  111.       theme->varname = Render_LoadTexture (L"%s/themes/%s/" texture_name L".*", app_path, theme->name); \
  112.       if (theme->varname == -1) \
  113.          MessageBox (NULL, LOCALIZE (L"Error_UnableToAddTextureD3DXCreateTextureFromFileFailed"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); \
  114.    }
  115.    #define THEME_LOAD_MESH(varname,mesh_name) \
  116.    { \
  117.       theme->varname = Render_LoadMesh (L"%s/themes/%s/" mesh_name L".*", app_path, theme->name); \
  118.       if (theme->varname == -1) \
  119.          MessageBox (NULL, LOCALIZE (L"Error_UnableToAddMeshD3DXLoadMeshFromXFailed"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); \
  120.    }
  121.    #define THEME_LOAD_SPRITE(varname,sprite_name) \
  122.    { \
  123.       theme->varname = Render_LoadSprite (L"%s/themes/%s/" sprite_name L".*", app_path, theme->name); \
  124.       if (theme->varname == -1) \
  125.          MessageBox (NULL, LOCALIZE (L"Error_UnableToAddSpriteD3DXCreateSpriteFailed"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); \
  126.    }
  127.    #define THEME_LOAD_PART(part_id,part_name) \
  128.    { \
  129.       theme->part_meshes[part_id] = -1; \
  130.       if (options.want_hiquality) \
  131.          theme->part_meshes[part_id] = Render_LoadMesh (L"%s/themes/%s/" part_name L"-hidef.*", app_path, theme->name); \
  132.       if (theme->part_meshes[part_id] == -1) \
  133.          theme->part_meshes[part_id] = Render_LoadMesh (L"%s/themes/%s/" part_name L".*", app_path, theme->name); \
  134.       if (theme->part_meshes[part_id] == -1) \
  135.          MessageBox (NULL, LOCALIZE (L"Error_UnableToAddMeshD3DXLoadMeshFromXFailed"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); \
  136.    }
  137.  
  138.    unsigned long file_size;
  139.    char *desc_buffer;
  140.    wchar_t filename[256];
  141.    wchar_t section_name[32];
  142.    wchar_t value[128];
  143.    light_t light;
  144.    void *inifile;
  145.    int light_index;
  146.    int light_count;
  147.    int length;
  148.    int pos;
  149.    int red;
  150.    int green;
  151.    int blue;
  152.    FILE *fp;
  153.  
  154.    // allocate space for and load its description
  155.    swprintf_s (filename, WCHAR_SIZEOF (filename), L"%s/themes/%s/readme.txt", app_path, theme->name);
  156.    _wfopen_s (&fp, filename, L"rb");
  157.    if (fp != NULL)
  158.    {
  159.       fseek (fp, 0, SEEK_END); // seek at end of file
  160.       file_size = ftell (fp); // get file size
  161.       fseek (fp, 0, SEEK_SET); // and rewind
  162.       if (file_size > 0)
  163.       {
  164.          desc_buffer = (char *) SAFE_malloc (file_size, sizeof (char), false);
  165.          fread (desc_buffer, file_size, 1, fp); // read file in whole in ASCII form
  166.          fclose (fp); // close it and then convert it to wide char
  167.          theme->description = (wchar_t *) SAFE_malloc (file_size, sizeof (wchar_t), false);
  168.          ConvertToWideChar (theme->description, file_size, desc_buffer);
  169.          SAFE_free ((void **) &desc_buffer); // we no longer need the ASCII buffer
  170.       }
  171.       else
  172.          theme->description = NULL; // this theme has no description
  173.       fclose (fp);
  174.    }
  175.  
  176.    // load its background image
  177.    THEME_LOAD_STEP (0) Background_LoadImage (&theme->bg, L"%s/themes/%s/background/background.*", app_path, theme->name);
  178.  
  179.    // load board meshes
  180.    THEME_LOAD_STEP (1) THEME_LOAD_MESH (board_meshindex, L"models/board");
  181.    THEME_LOAD_STEP (2) THEME_LOAD_MESH (table_meshindex, L"models/table");
  182.    THEME_LOAD_STEP (3) THEME_LOAD_MESH (trim_meshindex, L"models/trim");
  183.    THEME_LOAD_STEP (4) THEME_LOAD_MESH (tile_meshindex, L"models/tile");
  184.  
  185.    // load part meshes
  186.    THEME_LOAD_STEP (5) THEME_LOAD_PART (PART_KING, L"models/king");
  187.    THEME_LOAD_STEP (6) THEME_LOAD_PART (PART_QUEEN, L"models/queen");
  188.    THEME_LOAD_STEP (7) THEME_LOAD_PART (PART_BISHOP, L"models/bishop");
  189.    THEME_LOAD_STEP (8) THEME_LOAD_PART (PART_KNIGHT, L"models/knight");
  190.    THEME_LOAD_STEP (9) THEME_LOAD_PART (PART_ROOK, L"models/rook");
  191.    THEME_LOAD_STEP (10) THEME_LOAD_PART (PART_PAWN, L"models/pawn");
  192.  
  193.    // load part textures
  194.    THEME_LOAD_STEP (11) THEME_LOAD_TEXTURE (part_colors[COLOR_BLACK].texture, L"models/part-black");
  195.    THEME_LOAD_STEP (12) THEME_LOAD_TEXTURE (part_colors[COLOR_WHITE].texture, L"models/part-white");
  196.  
  197.    // load board, table, grid and trim textures
  198.    THEME_LOAD_STEP (13) THEME_LOAD_TEXTURE (board_texture, L"models/board");
  199.    THEME_LOAD_STEP (14) THEME_LOAD_TEXTURE (table_texture, L"models/table");
  200.    THEME_LOAD_STEP (15) THEME_LOAD_TEXTURE (trim_texture, L"models/trim");
  201.    THEME_LOAD_STEP (16) THEME_LOAD_TEXTURE (grid_texture, L"models/grid");
  202.  
  203.    // load overlay textures
  204.    THEME_LOAD_STEP (17) THEME_LOAD_TEXTURE (shadow_textureindex, L"shadow");
  205.    THEME_LOAD_STEP (18) THEME_LOAD_TEXTURE (hovered_textureindex, L"hovered");
  206.    THEME_LOAD_STEP (19) THEME_LOAD_TEXTURE (check_textureindex, L"check");
  207.    THEME_LOAD_STEP (20) THEME_LOAD_TEXTURE (threat_textureindex, L"takeable");
  208.    THEME_LOAD_STEP (21) THEME_LOAD_TEXTURE (lastmovesource_textureindex, L"lastmovesource");
  209.    THEME_LOAD_STEP (22) THEME_LOAD_TEXTURE (lastmovetarget_textureindex, L"lastmovetarget");
  210.    THEME_LOAD_STEP (23) THEME_LOAD_TEXTURE (selected_textureindex, L"selected");
  211.    THEME_LOAD_STEP (24) THEME_LOAD_TEXTURE (possiblemove_textureindex, L"possiblemove");
  212.    THEME_LOAD_STEP (25) THEME_LOAD_TEXTURE (takeable_textureindex, L"takeable");
  213.  
  214.    // load sprites
  215.    THEME_LOAD_STEP (26) THEME_LOAD_SPRITE (flatsprites[COLOR_WHITE][PART_PAWN], L"parts/pawn-white");
  216.    THEME_LOAD_STEP (27) THEME_LOAD_SPRITE (flatsprites[COLOR_WHITE][PART_ROOK], L"parts/rook-white");
  217.    THEME_LOAD_STEP (28) THEME_LOAD_SPRITE (flatsprites[COLOR_WHITE][PART_KNIGHT], L"parts/knight-white");
  218.    THEME_LOAD_STEP (29) THEME_LOAD_SPRITE (flatsprites[COLOR_WHITE][PART_BISHOP], L"parts/bishop-white");
  219.    THEME_LOAD_STEP (30) THEME_LOAD_SPRITE (flatsprites[COLOR_WHITE][PART_QUEEN], L"parts/queen-white");
  220.    THEME_LOAD_STEP (31) THEME_LOAD_SPRITE (flatsprites[COLOR_WHITE][PART_KING], L"parts/king-white");
  221.    THEME_LOAD_STEP (32) THEME_LOAD_SPRITE (flatsprites[COLOR_BLACK][PART_PAWN], L"parts/pawn-black");
  222.    THEME_LOAD_STEP (33) THEME_LOAD_SPRITE (flatsprites[COLOR_BLACK][PART_ROOK], L"parts/rook-black");
  223.    THEME_LOAD_STEP (34) THEME_LOAD_SPRITE (flatsprites[COLOR_BLACK][PART_KNIGHT], L"parts/knight-black");
  224.    THEME_LOAD_STEP (35) THEME_LOAD_SPRITE (flatsprites[COLOR_BLACK][PART_BISHOP], L"parts/bishop-black");
  225.    THEME_LOAD_STEP (36) THEME_LOAD_SPRITE (flatsprites[COLOR_BLACK][PART_QUEEN], L"parts/queen-black");
  226.    THEME_LOAD_STEP (37) THEME_LOAD_SPRITE (flatsprites[COLOR_BLACK][PART_KING], L"parts/king-black");
  227.    THEME_LOAD_STEP (38) THEME_LOAD_SPRITE (lastmovesource_spriteindex, L"lastmovesource");
  228.    THEME_LOAD_STEP (39) THEME_LOAD_SPRITE (lastmovetarget_spriteindex, L"lastmovetarget");
  229.  
  230.    // load the flat pieces textures
  231.    THEME_LOAD_STEP (40) THEME_LOAD_TEXTURE (flattextures[COLOR_WHITE][PART_PAWN], L"parts/pawn-white");
  232.    THEME_LOAD_STEP (41) THEME_LOAD_TEXTURE (flattextures[COLOR_WHITE][PART_ROOK], L"parts/rook-white");
  233.    THEME_LOAD_STEP (42) THEME_LOAD_TEXTURE (flattextures[COLOR_WHITE][PART_KNIGHT], L"parts/knight-white");
  234.    THEME_LOAD_STEP (43) THEME_LOAD_TEXTURE (flattextures[COLOR_WHITE][PART_BISHOP], L"parts/bishop-white");
  235.    THEME_LOAD_STEP (44) THEME_LOAD_TEXTURE (flattextures[COLOR_WHITE][PART_QUEEN], L"parts/queen-white");
  236.    THEME_LOAD_STEP (45) THEME_LOAD_TEXTURE (flattextures[COLOR_WHITE][PART_KING], L"parts/king-white");
  237.    THEME_LOAD_STEP (46) THEME_LOAD_TEXTURE (flattextures[COLOR_BLACK][PART_PAWN], L"parts/pawn-black");
  238.    THEME_LOAD_STEP (47) THEME_LOAD_TEXTURE (flattextures[COLOR_BLACK][PART_ROOK], L"parts/rook-black");
  239.    THEME_LOAD_STEP (48) THEME_LOAD_TEXTURE (flattextures[COLOR_BLACK][PART_KNIGHT], L"parts/knight-black");
  240.    THEME_LOAD_STEP (49) THEME_LOAD_TEXTURE (flattextures[COLOR_BLACK][PART_BISHOP], L"parts/bishop-black");
  241.    THEME_LOAD_STEP (50) THEME_LOAD_TEXTURE (flattextures[COLOR_BLACK][PART_QUEEN], L"parts/queen-black");
  242.    THEME_LOAD_STEP (51) THEME_LOAD_TEXTURE (flattextures[COLOR_BLACK][PART_KING], L"parts/king-black");
  243.  
  244.    //////////////////////////////
  245.    // read scene lights from file
  246.  
  247.    THEME_LOAD_STEP (52)
  248.    {
  249.       theme->illum.lights = NULL; // no lights for the scene so far
  250.       theme->illum.light_count = 0; // reset the known lights count
  251.  
  252.       // open the INI file
  253.       swprintf_s (filename, WCHAR_SIZEOF (filename), L"%s/themes/%s/lights.ini", app_path, theme->name);
  254.       inifile = INIFile_LoadINIFile (filename);
  255.  
  256.       // read the global light values and the parts illumination values
  257.       swscanf_s (INIFile_ReadEntryAsString (inifile, L"global", L"ambient light", L"50, 50, 50"), L"%d , %d , %d", &red, &green, &blue);
  258.       theme->illum.ambient_light = RGB_TO_RGBACOLOR (red, green, blue);
  259.       theme->board_material = Render_MaterialIndexOf (INIFile_ReadEntryAsString (inifile, L"global", L"board material", L"default"));
  260.       theme->table_material = Render_MaterialIndexOf (INIFile_ReadEntryAsString (inifile, L"global", L"table material", L"default"));
  261.       theme->trim_material = -1; // TODO: make customizable
  262.       theme->reflection_alpha = (unsigned char) INIFile_ReadEntryAsLong (inifile, L"global", L"table reflection alpha", 50);
  263.       theme->part_colors[COLOR_BLACK].material = Render_MaterialIndexOf (INIFile_ReadEntryAsString (inifile, L"global", L"black material", L"default"));
  264.       theme->part_colors[COLOR_WHITE].material = Render_MaterialIndexOf (INIFile_ReadEntryAsString (inifile, L"global", L"white material", L"default"));
  265.  
  266.       // figure out the number of lights in this file
  267.       light_count = INIFile_GetNumberOfSections (inifile) - 1; // deduce the [global] section
  268.  
  269.       // for each light section...
  270.       for (light_index = 0; light_index < light_count; light_index++)
  271.       {
  272.          swprintf_s (section_name, WCHAR_SIZEOF (section_name), L"light %d", light_index + 1); // build section name
  273.          memset (&light, 0, sizeof (light)); // wipe out temporary light structure
  274.  
  275.          // get this light parameters
  276.          wcscpy_s (value, WCHAR_SIZEOF (value), INIFile_ReadEntryAsString (inifile, section_name, L"type", L""));
  277.          if (_wcsicmp (value, L"directional") == 0)
  278.             light.type = LIGHT_DIRECTIONAL;
  279.          else if (_wcsicmp (value, L"point") == 0)
  280.             light.type = LIGHT_POINT;
  281.          else if (_wcsicmp (value, L"spot") == 0)
  282.             light.type = LIGHT_SPOT;
  283.          else
  284.             continue; // on invalid data, skip this section
  285.          swscanf_s (INIFile_ReadEntryAsString (inifile, section_name, L"color", L"0, 0, 0"), L"%d , %d , %d", &red, &green, &blue);
  286.          light.color = RGB_TO_RGBACOLOR (red, green, blue);
  287.          swscanf_s (INIFile_ReadEntryAsString (inifile, section_name, L"source", L"0.0, 0.0, 0.0"), L"%f , %f , %f", &light.pos_x, &light.pos_y, &light.pos_z);
  288.          swscanf_s (INIFile_ReadEntryAsString (inifile, section_name, L"direction", L"0.0, 0.0, 0.0"), L"%f , %f , %f", &light.direction_x, &light.direction_y, &light.direction_z);
  289.          light.range = (float) INIFile_ReadEntryAsDouble (inifile, section_name, L"range", 0.0);
  290.          swscanf_s (INIFile_ReadEntryAsString (inifile, section_name, L"attenuation", L"0.0, 0.0, 0.0"), L"%f , %f , %f", &light.attenuation_constant, &light.attenuation_proportional, &light.attenuation_square);
  291.          swscanf_s (INIFile_ReadEntryAsString (inifile, section_name, L"cone", L"0.0, 0.0"), L"%f , %f", &light.cone_inner, &light.cone_outer);
  292.  
  293.          // reallocate the lights array to hold one light more
  294.          theme->illum.lights = (light_t *) SAFE_realloc (theme->illum.lights, theme->illum.light_count, theme->illum.light_count + 1, sizeof (light_t), false);
  295.          memcpy (&theme->illum.lights[theme->illum.light_count], &light, sizeof (light_t)); // copy light in place
  296.          theme->illum.light_count++; // we know now one light more
  297.       }
  298.  
  299.       // close the INI file
  300.       INIFile_FreeINIFile (inifile);
  301.    }
  302.  
  303.    theme->load_index++; // this bit has been loaded
  304.    if (theme->load_index == 53)
  305.       theme->is_loaded = true; // when everything has been loaded, remember this theme is now usable
  306.  
  307.    return; // finished, theme data is loaded a bit more
  308.  
  309.    #undef THEME_LOAD_PART
  310.    #undef THEME_LOAD_SPRITE
  311.    #undef THEME_LOAD_MESH
  312.    #undef THEME_LOAD_TEXTURE
  313.    #undef THEME_LOAD_STEP
  314. }
  315.  
  316.  
  317. void Background_LoadImage (backgroundsprite_t *bg, const wchar_t *fmt, ...)
  318. {
  319.    // this function loads the specified background image for the specified theme
  320.  
  321.    static wchar_t bgimage_pathname[MAX_PATH];
  322.    va_list argptr;
  323.    int width;
  324.    int height;
  325.  
  326.    // concatenate all the arguments in one string
  327.    va_start (argptr, fmt);
  328.    wvsprintf (bgimage_pathname, fmt, argptr);
  329.    va_end (argptr);
  330.  
  331.    // does the background file look like an image we can comprehend ? try to get its width and height
  332.    if (GetImageSize (bgimage_pathname, &width, &height))
  333.    {
  334.       // yes it is, so load it as our background and round its size to the highest multiple of two
  335.       bg->sprite_width = 2;
  336.       while (bg->sprite_width < width)
  337.          bg->sprite_width *= 2; // save them rounded to the next power of two
  338.       bg->sprite_height = 2;
  339.       while (bg->sprite_height < height)
  340.          bg->sprite_height *= 2; // save them rounded to the next power of two
  341.  
  342.       bg->sprite_index = Render_LoadSprite (bgimage_pathname); // load texture as sprite
  343.    }
  344.    else
  345.    {
  346.       // no it's not, so load a default texture
  347.       bg->sprite_index = Render_LoadSprite (L"%s/data/notexture.png", app_path);
  348.       bg->sprite_width = 2;
  349.       bg->sprite_height = 2;
  350.    }
  351.  
  352.    return; // finished, theme background image is loaded
  353. }
  354.