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

Enhancement: Consider Node Ancestry in Proto Type Restrictions #6574

Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
613e492
allow programatic determination of base node model ancestry
CoolSpy3 Jul 3, 2024
1a807d6
consider node ancestry in proto type restrictions
CoolSpy3 Jul 3, 2024
21b26cd
update documentation
CoolSpy3 Jul 3, 2024
2c9a21c
update test suite
CoolSpy3 Jul 3, 2024
c8efce6
run clang-format
CoolSpy3 Jul 3, 2024
ae41015
workaround Transform edge case
CoolSpy3 Jul 3, 2024
517e0dd
fix spacing in documentation
CoolSpy3 Jul 3, 2024
72c7e6a
update changelog
CoolSpy3 Jul 3, 2024
1b8bb81
initialize mParentModel in constructor
CoolSpy3 Jul 3, 2024
3ff040d
fix typo
CoolSpy3 Jul 3, 2024
42477d1
fix DerivedAppearanceProto file extension
CoolSpy3 Jul 3, 2024
806ebe7
add proto_allowed_mf_field_value test
CoolSpy3 Jul 3, 2024
116a96b
fix DerivedAppearanceProto filename
CoolSpy3 Jul 3, 2024
2fb9dac
fix test suite
CoolSpy3 Jul 3, 2024
ee1c732
fix test suite
CoolSpy3 Jul 3, 2024
11f33ad
create WbFieldValueRestriction
CoolSpy3 Jul 6, 2024
24bcb24
add parsing of '=' syntax to reenable old behavior
CoolSpy3 Jul 6, 2024
c455435
keep track of proto parents
CoolSpy3 Jul 6, 2024
1955c3b
update field validation checks
CoolSpy3 Jul 6, 2024
b2917aa
switch to '+' syntax
CoolSpy3 Jul 7, 2024
cef8dfd
check if old field validation behavior should be used
CoolSpy3 Jul 7, 2024
5261ff9
fix parsing of '+'
CoolSpy3 Jul 7, 2024
17ae94e
update tests
CoolSpy3 Jul 8, 2024
1625d8c
clarify error messages to indicate whether subtypes are allowed
CoolSpy3 Jul 8, 2024
c12c743
more tests
CoolSpy3 Jul 8, 2024
9246e35
bug fixes
CoolSpy3 Jul 8, 2024
1efc106
update docs
CoolSpy3 Jul 8, 2024
bed1441
documentation clarification
CoolSpy3 Jul 8, 2024
e355f6d
update changelog
CoolSpy3 Jul 8, 2024
2960ff3
clarify function name
CoolSpy3 Jul 8, 2024
aca6d79
run clang-format
CoolSpy3 Jul 8, 2024
13234e1
improve node insertion validity api
CoolSpy3 Jul 8, 2024
698a111
bug fixes
CoolSpy3 Jul 8, 2024
c1928dc
Merge branch 'develop' of https://github.com/cyberbotics/webots into …
CoolSpy3 Jul 8, 2024
16f6a78
fix file formatting
CoolSpy3 Jul 8, 2024
f3790c0
additional documentation
CoolSpy3 Jul 8, 2024
6cae940
fix isAllowedToInsert
CoolSpy3 Jul 9, 2024
7792d53
address comments from PR
CoolSpy3 Jul 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/reference/changelog-r2024.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ Released on December **th, 2023.
- **Change the name of the web scene format from `X3D` to `W3D` ([#6280](https://github.com/cyberbotics/webots/pull/6280)).**
- Enhancements
- Improved the image range of the rotating [Lidar](lidar.md) ([#6324](https://github.com/cyberbotics/webots/pull/6324)).
- Updated proto node restrictions to consider node ancestry ([#6574](https://github.com/cyberbotics/webots/pull/6574)).
- Cleanup
- Removed deprecated `windowPosition`, `pixelSize` fields of [Display](display.md) node ([#6327](https://github.com/cyberbotics/webots/pull/6327)).
- Bug Fixes
- Fixed error message on Windows when `libssl-3-x64.dll` was added to `PATH` ([#6553](https://github.com/cyberbotics/webots/pull/6553)).
- Fixed length of arrays returned by `getPose()` in Java ([#6556](https://github.com/cyberbotics/webots/pull/6556)).
- Fixed length of arrays returned by `CameraRecognitionObject.getColors()` in Java ([#6564](https://github.com/cyberbotics/webots/pull/6564))

4 changes: 2 additions & 2 deletions docs/reference/proto-definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ PROTO MyProto [
field SFString name "my proto"
field SFColor{0 0 0, 0.5 0.5 0.5, 1 1 1} color 0.5 0.5 0.5
field SFNode physics NULL
field MFNode{Solid{}, Pose{}} extensionSlot []
field MFNode{Solid{}, Transform{}} extensionSlot []
]
```

In this example, the `color` field value can only be `0 0 0`, `0.5 0.5 0.5` or `1 1 1` and the `extensionSlot` field can only accept [Solid](../reference/solid.md) and [Pose](../reference/pose.md) nodes.
In this example, the `color` field value can only be `0 0 0`, `0.5 0.5 0.5` or `1 1 1` and the `extensionSlot` field can only accept [Solid](../reference/solid.md), [Transform](../reference/transform.md) nodes, and nodes that inherit from them.
CoolSpy3 marked this conversation as resolved.
Show resolved Hide resolved

### IS Statements

Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Accelerometer.wrl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# simulation. The acceleration is measured along the 3 axes (X, Y and Z) and is
# expressed in m/s^2. It is mostly used to measure the direction of the
# gravity, but can be used for many other purposes.
# parent: Solid

Accelerometer {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Altimeter.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# The Altimeter node can be used to determine the global altitude of a robot or of a robot part.
# parent: Solid

Altimeter {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/BallJoint.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# A BallJoint node can be used to simulate a rotating motion with 3 DOF (ball and socket).
# parent: Hinge2Joint

BallJoint {
field SFNode jointParameters NULL # BallJointParameters specifying the joint anchor and spring and damper constants, minStop, maxStop related to the first axis
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/BallJointParameters.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# The BallJointParamaters node defines the parameters of a BallJoint node.
# parent: JointParameters

BallJointParameters {
field SFFloat position 0 # current position (rad)
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Billboard.wrl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# A Billboard node contains children nodes that rotate and translate automatically to face the viewpoint.
# It is otherwise similar to a Group node.
# parent: Group

Billboard {
#field that inherits from the Group node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Camera.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# The Camera node is used to model an on-board camera.
# parent: Solid

Camera {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Charger.wrl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# The Charger node is used to model a special kind of battery charger for the robots.
# When a robot gets close to a Charger, the robot's battery gets recharged.
# parent: Solid

Charger {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Compass.wrl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# A Compass node can be used to simulate 1, 2 and 3-axis digital compasses.
# It indicates the direction of the simulated magnetic north which is specified in the WorldInfo node.
# parent: Solid

Compass {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Connector.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Connector nodes are used to simulate mechanical docking systems, or any other type of device that
# can dynamically create a rigid link with a similar device.
# The physical connection between two Connectors can be created and destroyed at run time by the robot controller program.
# parent: Solid

Connector {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Display.wrl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# It can model an embedded screen or it can display any graphical
# information such as graphs, text, robot trajectory, filtered camera
# images and so on.
# parent: Solid

Display {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/DistanceSensor.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# The DistanceSensor node can be used to model an ultrasound sonar, an infra-red sensor,
# a single-ray laser or any type of device that measures the distance to objects.
# To model a Lidar sensor, you should rather use a Lidar node.
# parent: Solid

DistanceSensor {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Emitter.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# The Emitter node is used to model a radio, or infra-red emitter.
# It can be used to send data packets to Receiver nodes (onboard other robots).
# An Emitter cannot receive data: bidirectional communication requires two Emitter/Receiver pairs.
# parent: Solid

Emitter {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Fluid.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# A Fluid node can be used to represent a collection of fluid volumes where hydrostatic and hydrodynamic forces apply.
# parent: Pose

Fluid {
#fields that inherit from the Pose node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/GPS.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# The GPS node can be used to determine the global position of a robot or of a robot part.
# parent: Solid

GPS {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Gyro.wrl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# A Gyro node measures the angular velocity about 3 orthogonal axes (X, Y and Z).
# The output is in rad/s. The Gyro node is mostly used for balance control.
# parent: Solid

Gyro {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Hinge2Joint.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# A Hinge2Joint can be used to simulate a combination of two rotating motions along axes which intersect.
# It is equivalent to two HingeJoint nodes but it spares the creation of an intermediate solid and is therefore more stable.
# Spring and damping behavior can be specified.
# parent: HingeJoint

Hinge2Joint {
field SFNode jointParameters NULL # HingeJointParameters specifying anchor, axis, spring and damper constants, minStop, maxStop, suspension
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/HingeJointParameters.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# A HingeJointParameters defines the parameters of a HingeJoint node.
# parent: JointParameters

HingeJointParameters {
field SFFloat position 0 # current position (m or rad)
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/InertialUnit.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# The InertialUnit node simulates an Inertial Measurement Unit (IMU).
# The InertialUnit node computes and returns the roll, pitch and yaw angles of the
# robot with respect to the global coordinate system defined in the WorldInfo node.
# parent: Solid

InertialUnit {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/LED.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# The LED node can be used to model a light emitting diode (LED) that can be controlled by the robot.
# parent: Solid

LED {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Lidar.wrl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# The Lidar node is used to model an on-board lidar.
# A lidar is used to measure the distance to obstacles.
# parent: Solid

Lidar {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/LightSensor.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# A LightSensor node can be used to model a phototransistor, a photodiode or any type
# of device that measures the irradiance of light on its surface.
# A LightSensor node detects the light emitted by PointLight, SpotLight and DirectionalLight nodes.
# parent: Solid

LightSensor {
# fields inherited from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Microphone.wrl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# parent: Solid
Microphone {
# fields that inherit from the Solid node:
w3dField SFVec3f translation 0 0 0
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Pen.wrl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# A Pen node can be used to model a pen attached to a mobile robot.
# It can draw the trajectory of the robot on a textured ground.
# parent: Solid

Pen {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Pose.wrl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# The Pose node is a grouping node that defines a coordinate system for its children that is
# relative to the coordinate system of its parent.
# parent: Group

Pose {
#fields specific to the AbstractPose node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/PositionSensor.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# A PositionSensor allows a robot controller to read the position of a joint with respect to its main axis.
# parent: Solid

PositionSensor {
field SFString name "position sensor" # used by wb_robot_get_device()
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Propeller.wrl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# The Propeller node is used to model a motorized helix propeller.
# It can be used to propel underwater robots, flying robots, floating robots or even wheeled robots.
# parent: Solid

Propeller {
field SFVec3f shaftAxis 1 0 0 # thrust direction (m)
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Radar.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# The Radar node is used to model a radar device, commonly found in automobiles.
# parent: Solid

Radar {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Radio.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Experimental Radio node.
# parent: Solid

Radio {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/RangeFinder.wrl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# The RangeFinder node is used to model an on-board range finder.
# A range finder is used to measure the distance to obstacles.
# parent: Solid

RangeFinder {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Receiver.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# A Receiver node models a radio or infra-red receiver.
# It can be used to receive data packets emitted by Emitter nodes (onboard other robots).
# A Receiver cannot emit data: bidirectional communication requires two Emitter/Receiver pairs.
# parent: Solid

Receiver {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Robot.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# The Robot node is a generic type of robot.
# parent: Solid

Robot {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Solid.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# A Solid node can be used to represent objects in the simulated environment (e.g. obstacles, walls, ground, robot parts, etc.).
# Solid nodes can be collision detected (boundingObject) and therefore can prevent objects from intersecting.
# In addition, Solid nodes can have an optional Physics node that allow them to be simulated with the physics engine.
# parent: Pose

Solid {
#fields that inherit from the Pose node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Speaker.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# The Speaker node is used to model a loudspeaker device.
# It can be used to playback wav sound files as well as text-to-speech.
# The sounds are localized in the 3D space and rendered at the main viewpoint in stereo.
# parent: Solid

Speaker {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/TouchSensor.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# A TouchSensor can be used to measure contact force ("force", "force-3d") or simply detect collisions ("bumper").
# It is critical that 'boundingObject' of a TouchSensor is defined and placed appropriately.
# Refer to the Webots reference manual for more information on this.
# parent: Solid

TouchSensor { #models a bumper, button, cat whisker, force sensor etc.
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Track.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# The Track node can be used to simulate tracks of tank robots or conveyor belts.
# parent: Solid

Track {
#fields that inherit from the Solid node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/TrackWheel.wrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# A TrackWheel node can be used to simulate a wheel that it is part of a track system.
# parent: Group

TrackWheel {
#fields specific to the TrackWheel node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/Transform.wrl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# The Transform node is a grouping node that defines a coordinate system for its children that is
# relative to the coordinate system of its parent.
# The 'scale' field of a Transform node can be adjusted only in a graphical context and not in a 'boundingObject' context.
# parent: Pose

Transform {
#fields specific to the AbstractTransform node:
Expand Down
1 change: 1 addition & 0 deletions resources/nodes/VacuumGripper.wrl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# VacuumGripper nodes are used to simulate vacuum suction systems.
# The physical connection with a Solid can be created and destroyed at run time by the robot controller program.
# parent: Solid

VacuumGripper {
#fields that inherit from the Solid node:
Expand Down
21 changes: 17 additions & 4 deletions src/webots/vrml/WbFieldModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,9 @@ bool WbFieldModel::isValueAccepted(const WbValue *value, int *refusedIndex) cons
assert(mfNode);
foreach (const WbVariant acceptedVariant, mAcceptedValues) {
const WbNode *nodeAccepted = acceptedVariant.toNode();
if (nodeAccepted && (mfNode->item(i)->nodeModelName() == nodeAccepted->modelName() ||
mfNode->item(i)->modelName() == nodeAccepted->modelName())) {
if (nodeAccepted && (nodeAccepted->isProtoInstance() ?
isProtoNodeTypeAccepted(nodeAccepted->modelName(), mfNode->item(i)->proto()) :
isBaseNodeTypeAccepted(nodeAccepted->nodeModelName(), mfNode->item(i)->model()))) {
accepted = true;
break;
}
Expand Down Expand Up @@ -242,8 +243,8 @@ bool WbFieldModel::isValueAccepted(const WbValue *value, int *refusedIndex) cons
return true;
const WbNode *nodeAccepted = acceptedVariant.toNode();
assert(nodeAccepted);
if (sfNode->value()->nodeModelName() == nodeAccepted->modelName() ||
sfNode->value()->modelName() == nodeAccepted->modelName())
if (nodeAccepted->isProtoInstance() ? isProtoNodeTypeAccepted(nodeAccepted->modelName(), sfNode->value()->proto()) :
isBaseNodeTypeAccepted(nodeAccepted->nodeModelName(), sfNode->value()->model()))
return true;
} else if (singleValue->variantValue() == acceptedVariant)
return true;
Expand All @@ -253,6 +254,18 @@ bool WbFieldModel::isValueAccepted(const WbValue *value, int *refusedIndex) cons
return false;
}

bool WbFieldModel::isBaseNodeTypeAccepted(const QString &expectedType, const WbNodeModel *actualType) const {
if (!actualType)
return false;
return expectedType == actualType->name() || isBaseNodeTypeAccepted(expectedType, actualType->parentModel());
}

bool WbFieldModel::isProtoNodeTypeAccepted(const QString &expectedType, const WbProtoModel *actualType) const {
if (!actualType)
return false;
return expectedType == actualType->name() || isProtoNodeTypeAccepted(expectedType, actualType->ancestorProtoModel());
}

bool WbFieldModel::isMultiple() const {
return dynamic_cast<WbMultipleValue *>(mDefaultValue);
}
Expand Down
4 changes: 4 additions & 0 deletions src/webots/vrml/WbFieldModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
//

#include <QtCore/QString>
#include <WbNodeModel.hpp>
#include <WbProtoModel.hpp>
#include <WbValue.hpp>
#include <WbVariant.hpp>

Expand Down Expand Up @@ -53,6 +55,8 @@ class WbFieldModel {

// accepted values
bool isValueAccepted(const WbValue *value, int *refusedIndex) const;
bool isBaseNodeTypeAccepted(const QString &expectedType, const WbNodeModel *actualType) const;
bool isProtoNodeTypeAccepted(const QString &expectedType, const WbProtoModel *actualType) const;
bool hasRestrictedValues() const { return !mAcceptedValues.isEmpty(); }
const QList<WbVariant> acceptedValues() const { return mAcceptedValues; }

Expand Down
13 changes: 12 additions & 1 deletion src/webots/vrml/WbNodeModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ void WbNodeModel::cleanup() {
delete it.next().value();
}

WbNodeModel::WbNodeModel(WbTokenizer *tokenizer) : mInfo(tokenizer->info()), mName(tokenizer->nextWord()) {
WbNodeModel::WbNodeModel(WbTokenizer *tokenizer) :
mInfo(tokenizer->info()),
mName(tokenizer->nextWord()),
mParentName(tokenizer->parent()),
mParentModel(NULL) {
tokenizer->skipToken("{");

while (tokenizer->peekWord() != "}") {
Expand Down Expand Up @@ -78,6 +82,13 @@ void WbNodeModel::readAllModels() {
cModels.insert(model->name(), model);
}

// Now that all the models are loaded, populate the ancestry tree
foreach (QString baseModelName, baseModelNames()) {
WbNodeModel *baseModel = findModel(baseModelName);
if (baseModel)
baseModel->mParentModel = findModel(baseModel->mParentName);
}

qAddPostRoutine(WbNodeModel::cleanup);
}

Expand Down
7 changes: 7 additions & 0 deletions src/webots/vrml/WbNodeModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ class WbNodeModel {
const QList<WbFieldModel *> &fieldModels() const { return mFieldModels; }
QStringList fieldNames();

// parent nodes (only defined for base nodes. For proto nodes, see
// WbProtoModel::ancestorProtoName/ancestorProtoNameModel/baseType)
const QString parentName() const { return mParentName; };
const WbNodeModel *parentModel() const { return mParentModel; };

QStringList documentationBookAndPage() const { return QStringList() << "reference" << mName.toLower(); }

private:
Expand All @@ -60,6 +65,8 @@ class WbNodeModel {
QString mInfo;
QString mName;
QList<WbFieldModel *> mFieldModels;
QString mParentName;
WbNodeModel *mParentModel;

static WbNodeModel *readModel(const QString &fileName);
static void readAllModels();
Expand Down
Loading
Loading