How do I add a parent entity to a scene in Bevy? - rust

I'm trying to attach a ComponentFoo to a whole scene coming from a gltf file. From what I understand I need to put the scene entities under a parent entity possessing that ComponentFoo.
commands
.spawn_scene(asset_server.load("models/FlightHelmet/FlightHelmet.gltf"));
.with(ComponentFoo {})
gives the following error:
panicked at 'Cannot add component because the 'current entity' is not set.
and as expected, that doesn't work either:
commands
.spawn_scene(asset_server.load("models/FlightHelmet/FlightHelmet.gltf"));
.current_entity()
.unwrap()
How do I get a parent Entity of the scene? Or at list iterate over all entities of that scene? The gltf loader seems to add a parent entity containing a Transform at the root of the loaded scenes, how could I pinpoint it?

Related

How to bind non-UI entity with UI entity in Bevy

Description
I'm trying to implement trigger logic when the player faced the trigger I should remove the UI element from the screen.
Spawning the trigger point
/// Create a trigger point and when the user faced with
/// it I'll mark the tutorial as `in-progress` and
/// remove it when the collision between tutorial
/// and player is stopped
commands
.insert(Sensor(true))
.insert(Collider::cuboid(8.0, 8.0))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert_bundle(SpriteBundle {
sprite: Sprite {
color: Color::rgb(0.1, 0.1, 0.1),
custom_size: Some(Vec2::new(16.0, 16.0)),
..Default::default()
},
transform: *tutorial_transform,
..Default::default()
})
// Tutorial is a component which I'll filter as `tutorial_entity`
.insert(Tutorial);
Create a UI
commands
.spawn_bundle(NodeBundle {
///
})
/// Trying to bind UI element with `Tutorial` entity
/// to remove it from the screen when the user faced with collider
.insert(Parent(tutorial_entity))
When the user faced collision
// I want to despawn all children UI elements that are linked with this non-UI element
commands.entity(tutorial_entity).despawn_recursive()
Error
I've got an error and no UI on the screen at all
Styled child in a non-UI entity hierarchy. You are using an entity with UI components as a child of an entity without UI components, results may be unexpected
Question
Do you know how to link a non-UI element with a UI element to remove the non-UI element and remove all linked UI elements with it?
I don't know if its still relevant but you could always just create a separate UI entity and add your own reference component.
I guess the for structurings sake i would create ( for example ) a UILinkComponent(pub Entity) and attach it to the world entity.
Pretty sure you shouldn't use Parent for that kind of relationship. The hierarchy is typically used for spatial relationships.
You should instead create a new component that stores the other Entity. You can still destroy it in the same way, but this way it isn't part of the hierarchy so the other UI elements don't get confused.

Clean way to get mousePressed event notified to QGraphicsView

I inherited from QGraphicsItemGroup and made a class that keeps a pointer to its contained items so that I can later refer to them and change properties. It has an ellipse item and a line item and I want only the ellipse to be clickable. I need that press event of the ellipse to propagate to the QGraphicsView so that I can send a signal to some surrounding widgets.
So far I tried inheriting also from QGraphicsObject to have signals available but got stuck with ambigous base error when trying to use scene->addItem. I tried casting to QGraphicsItemGroup but I still get the error. I also tried inheriting from QObject with no success.
I'm new to QGraphics and I know the QGraphics framework has a lot of tools for user interaction and even interaction between GraphicsItems but this is really kicking my butt.
What would be the proper way to get this behavior?
Create a separate "emitter" class
To allow your subclass of QGraphicsItemGroup to emit signals, you can create a separate "emitter" class that inherits from QObject. Then, you can add an instance of this emitter class within your subclass of QGraphicsItemGroup. The emitter object can then emit signals for your subclass as needed.
QGraphicsItemGroup is treated as a single item
Unfortunately, an instance of QGraphicsItemGroup is treated as a single item, so each mousePressEvent will belong to the entire group rather than one of the members of that group (i.e., the ellipse item or the line item). If you want the mousePressEvent to behave differently depending on which item is clicked, they will need to be separate items, or you could try using line->setParentItem(ellipse) to link up the 2 items without using QGraphicsItemGroup.

Sprite node suddenly not found Godot

I added my player as a singleton and now Godot cannot find its sprite node. The game crashes when I try to move and gives me a "get_node: Node not found: Sprite." error. Does anyone know what to do?
If by "singleton" you mean AutoLoad, please pay attention that this concept was introduced to Godot as a workaround for storing scene-independent or inter-scene information. As documentation says:
When autoloading a script, a Node will be created and the script will be attached to it. This node will be added to the root viewport before any other scenes are loaded.
As far as I understood from your question, the Sprite node is a child of a node that had a script attached to it with a line of code, similar to
self.get_node("Sprite")...
But when you AutoLoaded this script, you actually introduced a new node as a child of a root viewport, and this node does not inherit the tree structure of the "original" node that had Sprite child. It has only the same script attached as the original node. Also referring by AutoLoad name will refer to this new object (without Sprite child) rather than your original one.
I think what you wanted to do is to provide an inter-scene way to refer to that particular node (that has its Sprite child). I would recommend to look into Godot's Groups to do that in a clean way. Put your node to a specific group and then request it from that group:
theNode.add_to_group("MyPublicNodes")
# Get that node somewhere and get its `Sprite` child
get_tree().get_nodes_in_group("MyPublicNodes")[0].get_node("Sprite")

