# DefTree: A python module for editing Defold files

**URL:** <https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210>\
**Category:** The Defoldmine\
**Created:** [December 30, 2017, 4:14pm UTC](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210 "2017-12-30T16:14:45Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mattias\_Hedberg](https://forum-defold.b-cdn.net/user_avatar/forum.defold.com/mattias_hedberg/32/433_2.png) [@Mattias\_Hedberg](https://forum.defold.com/u/Mattias_Hedberg)\
**Post date:** [December 30, 2017, 4:14pm UTC](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210/1 "2017-12-30T16:14:46Z")

</div>

I have a python module for Defold that I use quite frequently when I do batch changes. Removing all layouts, scaling all particle effects, cleaning up gui scenes, generally finding out information and such. Available here if anyone want to check it out [https://deftree.readthedocs.io](https://deftree.readthedocs.io)

It works but consider it a beta, as I will highly likely make breaking change to the API in the future (but will keep it versioned properly of course).

You can find the source on  
[https://github.com/Jerakin/DefTree](https://github.com/Jerakin/DefTree)

### Examples

Here are some examples, updated for 1.0.2

You have removed a lot of images from disk that you know are obsolete and now you need to clean up all atlases.

> **Remove unused images in atlases**
>
> ```python
> import os
> import deftree
> 
> def get_files(project_root, ending):
> # Generator to get files
> for root, folders, files in os.walk(project_root):
> for f in files:
> if f.endswith(ending):
> yield os.path.join(root, f)
> 
> def get_images(df_object):
> """get all images paths in a given DefTree Element instance"""
> for x in df_object.elements():
> if deftree._is_element(x):
> get_images(x)
> else:
> yield x
> 
> def missing_images_in_atlas(project_root, atlas):
> """get images in an atlas that does not exist on disk"""
> tree = deftree.DefTree()
> root = tree.parse(atlas)
> for image in get_images(root):
> if not os.path.exists(os.path.join(project_root, image[1:])):
> yield image
> 
> def clean_up_atlas(project_root, atlas):
> """Remove all missing image in entries in the atlas"""
> for missing in missing_images_in_atlas(project_root, atlas):
> tree = deftree.parse(atlas)
> root = tree.get_root()
> for img in get_images(root):
> if img == missing:
> root.remove(img.get_parent())
> tree.write(atlas)
> 
> def verify(project_folder):
> """Print images that are missing on disk"""
> for atlas in get_files(project_folder, ".atlas"):
> for missing in missing_images_in_atlas(project_folder, atlas):
> print("{}{}{}".format(atlas.replace(project_folder, ""),
> (50 - len(atlas.replace(project_folder, ""))) * " ",
> missing))
> 
> def clean_up_all_atlases(project_folder):
> """Remove all missing image in entries in the project"""
> for atlas in get_files(project_folder, ".atlas"):
> clean_up_atlas(project_folder, atlas)
> 
> ```

You thought you wanted layouts when you started but now you have changed your mind.

> **Remove Layouts**
>
> ```pyton
> import deftree
> import os
> 
> def get_files(project_root, ending):
> # Generator to get files
> for root, folders, files in os.walk(project_root):
> for f in files:
> if f.endswith(ending):
> yield os.path.join(root, f)
> 
> def main(project):
> errors = list()
> for gui in get_files(project, ".gui"):
> # Create our tree
> tree = deftree.parse(gui)
> root = tree.get_root()
> rem = False
> 
> # Find all layouts
> for layout in root.iter_elements("layouts"):
> # For error reporting
> errors.append("{}".format(gui))
> 
> rem = True
> 
> # Remove the child layout from the root
> root.remove(layout)
> 
> # If we removed a layout rewrite the file
> if rem:
> tree.write(gui)
> 
> # Report our errors
> if errors:
> [print(x) for x in errors]
> 
> ```

You for some reason want to sort your atlases

> **Sort Atlases**
>
> ```python
> import os
> import deftree
> 
> def sort_atlas(atlas):
> tree = deftree.parse(atlas)
> root = tree.get_root()
> org = deftree.to_string(root)
> new_tree = deftree.DefTree()
> new_root = new_tree.get_root()
> _atlas = []
> _animations = []
> 
> for at in root.iter_elements("images"):
> _atlas.append(at.get_attribute("image").value)
> 
> for ani in root.iter_elements("animations"):
> _animations.append(ani)
> 
> # Sort the images
> for a in sorted(_atlas, key=lambda x: x.split("/")[-1]):
> ele = new_root.add_element("images")
> ele.add_attribute("image", a)
> 
> # Add the animations
> for animation in _animations:
> new_root.append(animation)
> 
> # Add the atlas attributes. Margin, extrude
> for at in root.attributes():
> if not at.name == "image":
> new_root.append(at)
> 
> new_tree.write(atlas)
> if not deftree.validate(org, deftree.to_string(new_root)):
> print("Sorted: {}".format(atlas))
> 
> ```

You noticed that without extrude 2 on your altases you get bleeding

> **Batch Edit Atlas Property**
>
> ```python
> import os
> import deftree
> 
> def get_files(project_root, ending):
> # Generator to get files
> for root, folders, files in os.walk(project_root):
> for f in files:
> if f.endswith(ending):
> yield os.path.join(root, f)
> 
> def set_atlas_extrude(project_folder, value):
> for atlas in get_files(project_folder, ".atlas"):
> tree = deftree.parse(atlas)
> root = tree.get_root()
> root.set_attribute("extrude_borders", value)
> 
> tree.write(atlas)
> 
> ```

* * *

It is made for python 3.3 or newer and is easiest installed with `pip install deftree`

---

<div class="post-metadata">

**Author:** ![Oleg\_The\_Evangelist](https://forum-defold.b-cdn.net/user_avatar/forum.defold.com/oleg_the_evangelist/32/1596_2.png) [@Oleg\_The\_Evangelist](https://forum.defold.com/u/Oleg_The_Evangelist)\
**Post date:** [February 8, 2018, 4:08pm UTC](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210/2 "2018-02-08T16:08:08Z")

</div>

mmmm… @Axel may want to at some point help with the graphics so this tool end up nicely on the Asset Portal 😉

---

<div class="post-metadata">

**Author:** ![AGulev](https://forum-defold.b-cdn.net/user_avatar/forum.defold.com/agulev/32/4541_2.png) [@AGulev](https://forum.defold.com/u/AGulev)\
**Post date:** [March 2, 2018, 8:56am UTC](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210/3 "2018-03-02T08:56:31Z")

</div>

DefTree is awesome! Thank for the lib and your help!  
I made few scripts for my projects.

One of them, for example, removing all unused PNG files from the project.  
I am find all links to PNG in every atlas, tilesource, cubemap and game.project (maybe I forgot something?) and then checking every png in project with this list I am searching unused PNGs and remove them. After that I removes all empty folders.

Maybe somebody it will be useful:

> <https://gist.github.com/AGulev/6562494806be79d96f1579888dc09519>

Dependencies: deftree and configparser

---

<div class="post-metadata">

**Author:** ![Mattias\_Hedberg](https://forum-defold.b-cdn.net/user_avatar/forum.defold.com/mattias_hedberg/32/433_2.png) [@Mattias\_Hedberg](https://forum.defold.com/u/Mattias_Hedberg)\
**Post date:** [March 6, 2018, 5:06pm UTC](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210/4 "2018-03-06T17:06:00Z")

</div>

Thanks @AGulev happy it was useful!

It is a good idea to share small scripts here so everyone can benefit 🙂  
Here is one that I made, it removes all resources in a gui file that are not used in it. If you don’t change resources with gui\_script (i.e. do a lot of `gui.set_texture()`) this can save memory for you!

> <https://gist.github.com/Jerakin/d4feecaeb3ecb76d20b5e36a51ea699a>

---

<div class="post-metadata">

**Author:** ![AGulev](https://forum-defold.b-cdn.net/user_avatar/forum.defold.com/agulev/32/4541_2.png) [@AGulev](https://forum.defold.com/u/AGulev)\
**Post date:** [March 6, 2018, 7:34pm UTC](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210/5 "2018-03-06T19:34:52Z")

</div>

🤩

Sometimes flipbook animations has the same frames in different png files. It makes atlases bigger than they should be, because Defold allows to use one png in few different animation(in one atlas) or few times in one animation.

This script replace duplicates in all project’s flipbook animations:

> <https://gist.github.com/AGulev/0e0c75faa822e8fef51a7ef6f6a0386b>

---

<div class="post-metadata">

**Author:** ![Oleg\_The\_Evangelist](https://forum-defold.b-cdn.net/user_avatar/forum.defold.com/oleg_the_evangelist/32/1596_2.png) [@Oleg\_The\_Evangelist](https://forum.defold.com/u/Oleg_The_Evangelist)\
**Post date:** [March 7, 2018, 10:35am UTC](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210/6 "2018-03-07T10:35:15Z")

</div>

few more scripts and we’re ready for a magic button named “make my game much smaller and faster before I ship”.

---

<div class="post-metadata">

**Author:** ![AGulev](https://forum-defold.b-cdn.net/user_avatar/forum.defold.com/agulev/32/4541_2.png) [@AGulev](https://forum.defold.com/u/AGulev)\
**Post date:** [March 8, 2018, 1:56pm UTC](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210/7 "2018-03-08T13:56:18Z")

</div>

My (not quite) first python script (Before first experements with DefTree) =)  
I found a python script for searching duplicates and made few modernisations:

- sorting by file sizes;
- calculation of total duplicates size.

This script don’t use DefTree, But I think this forum thread is suitable here.

Original script is here: [Finding Duplicate Files with Python | Python Central](https://www.pythoncentral.io/finding-duplicate-files-with-python/)

My version: [Python script for a searching duplicate files in folder. Modification of: https://www.pythoncentral.io/finding-duplicate-files-with-python/ (file size counter was added) · GitHub](https://gist.github.com/AGulev/d5dc12127e0fbe1cd4f239effb76cd81)

---

<div class="post-metadata">

**Author:** ![AGulev](https://forum-defold.b-cdn.net/user_avatar/forum.defold.com/agulev/32/4541_2.png) [@AGulev](https://forum.defold.com/u/AGulev)\
**Post date:** [March 8, 2018, 7:38pm UTC](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210/8 "2018-03-08T19:38:17Z")

</div>

I updated prev. my scripts (some bug fixes and improvements)

New script for removing multi-adding same sprites to the non animation atlas.  
User can add one sprite few times, but it has no sense without animation.I think it do not affect to the bundle, but it makes the search in the atlas more difficult.

 ![2018-03-08_22-32-52](https://forum-defold-uploads.b-cdn.net/original/2X/4/44baa047d0ae87aad98e7699a3552801f5dd3069.jpg)

> <https://gist.github.com/AGulev/b02da861ecb2177ac53dcac4e23eed93>
