Rule¶
The rules describe elements of the scenario, which objects you want in the scenario or which textures with options are needed.
Language is very easy - is based mostly on CSS language (we have a little exceptions like math operators or nested rules). In this language, we can link to another rules (for example, cube can link to the wall rule which links to the texture rule), and is enough to describe city-like scenarios.
The example of rule is below:
SELECTOR {
property: <VALUE>;
property: <VALUE>, <VALUE>; /* array of N elements */
property: <VALUE>;
/* ... */
CHILD-SELECTOR {
property: <VALUE>;
/* ... */
}
/* ... */
}
We have a few elements:
Selector - it’s a query with requirements to affect properties to element. In example we can make rule only for house object or we can make rule for roof with brick class. More details are in Selectors section.
Property - name of attribute of rule. With property we can decribe dimension of object, set texture path or links to another elements.
Value - value of property, can be an integer, string or link to another rule. Is possible to use functions.
Child - nested rules for children of overriding rule - very usefull for container where we have a many elements. Of course, child can have a another children.
Selectors¶
Selectors are powerfull syntax - we can describe elements with specified classes and makes relations with parent ↔ children of element. More details are below:
By Element name¶
Just element name - can be everything - cube, wall, texture, house, district or even fancy-cow. Rule, like element can only have one element’s name.
element { /*...properties...*/ }
By Class¶
Element can have variations - for example, house can have white or yellow walls, so we can write generic rule for house and write two rules for classes .white and .yellow to describe walls of our house.
Class starts with dot (like in CSS syntax).
.white { /*...properties...*/ }
.yellow { /*...properties...*/ }
Rule can have many classes (remember about no-space between classes - it’s neccessary!)
.class1.class2 { /*...properties...*/ }
We can join with element’s name:
house.yellow { /*...properties...*/ }
element.class1.class2 { /*...properties...*/ }
Parent operator¶
Containers can have a children - for example, we can have a district with N buildings, and we can have a oldtown district and modern district. So we can change shapes and textures of buldings depends of the parent element.
parent > element { /*...properties...*/ }
parent > .class { /*...properties...*/ }
parent > element.class { /*...properties...*/ }
parent > el1 > el2 { /*...properties...*/ }
With district example, rule should be as:
district.oldtown > building { /*...properties...*/ }
district.modern > building { /*...properties...*/ }
Greedy parent¶
Sometimes, we have a too nested structure - then we need a greedy parent selector.
parent element { /*...properties...*/ }
In example, imagine if you have a oldtown district which buldings have only wooden roof, so we can desribe rule with
district.oldtown roof { roof: wall.wooden; }
In another example, if you have these structure:
And one rule:
parent grandchild { color: red; }
Then grandchild will have red color.
Many Selectors¶
Sometimes, many elements can have a similar configuration, so it’s possible to have an one rule for many selectors:
selector1, selector2, selector3 {
/*...properties...*/
}
Merge Rules¶
It’s possible to write many rules for one element. In example:
draw-obj { wall: wall.brick.red; }
wall.brick { property-brick: OBJ2; }
wall.red { property-red: OBJ1; }
It’s equality this same with:
draw-obj { wall: wall.brick.red; }
wall.brick.red {
property-brick: OBJ2;
property-red: OBJ1;
}
Warning
order of rules is important, bottom rule overwrite properties from top rule, for example:
draw-obj { wall: wall.brick.grass; }
wall.brick { color: red; }
wall.grass { color: green; }
It is equal with:
draw-obj { wall: wall.brick.grass; }
wall.brick.grass { color: green; }