Skip to content

Commit

Permalink
Moves to nested class and consts for categories instead of enums
Browse files Browse the repository at this point in the history
  • Loading branch information
imothee committed Feb 26, 2024
1 parent b69e870 commit a904d24
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 58 deletions.
4 changes: 2 additions & 2 deletions addons/pandora/api.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
extends Node

const EntityIdFileGenerator = preload("res://addons/pandora/util/entity_id_file_generator.gd")
const CategoryEnumGenerator = preload("res://addons/pandora/util/category_enum_generator.gd")
const CategoryIdFileGenerator = preload("res://addons/pandora/util/category_id_file_generator.gd")
const ScriptUtil = preload("res://addons/pandora/util/script_util.gd")

signal data_loaded
Expand Down Expand Up @@ -160,7 +160,7 @@ func save_data() -> void:
_storage.store_all_data(all_object_data, _context_manager.get_context_id())

EntityIdFileGenerator.regenerate_id_files(get_all_roots())
CategoryEnumGenerator.regenerate_category_enums(get_all_roots())
CategoryIdFileGenerator.regenerate_category_id_file(get_all_roots())


func calculate_import_data(path: String) -> int:
Expand Down
51 changes: 0 additions & 51 deletions addons/pandora/util/category_enum_generator.gd

This file was deleted.

92 changes: 92 additions & 0 deletions addons/pandora/util/category_id_file_generator.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
## Generates a .gd file that allows for easier access
## of categories and subcategories of the data
static func regenerate_category_id_file(root_categories: Array[PandoraCategory]) -> void:
var root_category_tuples: Array[CategoryTuple] = []
# { parent: [CategoryTuple] }
var subcategory_tuples = {}

for category in root_categories:
root_category_tuples.append(
CategoryTuple.new(category.get_entity_name(), category.get_entity_id())
)
generate_sub_category_tuples(
category.get_entity_name(), category._children, subcategory_tuples
)

generate_category_id_file(root_category_tuples, subcategory_tuples)


static func generate_sub_category_tuples(
parent_category: String, entities: Array[PandoraEntity], subcategory_tuples: Dictionary
) -> void:
var category_tuples: Array[CategoryTuple] = []
subcategory_tuples[parent_category] = category_tuples

for entity in entities:
if entity is PandoraCategory:
var entity_name = entity.get_entity_name()

subcategory_tuples[parent_category].append(
CategoryTuple.new(entity_name, entity.get_entity_id())
)

# If we already have an existing category name, we need to rename it with the parent category
if subcategory_tuples.has(entity_name):
entity_name = "%s_%s" % [parent_category, entity_name]

generate_sub_category_tuples(entity_name, entity._children, subcategory_tuples)


static func generate_category_id_file(
root_category_tuples: Array[CategoryTuple], subcategory_tuples: Dictionary
) -> void:
var file_path = "res://pandora/categories.gd"
if not DirAccess.dir_exists_absolute("res://pandora"):
DirAccess.make_dir_absolute("res://pandora")

var file_access = FileAccess.open(file_path, FileAccess.WRITE)
file_access.store_line("# Do not modify! Auto-generated file.")
file_access.store_line("class_name PandoraCategories\n\n")

# Per GDScript style guide we put consts at the top of the file so we do the root_category_tuples first
for category_tuple in root_category_tuples:
var line = (
'const %s = "%s"'
% [
category_tuple.category_name.to_upper().replace(" ", "_"),
category_tuple.category_id
]
)
file_access.store_line(line)

file_access.store_line("\n")

# We then do all the inline classes
for parent_category in subcategory_tuples:
if subcategory_tuples[parent_category].size() == 0:
continue

var line = "class %sCategories:" % parent_category.to_pascal_case()
file_access.store_line(line)

for category_tuple in subcategory_tuples[parent_category]:
line = (
' const %s = "%s"'
% [
category_tuple.category_name.to_upper().replace(" ", "_"),
category_tuple.category_id
]
)
file_access.store_line(line)
file_access.store_line("\n")

file_access.close()


class CategoryTuple:
var category_name: String
var category_id: String

