I have multiple entities which I would like to share the same material. Therefore, if I make a change to the material properties, the properties would be updated on all the entities within the scene using that material.
Is this possible? If so, how can it be done?
Create a material manually and attach to mesh:
var material = new THREE.SomeMaterial();
AFRAME.registerComponent('my-material', {
this.el.getObject3D('mesh').material = material;
});
<a-entity geometry my-material></a-entity>
And then you can manually manipulate the material whenever you want and it will auto-apply to all entities / meshes using it (e.g., material.color.set(0.5, 0.5, 0.5)).
The mixin method also works although slightly less efficient and more abstracted
Use a-mixin with a material component and manipulate its attributes. All entities that have it applied will update:
https://aframe.io/docs/0.8.0/core/mixins.html#sidebar
Related
i'm adding aframe entities programmatically.
I didn't find how to set their class so that they get raycaster events.
i tried this without succes:
this.el.setAttribute('class', 'link');
or:
this.el.className = "link";
From the docs (I'm linking MDN, for this is not aframe exclusive):
Add a class using
this.el.classList.add("myClass");
Remove it using
this.el.classList.remove("myClass");
You can check out this fiddle where i add/remove classes to set which objects are clickable. Here with a mouse-cursor instead of the classic one.
I have a content type with geo data that I'd like to display on a map based on some contextual filters. There are multiple views on the site with different configs. I have defined my map, its behaviors, default layer, etc. and it works with an "all nodes of x type" view using an Openlayers data overlay and a map display.
A second view has it's own data overlay with a different set of points and a map display. I'd like to reuse the same Openlayers map so that any future changes to behaviors, zoom levels, etc. don't need to be made across multiple maps.
The problem I'm having is that whatever layer I define as activated in the Openlayers map is the default layer for all the views using that map. I need some way to define a default activated layer based on the view, url, or something else. Any ideas on how to achieve this?
First you have to create or clone and modify a view.
Second, you have to create another Openlayers map in /admin/structure/openlayers/maps/list/, and at the layers and styles/overlay layers you have to enable the layer of the newly created view.
Third, you have to edit the view and at the view format's settings you can select the new map.
Came up with a single view solution awhile back and forgot to post it. This allows you to create a single view using a single OpenLayers Map block with multiple data overlays within the same view, setting the active one based on URL. The benefits of this approach are that a change to one field populates across all of the displays and changing the map's styling, behavior, etc. only needs to be done once. This simplifies maintenance and changes for folks.
Here's what worked:
1. Create you OpenLayers map, layer definitions, etc. as you normally would.
2. Create a new view with the Format: OpenLayers Map. Configure it as you normally would.
3. To the OpenLayers Map view, add new OpenLayers Data Overlay displays for each source.
4. Edit the OpenLayers Map. Under Overlay Layers, check enabled and in switcher for each new Data Overlay. In my case, the Activated checkboxes are all unchecked.
5. Implement hook_openlayers_map_preprocess_alter(). Here's what mine looks like
function mymoduleortheme_openlayers_map_preprocess_alter(&$map = array()) {
//$displayLayer['URL param'] = "map_data_overlay_machine_name";
$displayLayer = array();
$displayLayer['first-page'] = "openlayers_maps_openlayers_first_page_data";
$displayLayer['another-page'] = "openlayers_maps_openlayers_another_page_data";
$currentURI = array();
$currentURI = explode("/", $_SERVER['REQUEST_URI']);
foreach ($map['layer_switcher'] as $idx => $val) {
//Map data found, activate the correct
if (isset($currentURI[2]) && isset($displayLayer[$currentURI[2]]) && $idx == $displayLayer[$currentURI[2]]) {
$map['layer_activated'][$displayLayer[$currentURI[2]]] = $displayLayer[$currentURI[2]];
}
else
$map['layer_switcher'][$idx] = 0;
}
}
Probably room for improvement, but it's working and does the trick. The switcher isn't used on this site so it's just CSS'd out.
I have been trying to get my head around a way to intergrate Ember.js with Three.js. In particular, I want to render a number of elements, controlling the data with Ember.js bindings and general pub/sub handling, but also wont to be able to manipulate the views/elements with three.js using THREE.CSS3DObject.
I'm fairly confident with Ember but new to Three. I guess what I'm thinking is, can I have an element that exists in both the THREE.Scene and the Ember application namespace?
In the THREE.js periodic table example:
http://mrdoob.github.com/three.js/examples/css3d_periodictable.html
an DOM.element is create and then later decorated with attributes (style, position etc).
var element = document.createElement( 'div' );
element.className = 'element';
element.style.backgroundColor = 'rgba(0,127,127,'+(Math.random()* 0.5 + 0.25 ) + ')';
Later, it is added as an element to the THREE.CSS3Object constructor:
var object = new THREE.CSS3DObject( element );
I'm wondering if I can create the elements in perhaps an Ember containerView and then use jQuery to iterate over the childViews, caching the currently iterated element as 'element' and then render this to the THREE.CSS3DObject constructor?
I know it's a bit hacky and I only mention the above as some indication that I have tried to think up a way before asking for help! haha!
Any guidance or even pie in the sky suggestions like mine would be greatly appreciated. Thanks in advance.
Three's CSS3D renderer is just a thin abstraction of the browsers' own renderer and therefore should not conflict with the manipulation of DOM elements with Ember or jQ.
Once passed to the CSS3DObject constructor, an element's 3D transforms are updated but beyond that, it's business as usual. You can manipulate its content and style it as needed.
What's the fastest way to render dijit widgets?
I know that the programmatic way is faster than the declarative. (Some reference)
I have a custom widget that loads too slowly (it's a datagrid with combobox, buttons and other small dijit widgets used for adding filters, etc).
Looking at the source, I see that all the dijit widgets are created programmatically, but the DOM nodes where they are inserted into are created programmatically as well.
Is it the "right" way?
I'm trying to speed up the rendering of this widget, and currently my choice would be to combine a velocity template (my company uses struts2 + velocity) to create the DOM nodes, with programmatically created widgets (using placeAt and similar methods to insert the widgets into the already built DOM nodes).
It would work fine, but sadly all the css classes are overwritten by dijit, so I have to overwrite them again, which causes a sensible overhead.
In the template I write something like this:
<input id="idOfAnExistingDomNode" class="myCssClass" />
And to insert a FilteringSelect in that DOM node I have to write this:
var fieldSelect = new dijit.form.FilteringSelect({
store : jsonStore,
searchAttr : "caption",
labelAttr : "caption",
selectOnClick : true,
value : "Content"
}, "idOfAnExistingDomNode");
fieldSelect.domNode.className += " myCssClass";
The last line is necessary because myCssClass is overwritten during the creation of the FilteringSelect.
Is there any way to avoid this issue?
Or, perhaps, I'm trying to do this thing the wrong way? I'm not completely sure about that "velocity template" thing.
Note: Dojo version is 1.5 and no, sadly we can't upgrade it to newer versions.
Please forgive me for my TERRIBLE English.
Often one of the faster ways to instantiate widgets is to create them in a temporary div and then move that div onto the DOM. Have you tried profiling what exactly is slow in this instantiation? Part of me wonders if too much time is being spent waiting for data, as a few widgets + a grid with reasonable pagesize params shouldn't take long to load.
As for your class issue, it is strange that dojo is not mixing in the existing class. That said, you could do a lookup on the node first, get the class attribute, and then specify it as
the class attribute in your mixin object when creating the FilteringSelect. If you do so, be sure you wrap class in quotes or older IE's will reject it.
I have 2 components for example (editor.mxml using mx:windows), when I click an edit button, I want to get the current value from the other component's datafield? (datagrid.mxml using mx:window)
I do know how to access the main MXML's datagrid by parentDocument or Application.application method, but stumped block if I want to access other way as mentioned above. Keep the code as simple as possible.
You could either do dependency injection, that is, give component A a reference to component B so that they can communicate directly (example of tighter coupling,) or have both components communicate through a common mediator using events (example of more loose coupling.)
Both of those options would be implemented wherever it is that you're creating those components (A and B in this example) and adding them to the display list.
This might be more complicated than it deserves, and it smacks of Pattern-Fever, but you could use a mediator class that listens for the CLICK event from the button and knows enough about the other component to query its property. It could even transmit that data using a custom event, which the button listens for.
While this involves three classes instead of two, it often turns out to be easier to have two components that focus on looking good and one that worries about coordination.
Cheers
Try this:
FlexGlobals.topLevelApplication
This points Your root. From the root You can grab every element You want.
You can also add an id to the custom component like this,
<custom:Editor id="myCustomComponent">
</Editor:AddressForm>
and
access your datagrid's value like this,
var data:ArrayCollection = myCustomComponent.DatagridID.dataProvider;