multimaterial support, "preset"
each preset contains visibility, flags and material
This commit is contained in:
@@ -91,6 +91,7 @@ void Scene::assignFrom(const Scene * s) {
|
||||
addObject(s->root_->child(i)->clone());
|
||||
// qDebug() << i << o->child(i)->pos();
|
||||
}
|
||||
setPreset(s->preset());
|
||||
tree_changed = mat_changed = lights_changed = need_reload_materials = tree_struct_changed = true;
|
||||
}
|
||||
|
||||
@@ -321,11 +322,16 @@ Material * Scene::newMaterial(const QString & name) {
|
||||
void Scene::removeMaterial(Material * m) {
|
||||
if (!m || !materials.contains(m)) return;
|
||||
ObjectBaseList ol = root_->children(true);
|
||||
foreach(ObjectBase * o, ol)
|
||||
if (o->material_ == m) o->setMaterial(0);
|
||||
for (auto * o: ol)
|
||||
for (auto & p: o->presets)
|
||||
if (p.material == m) {
|
||||
p.material = nullptr;
|
||||
o->setObjectsChanged();
|
||||
}
|
||||
materials.removeAll(m);
|
||||
changed_materials.removeAll(m);
|
||||
mat_changed = true;
|
||||
mat_changed = true;
|
||||
tree_changed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -349,6 +355,15 @@ void Scene::removeLight(Light * l) {
|
||||
}
|
||||
|
||||
|
||||
void Scene::setPreset(int preset) {
|
||||
if (cur_preset == preset) return;
|
||||
cur_preset = preset;
|
||||
root_->setPreset(cur_preset);
|
||||
mat_changed = tree_changed = tree_struct_changed = lights_changed = true;
|
||||
emit presetChanged(cur_preset);
|
||||
}
|
||||
|
||||
|
||||
void Scene::dump() {
|
||||
qDebug() << "Scene" << name();
|
||||
qDebug() << "Meshes:" << geometries.size();
|
||||
@@ -371,28 +386,31 @@ void Scene::attachObject(ObjectBase * o) {
|
||||
o->setMesh(attachMesh(o->mesh()));
|
||||
setObjectMeshChanged(o);
|
||||
}
|
||||
if (o->material()) { // search suitable material in this scene
|
||||
uint ohash = o->material()->hash();
|
||||
bool need_new = true;
|
||||
foreach(Material * m, materials) {
|
||||
if (m == o->material()) { // already exists by ptr
|
||||
need_new = false;
|
||||
break;
|
||||
for (auto & p: o->presets) {
|
||||
if (p.material) { // search suitable material in this scene
|
||||
uint ohash = p.material->hash();
|
||||
bool need_new = true;
|
||||
foreach(Material * m, materials) {
|
||||
if (m == p.material) { // already exists by ptr
|
||||
need_new = false;
|
||||
break;
|
||||
}
|
||||
if (m->hash() == ohash) { // already exists by hash
|
||||
need_new = false;
|
||||
p.material = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m->hash() == ohash) { // already exists by hash
|
||||
need_new = false;
|
||||
o->setMaterial(m);
|
||||
break;
|
||||
if (need_new) { // need to clone material and add to scene
|
||||
Material * nmat = new Material();
|
||||
*nmat = *(p.material);
|
||||
nmat->setMapsChanged();
|
||||
p.material = nmat;
|
||||
materials << nmat;
|
||||
}
|
||||
}
|
||||
if (need_new) { // need to clone material and add to scene
|
||||
Material * nmat = new Material();
|
||||
*nmat = *(o->material());
|
||||
nmat->setMapsChanged();
|
||||
o->setMaterial(nmat);
|
||||
materials << nmat;
|
||||
}
|
||||
}
|
||||
o->setPreset(cur_preset);
|
||||
setTreeStructChanged();
|
||||
}
|
||||
|
||||
@@ -507,15 +525,25 @@ void Scene::destroyUnused(QOpenGLExtraFunctions * f) {
|
||||
QDataStream & operator<<(QDataStream & s, const Scene * p) {
|
||||
ChunkStream cs;
|
||||
// qDebug() << "place" << p->name() << "...";
|
||||
QVector<short> geom_ind, mat_ind;
|
||||
QVector<short> geom_ind, mats;
|
||||
QVector<QVector<short>> mat_ind;
|
||||
ObjectBaseList cl = p->root_->children(true);
|
||||
geom_ind.reserve(cl.size());
|
||||
mat_ind.reserve(cl.size());
|
||||
foreach(ObjectBase * c, cl) {
|
||||
for (auto * c: cl) {
|
||||
geom_ind << p->geometries.indexOf(c->mesh());
|
||||
mat_ind << p->materials.indexOf(c->material());
|
||||
mats.clear();
|
||||
for (auto i: c->presets)
|
||||
mats << p->materials.indexOf(i.material);
|
||||
mat_ind << mats;
|
||||
}
|
||||
cs.add(1, p->name_).add(10, p->geometries).add(11, p->materials).add(20, p->root_).add(21, geom_ind).add(22, mat_ind);
|
||||
cs.add(1, p->name_)
|
||||
.add(10, p->geometries)
|
||||
.add(11, p->materials)
|
||||
.add(20, p->root_)
|
||||
.add(21, geom_ind)
|
||||
.add(23, mat_ind)
|
||||
.add(24, p->cur_preset);
|
||||
s << qCompress(cs.data());
|
||||
return s;
|
||||
}
|
||||
@@ -525,7 +553,9 @@ QDataStream & operator>>(QDataStream & s, Scene *& p) {
|
||||
s >> ba;
|
||||
ba = qUncompress(ba);
|
||||
ChunkStream cs(ba);
|
||||
QVector<short> geom_ind, mat_ind;
|
||||
QVector<short> geom_ind, mat_ind_v0;
|
||||
QVector<QVector<short>> mat_ind_v1;
|
||||
int version = 0, preset = 0;
|
||||
while (!cs.atEnd()) {
|
||||
switch (cs.read()) {
|
||||
case 1: cs.get(p->name_); break;
|
||||
@@ -536,16 +566,44 @@ QDataStream & operator>>(QDataStream & s, Scene *& p) {
|
||||
p->root_->setScene(p);
|
||||
break;
|
||||
case 21: cs.get(geom_ind); break;
|
||||
case 22: cs.get(mat_ind); break;
|
||||
case 22:
|
||||
cs.get(mat_ind_v0);
|
||||
version = 0;
|
||||
break;
|
||||
case 23:
|
||||
cs.get(mat_ind_v1);
|
||||
version = 1;
|
||||
break;
|
||||
case 24: cs.get(preset); break;
|
||||
}
|
||||
}
|
||||
p->makeMaterialsUniqueNames();
|
||||
ObjectBaseList cl = p->root_->children(true);
|
||||
int cnt = qMin(qMin(cl.size(), geom_ind.size()), mat_ind.size());
|
||||
int cnt = qMin(cl.size(), geom_ind.size());
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
ObjectBase * c(cl[i]);
|
||||
if (geom_ind[i] >= 0) c->mesh_ = p->geometries[geom_ind[i]];
|
||||
if (mat_ind[i] >= 0) c->material_ = p->materials[mat_ind[i]];
|
||||
}
|
||||
if (version == 0) {
|
||||
cnt = qMin(cl.size(), mat_ind_v0.size());
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
if (mat_ind_v0[i] >= 0) cl[i]->currentPreset().material = p->materials[mat_ind_v0[i]];
|
||||
}
|
||||
} else if (version == 1) {
|
||||
cnt = qMin(cl.size(), mat_ind_v1.size());
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
ObjectBase * c(cl[i]);
|
||||
const auto & matv(mat_ind_v1[i]);
|
||||
if (c->presets.size() < matv.size()) c->presets.resize(matv.size());
|
||||
for (int j = 0; j < matv.size(); ++j) {
|
||||
if (matv[j] >= 0)
|
||||
c->presets[j].material = p->materials[matv[j]];
|
||||
else
|
||||
c->presets[j].material = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
p->cur_preset = -1;
|
||||
p->setPreset(preset);
|
||||
return s;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user