mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 12:57:59 +02:00
Merge pull request #14619 from SamGondelman/matTarget
Case 20240: Better material entity targeting
This commit is contained in:
commit
3ec9290dca
3 changed files with 53 additions and 22 deletions
|
@ -841,10 +841,14 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
||||||
* @property {number} priority=0 - The priority for applying the material to its parent. Only the highest priority material is
|
* @property {number} priority=0 - The priority for applying the material to its parent. Only the highest priority material is
|
||||||
* applied, with materials of the same priority randomly assigned. Materials that come with the model have a priority of
|
* applied, with materials of the same priority randomly assigned. Materials that come with the model have a priority of
|
||||||
* <code>0</code>.
|
* <code>0</code>.
|
||||||
* @property {string|number} parentMaterialName="0" - Selects the submesh or submeshes within the parent to apply the material
|
* @property {string} parentMaterialName="0" - Selects the mesh part or parts within the parent to which to apply the material.
|
||||||
* to. If in the format <code>"mat::string"</code>, all submeshes with material name <code>"string"</code> are replaced.
|
* If in the format <code>"mat::string"</code>, all mesh parts with material name <code>"string"</code> are replaced.
|
||||||
* Otherwise the property value is parsed as an unsigned integer, specifying the mesh index to modify. Invalid values are
|
* Otherwise the property value is parsed as an unsigned integer, specifying the mesh part index to modify. If <code>"all"</code>,
|
||||||
* parsed to <code>0</code>.
|
* all mesh parts will be replaced. If an array (starts with <code>"["</code> and ends with <code>"]"</code>), the string will be
|
||||||
|
* split at each <code>","</code> and each element will be parsed as either a number or a string if it starts with
|
||||||
|
* <code>"mat::"</code>. In other words, <code>"[0,1,mat::string,mat::string2]"</code> will replace mesh parts 0 and 1, and any
|
||||||
|
* mesh parts with material <code>"string"</code> or <code>"string2"</code>. Do not put spaces around the commas. Invalid values
|
||||||
|
* are parsed to <code>0</code>.
|
||||||
* @property {string} materialMappingMode="uv" - How the material is mapped to the entity. Either <code>"uv"</code> or
|
* @property {string} materialMappingMode="uv" - How the material is mapped to the entity. Either <code>"uv"</code> or
|
||||||
* <code>"projected"</code>. In "uv" mode, the material will be evaluated within the UV space of the mesh it is applied to. In
|
* <code>"projected"</code>. In "uv" mode, the material will be evaluated within the UV space of the mesh it is applied to. In
|
||||||
* "projected" mode, the 3D transform of the Material Entity will be used to evaluate the texture coordinates for the material.
|
* "projected" mode, the 3D transform of the Material Entity will be used to evaluate the texture coordinates for the material.
|
||||||
|
|
|
@ -1486,29 +1486,56 @@ bool Model::isRenderable() const {
|
||||||
return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty());
|
return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned int> Model::getMeshIDsFromMaterialID(QString parentMaterialName) {
|
std::set<unsigned int> Model::getMeshIDsFromMaterialID(QString parentMaterialName) {
|
||||||
// try to find all meshes with materials that match parentMaterialName as a string
|
std::set<unsigned int> toReturn;
|
||||||
// if none, return parentMaterialName as a uint
|
|
||||||
std::vector<unsigned int> toReturn;
|
|
||||||
const QString MATERIAL_NAME_PREFIX = "mat::";
|
|
||||||
if (parentMaterialName.startsWith(MATERIAL_NAME_PREFIX)) {
|
|
||||||
parentMaterialName.replace(0, MATERIAL_NAME_PREFIX.size(), QString(""));
|
|
||||||
for (unsigned int i = 0; i < (unsigned int)_modelMeshMaterialNames.size(); i++) {
|
|
||||||
if (_modelMeshMaterialNames[i] == parentMaterialName.toStdString()) {
|
|
||||||
toReturn.push_back(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toReturn.empty()) {
|
const QString all("all");
|
||||||
toReturn.push_back(parentMaterialName.toUInt());
|
if (parentMaterialName == all) {
|
||||||
|
for (unsigned int i = 0; i < (unsigned int)_modelMeshRenderItemIDs.size(); i++) {
|
||||||
|
toReturn.insert(i);
|
||||||
|
}
|
||||||
|
} else if (!parentMaterialName.isEmpty()) {
|
||||||
|
auto parseFunc = [this, &toReturn] (QString& target) {
|
||||||
|
if (target.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// if target starts with "mat::", try to find all meshes with materials that match target as a string
|
||||||
|
// otherwise, return target as a uint
|
||||||
|
const QString MATERIAL_NAME_PREFIX("mat::");
|
||||||
|
if (target.startsWith(MATERIAL_NAME_PREFIX)) {
|
||||||
|
std::string targetStdString = target.replace(0, MATERIAL_NAME_PREFIX.size(), "").toStdString();
|
||||||
|
for (unsigned int i = 0; i < (unsigned int)_modelMeshMaterialNames.size(); i++) {
|
||||||
|
if (_modelMeshMaterialNames[i] == targetStdString) {
|
||||||
|
toReturn.insert(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toReturn.insert(target.toUInt());
|
||||||
|
};
|
||||||
|
|
||||||
|
if (parentMaterialName.length() > 2 && parentMaterialName.startsWith("[") && parentMaterialName.endsWith("]")) {
|
||||||
|
QStringList list = parentMaterialName.split(",", QString::SkipEmptyParts);
|
||||||
|
for (int i = 0; i < list.length(); i++) {
|
||||||
|
auto& target = list[i];
|
||||||
|
if (i == 0) {
|
||||||
|
target = target.replace(0, 1, "");
|
||||||
|
}
|
||||||
|
if (i == list.length() - 1) {
|
||||||
|
target = target.replace(target.length() - 1, 1, "");
|
||||||
|
}
|
||||||
|
parseFunc(target);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parseFunc(parentMaterialName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {
|
void Model::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {
|
||||||
std::vector<unsigned int> shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str()));
|
std::set<unsigned int> shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str()));
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
for (auto shapeID : shapeIDs) {
|
for (auto shapeID : shapeIDs) {
|
||||||
if (shapeID < _modelMeshRenderItemIDs.size()) {
|
if (shapeID < _modelMeshRenderItemIDs.size()) {
|
||||||
|
@ -1531,7 +1558,7 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
|
void Model::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
|
||||||
std::vector<unsigned int> shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str()));
|
std::set<unsigned int> shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str()));
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
for (auto shapeID : shapeIDs) {
|
for (auto shapeID : shapeIDs) {
|
||||||
if (shapeID < _modelMeshRenderItemIDs.size()) {
|
if (shapeID < _modelMeshRenderItemIDs.size()) {
|
||||||
|
|
|
@ -513,7 +513,7 @@ private:
|
||||||
|
|
||||||
void calculateTextureInfo();
|
void calculateTextureInfo();
|
||||||
|
|
||||||
std::vector<unsigned int> getMeshIDsFromMaterialID(QString parentMaterialName);
|
std::set<unsigned int> getMeshIDsFromMaterialID(QString parentMaterialName);
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(ModelPointer)
|
Q_DECLARE_METATYPE(ModelPointer)
|
||||||
|
|
Loading…
Reference in a new issue