diff --git a/includes/defaults.php b/includes/defaults.php
index 95536674..ceb65259 100644
--- a/includes/defaults.php
+++ b/includes/defaults.php
@@ -73,12 +73,16 @@ $s['file_exts'] = array('png');
$s['dir_data'] = './data/';
// File containing Pokémon data
$s['file_pkmn_data'] = 'pkmn.json';
+// File containing data for other icons
+$s['file_icon_data'] = 'item-icons.json';
// Output directory (created if nonexistent)
$s['dir_output'] = './output/';
// Mode at which the directory is created
$s['dir_mode'] = 0777;
// If set, which Pokémon to include (debugging only)
$s['pkmn_range'] = null;
+// If set, which icons to include (debugging only)
+$s['icon_range'] = null;
// Whether to index numbers instead of slugs in the overview (debugging only)
$s['html_no_slugs'] = false;
// Github project base directory
diff --git a/includes/i18n.php b/includes/i18n.php
index ab595e9e..6c74a63c 100644
--- a/includes/i18n.php
+++ b/includes/i18n.php
@@ -46,7 +46,9 @@ class I18n
'no_cli' => "We don't seem to be running via the command line. Keep in mind this tool was designed for command line usage, and hasn't been tested in other situations.\n",
'pngcrush_missing' => "pngcrush seems to be missing (path: %s). By default, it needs to be in the tools directory, chmodded to be executable, and at least version 1.7.60.\nImage will not be optimized by pngcrush.\n",
'no_images' => "Couldn't find the source images. Make sure they're in %sregular/ and %sshiny/.\n",
+ 'no_icon_images' => "Couldn't find the icon images.\n",
'no_data' => "Couldn't find the Pokémon data file. Make sure it's named %s and is placed in the %s directory.\n",
+ 'no_icons_data' => "Couldn't find the icons data file. Make sure it's named %s and is placed in the %s directory.\n",
'sprite_stats' => "\nGenerating %dx%d sprite composed of %d images.\nMemory usage will be about %s.\n",
'sprite_ready' => "\nFinished preparing the sprite image.\n",
'sprite_saving' => "Saving sprite image to %s.\n",
@@ -97,7 +99,9 @@ class I18n
'no_cli' => "We don't seem to be running via the command line. Keep in mind this tool was designed for command line usage, and hasn't been tested in other situations.\n",
'pngcrush_missing' => "pngcrush seems to be missing (path: %s). By default, it needs to be in the tools directory, chmodded to be executable, and at least version 1.7.60.\nImage will not be optimized by pngcrush.\n",
'no_images' => "Couldn't find the source images. Make sure they're in %sregular/ and %sshiny/.\n",
+ 'no_icon_images' => "Couldn't find the icon images.\n",
'no_data' => "Couldn't find the Pokémon data file. Make sure it's named %s and is placed in the %s directory.\n",
+ 'no_icons_data' => "Couldn't find the icons data file. Make sure it's named %s and is placed in the %s directory.\n",
'sprite_stats' => "\nGenerating %dx%d sprite composed of %d images.\nMemory usage will be about %s.\n",
'sprite_ready' => "\nFinished preparing the sprite image.\n",
'sprite_saving' => "Saving sprite image to %s.\n",
diff --git a/includes/iconstack.php b/includes/iconstack.php
index 43bec36c..156769a8 100644
--- a/includes/iconstack.php
+++ b/includes/iconstack.php
@@ -16,7 +16,9 @@ class IconStack
{
/** @var mixed[] Pokémon data. */
public $pkmn_data = array();
-
+ /** @var mixed[] Icon data. */
+ public $icon_data = array();
+
/** @var int Pokémon sprite image width. */
public $pkmn_img_width;
/** @var int Pokémon sprite image height. */
@@ -25,10 +27,10 @@ class IconStack
public $pkmn_img_padding;
/** @var int Amount of sprite images in one row. */
public $pkmn_row_count;
-
+
/** @var string[] Sprite versions to include (regular, shiny). */
public $versions = array();
-
+
/** @var int Stack counter. */
private $counter = 0;
/** @var mixed[] Pokémon sprite stack. */
@@ -43,12 +45,12 @@ class IconStack
public $etc_sect_width = 0;
/** @var int Etc sprite stack height. */
public $etc_sect_height = 0;
-
+
/** @var mixed[] Icon set sizes. */
public $set_sizes = array();
/** @var mixed[] Icon data. */
public $type_tree = array();
-
+
/**
* Initializes a number of variables from the settings file.
*/
@@ -66,7 +68,7 @@ class IconStack
$this->pkmn_img_width += $this->pkmn_img_padding;
$this->pkmn_img_height += $this->pkmn_img_padding;
}
-
+
/**
* Get icon stack of all icons besides Pokémon sprites.
*
@@ -79,7 +81,7 @@ class IconStack
}
return $this->etc_stack;
}
-
+
/**
* Get all icons.
*
@@ -89,7 +91,7 @@ class IconStack
{
return array_merge($this->pkmn_stack, $this->etc_stack);
}
-
+
/**
* Get icon set info.
*
@@ -102,7 +104,7 @@ class IconStack
}
return $this->etc_sets;
}
-
+
/**
* Creates a special type of data structure specially suited
* for the SCSS styler, JS generator and overview generator.
@@ -111,7 +113,7 @@ class IconStack
{
$icons = $this->get_all_icons();
$pkmn_sect_size = $this->get_pkmn_icon_stack_size();
-
+
$tree = array();
foreach ($icons as $icon) {
$subvariation = $icon['subvariation'];
@@ -120,13 +122,13 @@ class IconStack
$idx = $icon['idx'];
$set = @$icon['set'];
$original = @$icon['original'];
-
+
$slug = $icon['slug'];
$variation = $icon['variation'];
$version = $icon['version'];
-
+
$is_standard = $variation == '.';
-
+
// All icons other than Pokémon sprites need to be offset
// with the height of the Pokémon sprite section.
$x = $icon['fit']['x'];
@@ -146,7 +148,7 @@ class IconStack
'idx' => $idx,
'id' => $icon['id'],
);
-
+
if ($type == 'pkmn') {
$tree['pkmn'][$slug][$variation][$version][$subvariation] = $icon_info;
}
@@ -156,7 +158,7 @@ class IconStack
}
$this->type_tree = $tree;
}
-
+
/**
* Returns the type tree data structure for our icons.
*
@@ -169,7 +171,7 @@ class IconStack
}
return $this->type_tree;
}
-
+
/**
* Determines and returns the sizes of the Pokémon icon sets.
*
@@ -181,7 +183,7 @@ class IconStack
return $this->set_sizes;
}
$sizes = array();
-
+
// The Pokémon icon sizes are always static.
$sizes['pkmn'] = array(
'w' => $this->pkmn_img_width - $this->pkmn_img_padding,
@@ -223,7 +225,7 @@ class IconStack
$this->set_sizes = $sizes;
return $this->set_sizes;
}
-
+
/**
* Creates an icon stack of the etc sprites.
*/
@@ -231,17 +233,17 @@ class IconStack
{
// This stack will contain icons from all other icon sets.
$stack = array();
-
+
// Save an array of sets.
$sets = array();
-
+
$etc_icon_sets = Settings::get('etc_icon_sets');
$dir_base = Settings::get('dir_base');
$file_exts = Settings::get('file_exts');
-
+
// Start off where the Pokémon stack ended.
$n = count($this->pkmn_stack);
-
+
if (Settings::get('include_icon_sets')) {
foreach ($etc_icon_sets as $set) {
$dir = $dir_base.$set.'/';
@@ -287,12 +289,12 @@ class IconStack
// Sort icons by size.
uasort($stack, array($this, 'etc_max_w_h_sort'));
-
+
// Deep convert $stack to a StdClass rather than a regular array.
// This is in order to be able to use it with the GrowingPacker, which
// only accepts a StdClass as input.
$stack = json_decode(json_encode($stack), false);
-
+
// Make sure to pass the width of the Pokémon section as
// the initial width. If we're not including Pokémon icons,
// set it to a static value.
@@ -301,28 +303,28 @@ class IconStack
if (!$initial_width) {
$initial_width = $this->pkmn_img_width * $this->pkmn_row_count;
}
-
+
// Initialize our packing algorithm and feed the icons.
// Permit horizontal growth only if we're not including Pokémon icons.
$packer = new GrowingPacker();
$packer->fit($stack, $initial_width, null, false, true);
-
+
// Convert back to array.
$stack = json_decode(json_encode($stack), true);
-
+
// Remove extraneous data from the stack.
foreach ($stack as $n => $icon) {
unset($stack[$n]['fit']['right']);
unset($stack[$n]['fit']['down']);
unset($stack[$n]['fit']['used']);
}
-
+
$this->etc_stack = $stack;
$this->etc_sets = $sets;
$this->etc_sect_width = intval($packer->root->w);
$this->etc_sect_height = intval($packer->root->h);
}
-
+
/**
* Sort by size (descending), then id (ascending).
*
@@ -339,13 +341,13 @@ class IconStack
// Take either the width or the height, whichever is the largest.
$a_size = max($a['w'], $a['h']);
$b_size = max($b['w'], $b['h']);
-
+
// If the items have the same size,
if ($a_size == $b_size) {
// Check their series number instead.
$a_id = $a['id'];
$b_id = $b['id'];
-
+
if ($a_id == $b_id) {
return 0;
}
@@ -355,7 +357,7 @@ class IconStack
// Descending
return ($a_size > $b_size) ? -1 : 1;
}
-
+
/**
* Sorts the icons so that the standard variation is always at the top.
*
@@ -377,7 +379,7 @@ class IconStack
return $val;
}
}
-
+
/**
* Parse Pokémon data file.
*
@@ -386,9 +388,17 @@ class IconStack
*/
public function parse_data_file($file, $range=null)
{
- $this->pkmn_data = json_decode(file_get_contents($file), true);
-
- // If requested, process only a specific range. (Debugging variable.)
+ $this->pkmn_data = $this->slice_icons(json_decode(file_get_contents($file), true), $range);
+ }
+
+ /**
+ * Parse icons data file.
+ *
+ * @param string $file Filename.
+ * @param string $range Range variable (undocumented; debugging only).
+ */
+ private function slice_icons($data, $range)
+ {
if (isset($range)) {
$range = str_replace(',', '-', $range);
$range = explode('-', $range);
@@ -400,14 +410,26 @@ class IconStack
intval($range[0]) - 1,
intval($range[1]) - intval($range[0]) + 1
);
- $this->pkmn_data = array_slice(
- $this->pkmn_data,
+ return array_slice(
+ $data,
$range[0],
$range[1]
);
}
+ return $data;
}
-
+
+ /**
+ * Parse icons data file.
+ *
+ * @param string $file Filename.
+ * @param string $range Range variable (undocumented; debugging only).
+ */
+ public function parse_icons_data_file($file, $range=null)
+ {
+ $this->icon_data = $this->slice_icons(json_decode(file_get_contents($file), true), $range);
+ }
+
/**
* Checks whether Pokémon data is loaded and non-empty.
*/
@@ -415,7 +437,15 @@ class IconStack
{
return !empty($this->pkmn_data);
}
-
+
+ /**
+ * Checks whether icon data is loaded and non-empty.
+ */
+ public function has_icon_data()
+ {
+ return !empty($this->icon_data);
+ }
+
/**
* Checks whether Pokémon images can be found.
*/
@@ -432,7 +462,23 @@ class IconStack
);
return is_file($final_img);
}
-
+
+ /**
+ * Checks whether icon images can be found.
+ */
+ public function has_icon_images()
+ {
+ // Check to see if the images are there.
+ $test_group = 'medicine';
+ $test_item = @reset($this->icon_data['icons'][$test_group]);
+ $test_img = (
+ Settings::get('dir_base').
+ $test_group.'/'.
+ $test_item['icon']['filename']
+ );
+ return is_file($test_img);
+ }
+
/**
* Returns parsed Pokémon data.
*
@@ -442,7 +488,17 @@ class IconStack
{
return $this->pkmn_data;
}
-
+
+ /**
+ * Returns parsed icon data.
+ *
+ * @return mixed[] Parsed icon data.
+ */
+ public function get_icon_data()
+ {
+ return $this->icon_data;
+ }
+
/**
* Returns x/y coordinates for the next Pokémon icon.
*
@@ -454,7 +510,7 @@ class IconStack
$width = $this->pkmn_img_width;
$height = $this->pkmn_img_height;
$row_count = $this->pkmn_row_count;
-
+
if ($inc != false) {
$this->counter += 1;
}
@@ -468,7 +524,7 @@ class IconStack
);
return $fit;
}
-
+
/**
* Returns the total size of the Pokémon icon stack.
*
@@ -483,32 +539,32 @@ class IconStack
);
}
$fit = $this->get_pkmn_icon_fit(false);
-
+
if ($this->counter > $this->pkmn_row_count) {
$width = ($this->pkmn_img_width * $this->pkmn_row_count);
}
else {
$width = $fit['fit']['x'] + $this->pkmn_img_width;
}
-
+
// See if the width is at least the size of 32 Pokémon icons.
// Note that padding has already been added to pkmn_img_width.
$min_width = (($this->pkmn_img_width) * $this->pkmn_row_count) + $this->pkmn_img_padding;
if ($width < $min_width) {
$width = $min_width;
}
-
+
$height = $fit['fit']['y'] + $this->pkmn_img_height;
-
+
$this->pkmn_sect_width = intval($width);
$this->pkmn_sect_height = intval($height);
-
+
return array(
'w' => $this->pkmn_sect_width,
'h' => $this->pkmn_sect_height,
);
}
-
+
/**
* Returns the total size of the etc icon stack.
*
@@ -521,7 +577,7 @@ class IconStack
'h' => $this->etc_sect_height + $this->img_padding,
);
}
-
+
/**
* Returns the total size of the Pokémon stack plus the etc icon
* stack below it.
@@ -532,20 +588,20 @@ class IconStack
{
$include_pkmn = Settings::get('include_pkmn');
$include_icon_sets = Settings::get('include_icon_sets');
-
+
$pkmn_size = $this->get_pkmn_icon_stack_size();
$etc_size = $this->get_etc_icon_stack_size();
-
+
$width = $include_pkmn ? $pkmn_size['w'] : $etc_size['w'];
$height = $include_pkmn ? $pkmn_size['h'] : 0;
$height += $include_icon_sets ? $etc_size['h'] : 0;
-
+
return array(
'w' => $width + $this->pkmn_img_padding,
'h' => $height + $this->pkmn_img_padding,
);
}
-
+
/**
* Creates an icon stack of the Pokémon sprites.
*
@@ -556,13 +612,13 @@ class IconStack
{
// Loop through the available Pokémon and adding each of their
// variants and forms to a stack.
-
+
// Initialize the sprite stack.
$this->pkmn_stack = array();
-
+
// List of sprite variants.
$this->sprites_variants = array();
-
+
// Include regular Pokémon, and shiny Pokémon if set.
$this->versions = array();
if (Settings::get('include_pkmn_nonshiny')) {
@@ -572,7 +628,7 @@ class IconStack
$this->versions[] = 'shiny';
}
$this->counter = -1;
-
+
// If we're skipping Pokémon sprite icons, $pkmn_data will be empty.
foreach ($this->pkmn_data as $id => $pkmn) {
$stack_items = $this->get_pkmn_stack_items($id, $pkmn);
@@ -580,14 +636,14 @@ class IconStack
$this->pkmn_stack[] = $item;
}
}
-
+
// Add the special items (e.g. egg, unknown).
if (Settings::get('include_special_icons')) {
$special_items = $this->get_special_stack_items();
$this->pkmn_stack = array_merge($this->pkmn_stack, $special_items);
}
}
-
+
/**
* Returns the special items for the Pokémon stack.
* Currently, just "egg", "egg-manaphy" and "unknown".
@@ -628,7 +684,7 @@ class IconStack
'jpn_ro' => 'Manaphy Tamago',
),
);
-
+
// Unknown (not Unown) or glitch Pokémon.
$unknown = array(
'idx' => null,
@@ -645,14 +701,14 @@ class IconStack
'jpn_ro' => 'Fumei',
),
);
-
+
return array_merge(
$this->get_pkmn_stack_items('egg', $egg, true),
$this->get_pkmn_stack_items('egg-manaphy', $egg_manaphy, true),
$this->get_pkmn_stack_items('unknown', $unknown, true)
);
}
-
+
/**
* Returns the icon stack (and generates it if it doesn't exist).
*
@@ -665,7 +721,7 @@ class IconStack
}
return $this->pkmn_stack;
}
-
+
/**
* Returns the standard icons that need to be referred to
* in the case of duplicates.
@@ -679,7 +735,7 @@ class IconStack
}
return $this->sprites_variants;
}
-
+
/**
* Produces and returns a variable name for an icon
* based on its attributes.
@@ -713,8 +769,8 @@ class IconStack
}
return implode('-', $items);
}
-
-
+
+
/**
* Returns stack items for a specific Pokémon.
*
@@ -734,7 +790,7 @@ class IconStack
'section' => 'pkmn',
'name_display' => $pkmn['name'][Settings::get('pkmn_language')],
);
-
+
// Retrieve some variables from the settings.
$vars = array(
'dir_base', 'dir_pkmn', 'dir_pkmn_female', 'dir_pkmn_right',
@@ -743,15 +799,15 @@ class IconStack
foreach ($vars as $var) {
$$var = Settings::get($var);
}
-
+
// Keep this Pokémon's stack items and return them at the end.
$tmp_stack = array();
-
+
// Sort the variations to ensure the standard variation
// comes first. The data file should already be pre-sorted,
// but we're making sure.
uksort($pkmn['icons'], array($this, 'pkmn_variation_sort'));
-
+
foreach ($pkmn['icons'] as $icon => $icon_data) {
// Zygarde has '10' and '50' formes. Make sure the icon name is a string.
$icon = (string)$icon;
@@ -789,15 +845,15 @@ class IconStack
$tmp_stack[] = $pkmn_info;
continue;
}
-
+
// Loop through each icon twice: once for regular versions, and
// (if requested), once more for shiny versions.
// Every variation is added to the stack.
-
+
foreach ($this->versions as $version) {
// Refer to either the regular or shiny icon directory.
$version_dir = Settings::get('dir_pkmn_'.$version);
-
+
$is_duplicate = !empty($icon_data['is_duplicate_from']);
$info = array(
'version' => $version,
@@ -810,17 +866,17 @@ class IconStack
$info['original'] = @$this->sprites_variants[$id][$version][$icon_data['is_duplicate_from']];
}
$is_standard = $icon == '.';
-
+
// Don't include non-standard forms
// if we've got that turned off.
if ($include_pkmn_forms != true && !$is_standard) {
continue;
}
-
+
// The standard version is indicated by a single period.
// All other variants are present as slug-variant.png.
$variation = $is_standard ? '' : '-'.$icon;
-
+
// Produce a variable name.
$var = $this->get_icon_var_name(
'pkmn',
@@ -829,7 +885,7 @@ class IconStack
'.',
$version
);
-
+
// Add to the stack
$pkmn_info = array_merge($base_info,
$info,
@@ -847,12 +903,12 @@ class IconStack
)
);
$tmp_stack[] = $pkmn_info;
-
+
// Save this icon in the variant list.
// We need to re-use it for variations that
// don't have their own icon.
$this->sprites_variants[$id][$version][$icon] = $pkmn_info;
-
+
// Female variant
if ($include_pkmn_forms && $icon_data['has_female']) {
$var = $this->get_icon_var_name(
@@ -880,7 +936,7 @@ class IconStack
)
);
}
-
+
// Right-facing variant
if ($include_pkmn_forms && $icon_data['has_right']
&& $include_pkmn_right > 0) {
@@ -940,7 +996,7 @@ class IconStack
}
}
}
-
+
return $tmp_stack;
}
-}
\ No newline at end of file
+}
diff --git a/includes/usage.php b/includes/usage.php
index 136c5083..fd482b6e 100644
--- a/includes/usage.php
+++ b/includes/usage.php
@@ -16,7 +16,7 @@ class Usage extends TemplateFormatter
{
/** @var string[] Arguments that require a value. */
public static $ARG_REQ = array(
- 'dir-icons:', 'dir-data:', 'file-data:',
+ 'dir-icons:', 'dir-data:', 'file-data:', 'file-icons-data:',
'dir-output:', 'file-output-img-tmp:', 'file-output-img:',
'file-output-scss:', 'file-output-html:', 'file-output-md:',
'tpl-scss:', 'tpl-html:', 'css-base-sel:', 'css-shiny-sel:',
@@ -183,10 +183,12 @@ class Usage extends TemplateFormatter
'file-output-img-tmp' => 'img_output_tmp',
'dir-output' => 'dir_output',
'file-data' => 'file_pkmn_data',
+ 'file-icons' => 'file_icon_data',
'dir-data' => 'dir_data',
'dir-pkmn' => 'dir_pkmn',
'dir-icons' => 'dir_base',
'pkmn-range' => 'pkmn_range',
+ 'icon-range' => 'icon_range',
'pkmn-lang' => 'pkmn_language',
'lang' => 'i18n_language',
);
diff --git a/pokesprite.php b/pokesprite.php
index eb097372..ec6db017 100755
--- a/pokesprite.php
+++ b/pokesprite.php
@@ -215,6 +215,25 @@ else {
$pkmn_data = array();
}
+// Retrieve icons from the set.
+if ($include_icon_sets) {
+ $icon_stack->parse_icons_data_file($dir_data.$file_icon_data, $icon_range);
+ $icon_data = $icon_stack->get_icon_data();
+
+ // Check if the data is there.
+ $has_data = $icon_stack->has_icon_data();
+ $has_imgs = $icon_stack->has_icon_images();
+
+ if (!$has_data) {
+ print(I18n::lf('no_icons_data', array($file_icon_data, $dir_data)));
+ die();
+ }
+ if (!$has_imgs) {
+ print(I18n::l('no_icon_images'));
+ die();
+ }
+}
+
// Generate and return the entire Pokémon icon stack.
$pkmn_icons = $icon_stack->get_pkmn_icon_stack();
$pkmn_std_icons = $icon_stack->get_pkmn_std_icons();