func _init(category_name: String, category_id: String) -> void:
self.category_name = category_name
self.category_id = category_id
7 changes: 5 additions & 2 deletions docs/api/access.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ In this example, the `Damage` property of the `SWORD` entity is fetched, demonst

Pandora allows you to define entities on nodes directly inside the editor:

- The exported type **must** extend `PandoraEntity`
- The exported type **must** extend `PandoraEntity`
- The exported type **must** be a `@tool` script

This can be done as follows:

```gdscript
extends Node2D
Expand All @@ -39,6 +40,7 @@ extends Node2D
func _ready() -> void:
var instance:PandoraEntity = item.instantiate()
```

Within the Godot node editor properties, then select the entity of your choice from the list. Pandora automatically filters the entities depending on the type provided:

![custom-type-exports](../assets/custom_type_exports.gif)
Expand All @@ -55,6 +57,7 @@ if entity is CustomType:
# 1. a parent category of entity has the CustomType script set
# 2. CustomType extends PandoraEntity
```

**Advantage**: type-safe and allows for auto-completion</br>
😕 **Downside**: requires extra scripts to do type-checks

Expand Down Expand Up @@ -86,4 +89,4 @@ if entity.is_category(Items.CATEGORY_ORES):
```

**Advantage**: no additional setup required (quick)</br>
😕 **Downside**: currently not possible, requires [#63](https://github.com/bitbrain/pandora/issues/63) to be done first!
😕 **Downside**: category generation is still alpha and the api may change
59 changes: 56 additions & 3 deletions docs/mastery/id-constants.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,80 @@
# Generating ID Constants

> ⚠️ this functionality is still in alpha state. It is currently not possible to generate constants for categories or properties. Refer to [#61](https://github.com/bitbrain/pandora/issues/61) and [#63](https://github.com/bitbrain/pandora/issues/63) for more information.
> ⚠️ this functionality is still in alpha state. It is currently not possible to generate constants for properties. Refer to [#61](https://github.com/bitbrain/pandora/issues/61) for more information.
Imagine you want to access a certain entity you defined:

```gdscript
# what is the ID for copper ore?
var copper_ore = Pandora.get_entity("???")
```

You could hover the entity inside the entity tree to figure out what its ID value might be which can be cumbersome. An altrnative approach could be to find the entity by name - also this can be dangerous as the name of an entity is **not unique**.

Pandora allows you to generate so called **ID Constants** that you can access directly in your code:

![id-constants](../assets/editor-id-constants.png)

This will generate a new file called `res://pandora/ores.gd` that looks a bit like this:

```gdscript
# Do not modify! Auto-generated file.
class_name Ores
class_name Ores
const COPPER_ORE = "14"
```

This allows you to do something like this:

```gdscript
var copper_ore = Pandora.get_entity(Ores.COPPER_ORE)
```
In case the item gets renamed, this code starts failing (which is good!) as you can catch issues at compilation time, rather when the code is running in the game!

In case the item gets renamed, this code starts failing (which is good!) as you can catch issues at compilation time, rather when the code is running in the game!

Pandora will also generate a PandoraCategories file that contains the Category IDs of all categories and subcategories in your tree.
It handles non-unique categories by prepending the parents name to the category class generated.

It will generate a file called `res://pandora/categories.gs` that looks a bit like this:

```gdscript
# Do not modify! Auto-generated file.
class_name PandoraCategories
const ITEMS = "3"
const RARITY = "7"
const ENCHANTMENTS = "48"
const SKILLS = "66"
const ANIMATIONS = "70"
const CHARACTERS = "71"
const BODY_TYPES = "72"
const LOOT = "73"
const HAIR_TYPES = "120"
const RESOURCES = "135"
const RESOURCE_STATES = "142"
const GAMECONFIG = "177"
class ItemsCategories:
const EQUIPMENT = "4"
const CONSUMABLE = "37"
const RESOURCE = "38"
const LITERARY = "39"
const QUESTS = "40"
const MISC = "41"
class EquipmentCategories:
const WIELD = "35"
const ARMOR = "50"
const ACCESSORIES = "51"
```

This allows you to do something like this:

```gdscript
if entity.is_category(ItemsCategories.EQUIPMENT):
# entity is under the Equipment category
```

0 comments on commit a904d24

Please sign in to comment.