QT5: What is the Significance of a Layout's Parent?

I am attempting to write my first program using Qt5. I found a tutorial (zetcode.com/gui/qt5) with a number of examples, which all used dynamic layout creation. I'm trying to create a nested layout configuration, but I'm having a problem with specifying the parent parameter of the layout constructor. When I use the main window as the parent for the main layout and its sub-layouts, I get an error message, apparently telling me that QWidget can have only one QLayout. The window looks OK, but I haven't implemented all my functionality yet (slots and other code), so I don't know what, if anything, is broken. If I omit the parent parameter from the sub-layouts, I get no error messages and the window looks OK as well, but again I'm wondering whether this would affect my subsequent code additions.
Can anyone explain to me the significance of a layout's parent? I've noted that specification of the parent window in the layout's constructor is apparently not sufficient, because all of the examples I've seen call setLayout() at the end of the window's constructor. In particular, will my omission of a parent ever cause problems?
The "rules" are that there can be at most one top level layout on a given widget, and that widgets can be only children of other widgets, not of layouts. So what happens is that:
when you set a layout on a widget, the widget will take ownership of that layout;
when you add widgets on a layout, these widgets will be reparented to the widget the layout is/gets installed upon;
when you add a layout inside another layout, the inner layout becomes a child of the outer layout.
What you're probably seeing is a side-effect of creating a layout with a widget as parent, as in
QLayout *layout = new SomeLayout(widget);
This will try to install the layout on widget, and fail in case there's already one. The good news is, you can pretty much ignore passing parents around and rely on the system to do "the right thing". For instance:
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
QHBoxLayout *mainLayout = new QHBoxLayout; // top level layout
QVBoxLayout *subLayout1 = new QVBoxLayout; // sub layout 1 stuff
QPushButton *button = new QPushButton("button");
subLayout1->addWidget(button);
// create more widgets...
mainLayout->addLayout(subLayout1);
QVBoxLayout *subLayout2 = new QVBoxLayout; // sub layout 2 stuff
QLineEdit *edit = new QLineEdit;
subLayout2->addWidget(edit);
mainLayout->addLayout(subLayout2);
setLayout(mainLayout);
}
This will correctly create a layout hierarchy and a parent/child relation so that nothing will get leaked.

Relationships are (null) when -awakeFromInsert message received by new object in NSOrderedSet

The following -awakeFromInsert implementation sets properties of new objects instantiated by array controllers in a UI when the user presses an add button:
- (void)awakeFromInsert
{
[super awakeFromInsert];
NSLog(#"Adding perceptron %ld to layer %ld", self.indexInLayer, self.layer.indexInNetwork);
NSLog(#"New perceptron added to layer %#", self.layer );
// more code here to do the configuration
}
The problem is that the self.parent relationship of the new object is not set when -awakeFromInsert is called (it is nil) so I can't use it to access the parent object (for example how many childs there are or what index the new object is).
Output of the above code:
2012-12-17 21:36:39.309 MLPManager[98112:403] Adding perceptron 0 to layer 0
2012-12-17 21:36:39.309 MLPManager[98112:403] New perceptron added to layer (null)
I'm pretty sure that the new objects are being connected up correctly because the indexInLayer method works perfectly when the UITableView calls it to add indexes of the objects to the view:
- (NSUInteger)indexInLayer
{
NSUInteger index = [self.layer.perceptrons indexOfObject:self];
//NSLog(#"indexInLayer returning %ld", index );
return index;
}
My data model has three entities: Network, Layer, Perceptron arranged as ordered sets and connected to the next by to-many relationships (i.e. Parent - Child - Grandchild). My UI has three array controllers and three UITableViews. I've set it up so that the Child array controller only contains the children of the selected Parent, and the Grandchild array controller only contains the grandchildren of the selected Child. When I add childs or grandchilds to these arraycontrollers they are automatically set as children of the currently selected parent. That all works fine.
At what point is self.layer set by the UI? Can someone confirm that this is occurring after -awakeFromInsert? And if so, how am I supposed to configure a new object if I can't do it from within -awakeFromInsert? I note that the Apple documentation for -awakeFromInsert says it is "invoked automatically by the Core Data framework when the receiver is first inserted into a managed object context."
The reason I need information on the layer object and other parts of the data structure is that I need to automatically instantiate various other objects (weights which are children of perceptrons) at the same time as the new perceptron object. Should I be using -awakeFromInsert for these kind of tasks?
First, there appears to be coupling in your code between model (NSManagedObject) and view (UITableView) objects. That is not recommended according to the model-view-controller design pattern.
layer and indexInLayer are not standard attributes of NSManagedObject so I assume these are attributes in your entity. As an alternative to doing the setup in awakeFromInsert, I wonder if you can instead implement your own setter methods for your attributes so that you can do the necessary work at the time the required data is available.
If you choose to implement your own setter methods, you need to follow Apple's guidance in the Managed Object Accessor Methods documentation, specifically:
You must ensure that you invoke the relevant access and change
notification methods (willAccessValueForKey:, didAccessValueForKey:,
willChangeValueForKey:, didChangeValueForKey:,
willChangeValueForKey:withSetMutation:usingObjects:, and
didChangeValueForKey:withSetMutation:usingObjects:).
I do not know why layer and indexInLayer are not usable in your awakeFromInsert method; it's possible you need to solve that problem instead.

Resources