+#if ENABLE_UNUSED_CODE
+ Debug("setup:LoadArtworkInfo", "graphics set == %s",
+ artwork.gfx_current_identifier);
+ Debug("setup:LoadArtworkInfo", "sounds set == %s",
+ artwork.snd_current_identifier);
+ Debug("setup:LoadArtworkInfo", "music set == %s",
+ artwork.mus_current_identifier);
+#endif
+
+ sortTreeInfo(&artwork.gfx_first);
+ sortTreeInfo(&artwork.snd_first);
+ sortTreeInfo(&artwork.mus_first);
+
+#if ENABLE_UNUSED_CODE
+ dumpTreeInfo(artwork.gfx_first, 0);
+ dumpTreeInfo(artwork.snd_first, 0);
+ dumpTreeInfo(artwork.mus_first, 0);
+#endif
+}
+
+static void MoveArtworkInfoIntoSubTree(ArtworkDirTree **artwork_node)
+{
+ ArtworkDirTree *artwork_new = newTreeInfo();
+ char *top_node_name = "standalone artwork";
+
+ setTreeInfoToDefaults(artwork_new, (*artwork_node)->type);
+
+ artwork_new->level_group = TRUE;
+
+ setString(&artwork_new->identifier, top_node_name);
+ setString(&artwork_new->name, top_node_name);
+ setString(&artwork_new->name_sorting, top_node_name);
+
+ // create node to link back to current custom artwork directory
+ createParentTreeInfoNode(artwork_new);
+
+ // move existing custom artwork tree into newly created sub-tree
+ artwork_new->node_group->next = *artwork_node;
+
+ // change custom artwork tree to contain only newly created node
+ *artwork_node = artwork_new;
+}
+
+static void LoadArtworkInfoFromLevelInfoExt(ArtworkDirTree **artwork_node,
+ ArtworkDirTree *node_parent,
+ LevelDirTree *level_node,
+ boolean empty_level_set_mode)
+{
+ int type = (*artwork_node)->type;
+
+ // recursively check all level directories for artwork sub-directories
+
+ while (level_node)
+ {
+ boolean empty_level_set = (level_node->levels == 0);
+
+ // check all tree entries for artwork, but skip parent link entries
+ if (!level_node->parent_link && empty_level_set == empty_level_set_mode)
+ {
+ TreeInfo *artwork_new = getArtworkInfoCacheEntry(level_node, type);
+ boolean cached = (artwork_new != NULL);
+
+ if (cached)
+ {
+ pushTreeInfo(artwork_node, artwork_new);
+ }
+ else
+ {
+ TreeInfo *topnode_last = *artwork_node;
+ char *path = getPath2(getLevelDirFromTreeInfo(level_node),
+ ARTWORK_DIRECTORY(type));
+
+ LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path, type);
+
+ if (topnode_last != *artwork_node) // check for newly added node
+ {
+ artwork_new = *artwork_node;
+
+ setString(&artwork_new->identifier, level_node->subdir);
+ setString(&artwork_new->name, level_node->name);
+ setString(&artwork_new->name_sorting, level_node->name_sorting);
+
+ artwork_new->sort_priority = level_node->sort_priority;
+ artwork_new->in_user_dir = level_node->in_user_dir;
+
+ update_artworkinfo_cache = TRUE;
+ }
+
+ free(path);
+ }
+
+ // insert artwork info (from old cache or filesystem) into new cache
+ if (artwork_new != NULL)
+ setArtworkInfoCacheEntry(artwork_new, level_node, type);
+ }
+
+ DrawInitText(level_node->name, 150, FC_YELLOW);
+
+ if (level_node->node_group != NULL)
+ {
+ TreeInfo *artwork_new = newTreeInfo();
+
+ if (node_parent)
+ setTreeInfoToDefaultsFromParent(artwork_new, node_parent);
+ else
+ setTreeInfoToDefaults(artwork_new, type);
+
+ artwork_new->level_group = TRUE;
+
+ setString(&artwork_new->identifier, level_node->subdir);
+
+ if (node_parent == NULL) // check for top tree node
+ {
+ char *top_node_name = (empty_level_set_mode ?
+ "artwork for certain level sets" :
+ "artwork included in level sets");
+
+ setString(&artwork_new->name, top_node_name);
+ setString(&artwork_new->name_sorting, top_node_name);
+ }
+ else
+ {
+ setString(&artwork_new->name, level_node->name);
+ setString(&artwork_new->name_sorting, level_node->name_sorting);
+ }
+
+ pushTreeInfo(artwork_node, artwork_new);
+
+ // create node to link back to current custom artwork directory
+ createParentTreeInfoNode(artwork_new);
+
+ // recursively step into sub-directory and look for more custom artwork
+ LoadArtworkInfoFromLevelInfoExt(&artwork_new->node_group, artwork_new,
+ level_node->node_group,
+ empty_level_set_mode);
+
+ // if sub-tree has no custom artwork at all, remove it
+ if (artwork_new->node_group->next == NULL)
+ removeTreeInfo(artwork_node);
+ }
+
+ level_node = level_node->next;
+ }
+}
+
+static void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node)
+{
+ // move peviously loaded artwork tree into separate sub-tree
+ MoveArtworkInfoIntoSubTree(artwork_node);
+
+ // load artwork from level sets into separate sub-trees
+ LoadArtworkInfoFromLevelInfoExt(artwork_node, NULL, leveldir_first_all, TRUE);
+ LoadArtworkInfoFromLevelInfoExt(artwork_node, NULL, leveldir_first_all, FALSE);
+
+ // add top tree node over all three separate sub-trees
+ *artwork_node = createTopTreeInfoNode(*artwork_node);
+
+ // set all parent links (back links) in complete artwork tree
+ setTreeInfoParentNodes(*artwork_node, NULL);
+}
+
+void LoadLevelArtworkInfo(void)
+{
+ print_timestamp_init("LoadLevelArtworkInfo");
+
+ DrawInitText("Looking for custom level artwork", 120, FC_GREEN);
+
+ print_timestamp_time("DrawTimeText");
+
+ LoadArtworkInfoFromLevelInfo(&artwork.gfx_first);
+ print_timestamp_time("LoadArtworkInfoFromLevelInfo (gfx)");
+ LoadArtworkInfoFromLevelInfo(&artwork.snd_first);
+ print_timestamp_time("LoadArtworkInfoFromLevelInfo (snd)");
+ LoadArtworkInfoFromLevelInfo(&artwork.mus_first);
+ print_timestamp_time("LoadArtworkInfoFromLevelInfo (mus)");
+
+ SaveArtworkInfoCache();
+
+ print_timestamp_time("SaveArtworkInfoCache");
+
+ // needed for reloading level artwork not known at ealier stage
+ ChangeCurrentArtworkIfNeeded(ARTWORK_TYPE_GRAPHICS);
+ ChangeCurrentArtworkIfNeeded(ARTWORK_TYPE_SOUNDS);
+ ChangeCurrentArtworkIfNeeded(ARTWORK_TYPE_MUSIC);
+
+ print_timestamp_time("getTreeInfoFromIdentifier");
+
+ sortTreeInfo(&artwork.gfx_first);
+ sortTreeInfo(&artwork.snd_first);
+ sortTreeInfo(&artwork.mus_first);
+
+ print_timestamp_time("sortTreeInfo");
+
+#if ENABLE_UNUSED_CODE
+ dumpTreeInfo(artwork.gfx_first, 0);
+ dumpTreeInfo(artwork.snd_first, 0);
+ dumpTreeInfo(artwork.mus_first, 0);
+#endif
+
+ print_timestamp_done("LoadLevelArtworkInfo");
+}
+
+static boolean AddTreeSetToTreeInfoExt(TreeInfo *tree_node_old, char *tree_dir,
+ char *tree_subdir_new, int type)
+{
+ if (tree_node_old == NULL)
+ {
+ if (type == TREE_TYPE_LEVEL_DIR)
+ {
+ // get level info tree node of personal user level set
+ tree_node_old = getTreeInfoFromIdentifier(leveldir_first, getLoginName());
+
+ // this may happen if "setup.internal.create_user_levelset" is FALSE
+ // or if file "levelinfo.conf" is missing in personal user level set
+ if (tree_node_old == NULL)
+ tree_node_old = leveldir_first->node_group;
+ }
+ else
+ {
+ // get artwork info tree node of first artwork set
+ tree_node_old = ARTWORK_FIRST_NODE(artwork, type);
+ }
+ }
+
+ if (tree_dir == NULL)
+ tree_dir = TREE_USERDIR(type);
+
+ if (tree_node_old == NULL ||
+ tree_dir == NULL ||
+ tree_subdir_new == NULL) // should not happen
+ return FALSE;
+
+ int draw_deactivation_mask = GetDrawDeactivationMask();
+
+ // override draw deactivation mask (temporarily disable drawing)
+ SetDrawDeactivationMask(REDRAW_ALL);
+
+ if (type == TREE_TYPE_LEVEL_DIR)
+ {
+ // load new level set config and add it next to first user level set
+ LoadLevelInfoFromLevelConf(&tree_node_old->next,
+ tree_node_old->node_parent,
+ tree_dir, tree_subdir_new);
+ }
+ else
+ {
+ // load new artwork set config and add it next to first artwork set
+ LoadArtworkInfoFromArtworkConf(&tree_node_old->next,
+ tree_node_old->node_parent,
+ tree_dir, tree_subdir_new, type);
+ }
+
+ // set draw deactivation mask to previous value
+ SetDrawDeactivationMask(draw_deactivation_mask);
+
+ // get first node of level or artwork info tree
+ TreeInfo **tree_node_first = TREE_FIRST_NODE_PTR(type);
+
+ // get tree info node of newly added level or artwork set
+ TreeInfo *tree_node_new = getTreeInfoFromIdentifier(*tree_node_first,
+ tree_subdir_new);
+
+ if (tree_node_new == NULL) // should not happen
+ return FALSE;
+
+ // correct top link and parent node link of newly created tree node
+ tree_node_new->node_top = tree_node_old->node_top;
+ tree_node_new->node_parent = tree_node_old->node_parent;