Tag? You may already have heard or read this word before. Let's see some generic concepts.
(from Wikipedia)
If you spend some time on forums (let's pick one randomly: forum ;)), you may have noticed that tags are attached to topics (and/or posts sometimes). The author can write words (tags) to shortly describe his/her topic without having to write a gramatically correct sentence. It's kind of a list of words that you could say during a brainstorming after reading the post.
Example of a topic with tags:
Thus, if you need information about, let's say, meshes, you can search for topics having "mesh" as a word in those topics, BUT you could also search for "mesh" as a tag of the topic. Indeed, maybe the word is never used in the topic (maybe it's only used, or not, in the title) but the author can choose to add it as a tag in the aim to categorize his/her topic. Tags can be used to categorize/group things.
Here the first search results:
OK...? What's the link with tags? Why are we about to talk about CSS classes?
Because CSS classes are great and Tags in Babylon.js can be considered similar, in principle, to CSS classes. So let's talk about them.
CSS stands for Cascading Style Sheets. It's used to define how to display HTML elements.
CSS classes are added to HTML elements (by writing them directly in the HTML code or by adding them via javascript) as a value of the class
attribute of the corresponding HTML elements.
HTML elements can have several CSS classes in their class
attribute and the same CSS class can be used on different HTML elements. CSS classes, just like tags on forums, can then be used to categorize HTML elements. Thus, a same style (background, font, color...) can easily be applied to a group of HTML elements identified by a CSS class (or a list of CSS classes).
Style for all HTML elements of the page having the "center" class on them (to find elements with a specific class, write a period character, followed by the name of the class)
.center
{
text-align: center;
color: red;
}
Thanks to javascript, you can even retrieve all these elements and then do further javascript operations on them (jQuery plugins largely use CSS classes).
var elements = document.getElementsByClassName(".center");
The above directive would gather a collection of all HTML elements that use the .center class.
Here we are! Tags in babylon.js can be used to categorize/group elements, and helper functions are provided to retrieve/gather tagged elements.
Tags were integrated into babylon.js on April 7, 2014. Pull request
There was a discussion about adding this feature on the forum. The goal was to be able to retrieve meshes.
The concept was expanded to allow the adding of tags on any javascript object (not necessarily only the objects created by babylon.js). The Tag
class that has been added to babylon.js contains all the necessary code for this generic concept (Typescript code) and internally uses the AndOrNotEvaluator
class (Typescript code).
The use of tags for a javascript object can be enabled/disabled like this (javascript code):
var myJSObj = {};
// enable tags for myJSObj
BABYLON.Tags.EnableFor(myJSObj);
// disable tags for myJSObj
BABYLON.Tags.DisableFor(myJSObj);
EnableFor
adds functions to the javascript object in the aim to:
hasTags
addTags
removesTags
matchesTagsQuery
(see below)Those functions are proxies of static methods of Tags
(HasTags
, AddTagsTo
, RemoveTagsFrom
and MatchesQuery
).
Tags
also contains GetTags
which retrieves the array of tags of the javascript object.
Remark: Tags.AddTagsTo enables tags for the object if needed
var myJSObj1 = {};
// enable tags for myJSObj1
BABYLON.Tags.EnableFor(myJSObj);// => addTags is available on myJSObj1
// add tags to myJSObj1
myJSObj1.addTags("tag1 tag2"); // same as BABYLON.Tags.AddTagsTo(myJSObj1, "tag1 tag2"),
var myJSObj2 = {};
// add tags to myJSObj2 without having to enable tags for it first
BABYLON.Tags.AddTagsTo(myJSObj2, "tag1 tag2"); // addTags couldn't be used on myJSObj2 since tags were not previously enabled for myJSObj2
Tags query:
Tags.MatchesQuery
(and matchesTagsQuery
if tags are enabled for the javascript object) accepts a list of correct tags (see "Rules to respect") containing parenthesis, and boolean evaluators such as (tag1 && (tag2 || tag4 || !tag5)) || !(!tag1) && !!!tag5
. The tags query is evaluated thanks to AndOrNotEvaluator
.
Full example:
var myJSObj1 = {};
BABYLON.Tags.AddTagsTo(myJSObj1, "tag1 tag2");
var myJSObj2 = {};
BABYLON.Tags.AddTagsTo(myJSObj2, "tag3 tag4 tag5");
var myJSObj3 = {};
BABYLON.Tags.EnableFor(myJSObj3);
var myJSObj4 = {};
myJSObj4.hasTags(); // TypeError: undefined is not a function
BABYLON.Tags.HasTags(myJSObj4); // false
myJSObj3.hasTags(); // false
BABYLON.Tags.HasTags(myJSObj3); // false
myJSObj2.hasTags(); // true
myJSObj1.hasTags(); // true
myJSObj1.matchesTagsQuery("tag1"); // true
myJSObj1.matchesTagsQuery("tag2"); // true
myJSObj1.matchesTagsQuery("tag1 || tag2"); // true
myJSObj1.matchesTagsQuery("tag1 && tag2"); // true
myJSObj1.matchesTagsQuery("tag3"); // false
myJSObj1.matchesTagsQuery("!tag3"); // true
myJSObj1.matchesTagsQuery("tag1 && tag3"); // false
myJSObj1.matchesTagsQuery("tag1 || tag3"); // true
myJSObj1.matchesTagsQuery("tag1 && !tag3"); // true
myJSObj1.removeTags("tag1");
myJSObj1.matchesTagsQuery("tag1 && !tag3"); // false
myJSObj2.removeTags("tag4 tag3 tag5");
myJSObj2.hasTags(); // false
BABYLON.Tags.DisableFor(myJSObj2);
myJSObj2.hasTags(); // TypeError: undefined is not a function
myJSObj3.matchesTagsQuery(""); // false
myJSObj3.matchesTagsQuery(); // true
myJSObj4.matchesTagsQuery(""); // TypeError: undefined is not a function
myJSObj4.matchesTagsQuery(); // TypeError: undefined is not a function
BABYLON.Tags.MatchesQuery(myJSObj4, ""); // false
BABYLON.Tags.MatchesQuery(myJSObj4, undefined); // true
BABYLON.Tags.MatchesQuery(myJSObj4); // true
Since it's possible to use tags on any javascript object and since meshes are javascript objects, it's possible to add tags on them and to retrieve them according to a tags query.
var meshes = myScene.getMeshesByTags("tag1 && (tag2 || tag4 || !tag5)) || !(!tag1) && !!!tag5");
All tags added to meshes, cameras, lights... are saved to the scene files (see .babylon file format)) and reloaded from them.
It's up to you!
You can use them to retrieve all the meshes that should be lighted by the light "light1":
var meshesToLightByLight1 = myScene.getMeshesByTags("mustBeLightedByLight1");
or make some green ghosts appear when you want:
var ghosts = myScene.getMeshesByTags("ghost && green");
for(var index=0; index < ghosts.length; index++) {
ghosts[index].isVisible = true;
}