Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Custom Preconditions2D #16

Open
RacoonDOEggs opened this issue Mar 1, 2024 · 2 comments
Open

[Docs] Custom Preconditions2D #16

RacoonDOEggs opened this issue Mar 1, 2024 · 2 comments

Comments

@RacoonDOEggs
Copy link

Hello,
I want to preface with how much I appreciate this addon as it offers a very complete and relatively easy to use integration of WFC. I am trying to make a custom Precondition2D that uses perlin noise (Or simplex noise) to create denser forested areas and plains that are to be populated by WFC. However, I am having trouble understanding how to use the bitset object and the mapper object. I'm also uncertain on how to add the custom precondition to the generator. Would it be possible to have a small crash course? The dungeon example isn't super explanatory...

@AlexeyBond
Copy link
Owner

Hi.

how to use the bitset object

WFCBitSet is a bit array implementation. It uses N bits of memory to store sets of integers between 0 and N-1.

You may think of it as of a fancy but limited and inconvenient array.

In context of preconditions, it is used to return (from read_domain method) sets of tiles allowed in certain cell. Each tile is represented as an integer.

The minimal set of operations you will have to use is creating a bit set and adding a value to it.

The bit set is created as by calling a constructor:

var mybitset = WFCBitSet.new(size);

where size is number of tiles in WFC rules, which can be acquired from a mapper.
By default a set will contain no values. If true is passed as second constructor argument, the set will contain all valuest between 0 (inclusive) and size (exclusive).

A value is added to a set by calling set_bit method:

mybitset.set_bit(2)

These two operations may be enough for basic precondition implementation (just create a bit set and add some tile ids to it). But other methods may be useful as well.
There is some minimal documentation for all of WFCBitSet methods and I hope it should be enough to use them with some basic understanding of bit array data structure and set operations in general.

and the mapper object.

The mapper is responsible for interaction between WFC generator and a map node. There are different mapper subclasses that work with different map nodes (WFCGridMapMapper2D for GridMaps, WFCLayeredTileMapMapper2D and legacy WFCTileMapMapper2D for TileMaps).

They map data between formats specific for map types and unified representation used by WFC generator and related stuff, including preconditions.

In precondition mapper is used to get data about available tile types:

  1. number of tiles available to generator
  2. parameters of different tiles that determine what category each tile belongs to

The number of tiles is returned by size() method of mapper. It should be used later to create WFCBitSets.

There are two approaches to provide tile categories data to the precondition:

  1. Use tile metadata. Metadata is values associated with each tile. In case of TileMaps, data layers are used as metadata. In case of GridMaps - it's possible to attach metadata to each mesh using a mapper property.
  2. Use an auxiliary map.

Tile metadata is accessed using read_tile_meta method of a mapper. There is also a read_tile_meta_boolean method, useful for booleam attributes.

For example, if you want to mark some tiles as tiles belonging to "forest" area, you may create a "is_forest" boolean data layer in the tileset and then use the following code to create a set of all tiles that have this data layer set to true:

var forest_domain = WFCBitSet.new(mapper.size());
for i in range(mapper.size()):
	if mapper.read_tile_meta_boolean(i, "is_forest"):
		forest_domain.set_bit(i)

In dungeon precondition this approach is implemented in learn_classes method.

This approach is extremally convenient with TileMaps. But GridMaps don't have a built-in metadata functionality and metadata settings in mapper aren't very convenient.

In case of GridMap, an auxiliary map approach is more usable.

In this case to configure a precondition a separate map is created. And reference to that map stored in your precondition settings object (see below).
Then you place, for example, "forest" tiles in the first row of the map and "plain" tiles in the second row.
Then ids of tiles belonging to each category can be extracted using mapper's get_used_rect and read_cell methods that reads tile from given coordinates in given map.

In dungeon precondition this is implemented in learn_classes_from_map method.

Dungeon precondition demos show most of configuration variants - tilemap with metadata, gridmap with metadata and gridmap with auxiliary map.

I'm also uncertain on how to add the custom precondition to the generator

To use a custom precondition with WFC2DGenerator you'll have to:

  1. Create a settings class (a subclass of WFC2DPrecondition2DNullSettings) for your precondition. The settings class should export the properties you'd like to be customizable. It also should implement a method create_precondition based on those settings. Settings class must be placed in it's own .gd file and must have a class_name set in order to be discoverable by inspector.

  2. Set (using the inspector) an instance of you settings class as precondition property of generator.

@RacoonDOEggs
Copy link
Author

Thank you! This clears up a lot of questions I had reading the code! I will let you know if I have more problems worth documenting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants