/*
* Project: MoleCuilder
* Description: creates and alters molecular systems
* Copyright (C) 2010-2012 University of Bonn. All rights reserved.
* Copyright (C) 2013 Frederik Heber. All rights reserved.
*
*
* This file is part of MoleCuilder.
*
* MoleCuilder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MoleCuilder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MoleCuilder. If not, see .
*/
/*
* GLWorldScene.cpp
*
* This is based on the Qt3D example "teaservice", specifically parts of teaservice.cpp.
*
* Created on: Aug 17, 2011
* Author: heber
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
#include "GLWorldScene.hpp"
#include
#include
#include
#include
#include
#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject.hpp"
#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_atom.hpp"
#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_bond.hpp"
#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.hpp"
#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_shape.hpp"
#include "UIElements/Qt4/InstanceBoard/QtObservedInstanceBoard.hpp"
#include "CodePatterns/MemDebug.hpp"
#include "CodePatterns/Log.hpp"
#include "Actions/SelectionAction/Atoms/AtomByIdAction.hpp"
#include "Actions/SelectionAction/Atoms/NotAtomByIdAction.hpp"
#include "Actions/SelectionAction/Molecules/MoleculeByIdAction.hpp"
#include "Actions/SelectionAction/Molecules/NotMoleculeByIdAction.hpp"
#include "Atom/atom.hpp"
#include "Bond/bond.hpp"
#include "Descriptors/AtomIdDescriptor.hpp"
#include "Descriptors/MoleculeIdDescriptor.hpp"
#include "Helpers/helpers.hpp"
#include "Shapes/ShapeRegistry.hpp"
#include "molecule.hpp"
#include "World.hpp"
#include
using namespace MoleCuilder;
GLWorldScene::GLWorldScene(
QtObservedInstanceBoard * _board,
QObject *parent) :
QObject(parent),
selectionMode(SelectAtom),
board(_board)
{
int sphereDetails[] = {5, 3, 2, 0};
int cylinderDetails[] = {16, 8, 6, 3};
for (int i=0;isetOption(QGLSceneNode::CullBoundingBox, true);
QGLBuilder cylinderBuilder;
cylinderBuilder << QGLCylinder(.25,.25,1.0,cylinderDetails[i]);
GLMoleculeObject::meshCylinder[i] = cylinderBuilder.finalizedSceneNode();
GLMoleculeObject::meshCylinder[i]->setOption(QGLSceneNode::CullBoundingBox, true);
}
connect(board, SIGNAL(moleculeInserted(QtObservedMolecule::ptr)),
this, SLOT(moleculeSignOn(QtObservedMolecule::ptr)), Qt::DirectConnection);
connect(board, SIGNAL(moleculeRemoved(ObservedValue_Index_t)),
this, SLOT(moleculeSignOff(ObservedValue_Index_t)), Qt::DirectConnection);
connect(board, SIGNAL(atomInserted(QtObservedAtom::ptr)),
this, SLOT(atomInserted(QtObservedAtom::ptr)));
connect(board, SIGNAL(atomRemoved(ObservedValue_Index_t)),
this, SLOT(atomRemoved(ObservedValue_Index_t)));
connect(this, SIGNAL(insertMolecule(QtObservedMolecule::ptr)),
this, SLOT(moleculeInserted(QtObservedMolecule::ptr)) );
connect(this, SIGNAL(removeMolecule(QtObservedMolecule*)),
this, SLOT(moleculeRemoved(QtObservedMolecule*)) );
// connect(this, SIGNAL(updated()), this, SLOT(update()));
}
GLWorldScene::~GLWorldScene()
{
// remove all elements
GLMoleculeObject::cleanMaterialMap();
}
void GLWorldScene::atomClicked(atomId_t no)
{
LOG(3, "INFO: GLMoleculeObject_molecule - atom " << no << " has been clicked.");
const atom * const Walker = const_cast(World::getInstance()).
getAtom(AtomById(no));
ASSERT( Walker != NULL,
"GLWorldScene::atomClicked() - clicked atom has disappeared.");
if (selectionMode == SelectAtom){
if (!World::getInstance().isSelected(Walker))
SelectionAtomById(std::vector(1,no));
else
SelectionNotAtomById(std::vector(1,no));
}else if (selectionMode == SelectMolecule){
const molecule *mol = Walker->getMolecule();
ASSERT(mol, "Atom without molecule has been clicked.");
molids_t ids(1, mol->getId());
if (!World::getInstance().isSelected(mol))
SelectionMoleculeById(ids);
else
SelectionNotMoleculeById(ids);
}
emit clicked(no);
}
void GLWorldScene::moleculeClicked(moleculeId_t no)
{
LOG(3, "INFO: GLMoleculeObject_molecule - mol " << no << " has been clicked.");
const molecule * const mol= const_cast(World::getInstance()).
getMolecule(MoleculeById(no));
ASSERT(mol, "Atom without molecule has been clicked.");
molids_t ids(1, mol->getId());
if (!World::getInstance().isSelected(mol))
SelectionMoleculeById(ids);
else
SelectionNotMoleculeById(ids);
emit clicked(no);
}
/** Prepares insertion of a general atom.
*
* This is called before the insertion into a molecule and thus before the
* insertion into the scene.
*
* @param _atom atom to insert
*/
void GLWorldScene::atomInserted(QtObservedAtom::ptr _atom)
{
const ObservedValue_Index_t atomid = _atom->getIndex();
ASSERT( QtObservedAtomMap.find(atomid) == QtObservedAtomMap.end(),
"GLWorldScene::AtomInserted() - atom with id "+toString(_atom->getAtomIndex())
+" is already present in QtObservedAtomMap.");
QtObservedAtomMap[atomid] = _atom;
}
/** Removes an general atom.
*
* This is called when the atom has been removed from the molecule.
*
* @param _atom atom to remove
*/
void GLWorldScene::atomRemoved(ObservedValue_Index_t _atomid)
{
const QtObservedAtomMap_t::iterator eraseiter = QtObservedAtomMap.find(_atomid);
ASSERT( eraseiter != QtObservedAtomMap.end(),
"GLWorldScene::AtomRemoved() - atom with id "+toString(_atomid)
+" is not present in QtObservedAtomMap.");
QtObservedAtomMap.erase(eraseiter);
}
/** Inserts an atom into the scene when molecule is present.
*
* @param _atom atom to insert
*/
void GLWorldScene::moleculesAtomInserted(QtObservedAtom::ptr _atom, QtObservedMolecule * _mol)
{
const ObservedValue_Index_t atomid = _atom->getIndex();
// this ASSERT cannot work: The same molecule may get reassigned to a different
// molecule, when e.g. the time step changes (which triggers an update-molecules).
// The GUI is slow and may lack behind and thus get to execute the event
// moleculeAtomInserted when the change has been already been done.
// ASSERT( (atommol == NULL) || (_mol == atommol),
// "GLWorldScene::moleculesAtomInserted() - atom "+toString(atomid)
// +" claims to belong to QtObservedMolecule "+toString(atommol)
// +" but signal came from QtObservedMolecule "+toString(_mol)+".");
LOG(3, "INFO: GLWorldScene: Received signal atomInserted for atom " << _atom->getAtomIndex());
const ObservedValue_Index_t molid = _mol->getIndex();
// check of molecule is already present
boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
const MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(molid);
if (moliter != MoleculesinSceneMap.end()) {
const RemovedMoleculesMap_t::iterator emptyiter = EmptyMolecules.find(_mol);
if (emptyiter != EmptyMolecules.end())
EmptyMolecules.erase(emptyiter);
// check that it is the right molecule
QtObservedMolecule::ptr &checkmol = moliter->second->ObservedMolecule;
if (checkmol.get() == _mol) {
LOG(3, "INFO: GLWorldScene: Sending signal moleculesAtomInserted for atom "
<< _atom->getAtomIndex());
QMetaObject::invokeMethod(moliter->second, // pointer to a QObject
"atomInserted", // member name (no parameters here)
Qt::QueuedConnection, // connection type
Q_ARG(QtObservedAtom::ptr, _atom)); // parameters
} else {
// relay atomRemoved to GLMoleculeObject_molecule in RemovedMolecules
// LOG(3, "INFO: GLWorldScene: Sending signal moleculesAtomInserted for atom "+toString(_atomid)
// +" to molecule in RemovedMolecules.");
// const RemovedMoleculesMap_t::iterator removedmoliter = RemovedMolecules.find(molid);
// ASSERT( removedmoliter != RemovedMolecules.end(),
// "GLWorldScene::moleculesAtomInserted() - signal from old mol "
// +toString(molid)+", but not present in RemovedMolecules");
// QMetaObject::invokeMethod(removedmoliter->second, // pointer to a QObject
// "atomInserted ", // member name (no parameters here)
// Qt::QueuedConnection, // connection type
// Q_ARG(QtObservedAtom::ptr, _atom)); // parameters
ASSERT( 0,
"GLWorldScene::moleculesAtomInserted() - would need to send atomInserted to already removed molecule.");
}
} else {
const RemovedMoleculesMap_t::iterator removedmoliter = RemovedMolecules.find(_mol);
if (removedmoliter != RemovedMolecules.end()) {
ASSERT( 0,
"GLWorldScene::moleculesAtomInserted() - would need to send atomInserted to already removed molecule.");
} else {
boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
// only record missed state for molecule if (still) present but not instantiated
if (QtObservedMoleculeMap.count(molid)) {
// store signal for when it is instantiated
if (MoleculeMissedStateMap.count(molid) == 0)
MoleculeMissedStateMap.insert( std::make_pair(molid ,StateChangeMap_t()) );
MoleculeMissedStateMap[molid].insert( std::make_pair(atomid, atomInsertedState) );
ASSERT( QtObservedAtomMap[atomid] == _atom,
"GLWorldScene::moleculesAtomInserted() - atom "+toString(atomid)
+" inserted in molecule "+toString(_mol->getMolIndex())
+" which does not match atom in QtObservedAtomMap.");
LOG(3, "INFO: GLWorldScene: Placing atomInserted for atom " << _atom->getAtomIndex()
<< " and molecule " << _mol->getMolIndex() << " into missed state map.");
}
}
}
}
/** Removes an atom into the scene before molecule is present.
*
* @param _atomid atom to remove
*/
void GLWorldScene::moleculesAtomRemoved(ObservedValue_Index_t _atomid, QtObservedMolecule * _mol)
{
LOG(3, "INFO: GLWorldScene: Received signal atomRemoved for atom "+toString(_atomid)+".");
const ObservedValue_Index_t molid = _mol->getIndex();
// check of molecule is already present
boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
const MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(molid);
if (moliter != MoleculesinSceneMap.end()) {
const QtObservedMolecule::ptr &checkmol = moliter->second->ObservedMolecule;
if (checkmol.get() == _mol) {
LOG(3, "INFO: GLWorldScene: Sending signal moleculesAtomRemoved for atom "+toString(_atomid)+".");
QMetaObject::invokeMethod(moliter->second, // pointer to a QObject
"atomRemoved", // member name (no parameters here)
Qt::QueuedConnection, // connection type
Q_ARG(ObservedValue_Index_t, _atomid)); // parameters
} else {
// relay atomRemoved to GLMoleculeObject_molecule in RemovedMolecules
LOG(3, "INFO: GLWorldScene: Sending signal moleculesAtomRemoved for atom "+toString(_atomid)
+" to molecule in RemovedMolecules.");
const RemovedMoleculesMap_t::iterator removedmoliter = RemovedMolecules.find(_mol);
ASSERT( removedmoliter != RemovedMolecules.end(),
"GLWorldScene::moleculesAtomRemoved() - signal from old molecule "
+toString(molid)+", but not present in RemovedMolecules");
#ifndef NDEBUG
const QtObservedMolecule::ptr &othercheckmol = removedmoliter->second->ObservedMolecule;
#endif
ASSERT( othercheckmol.get() == _mol,
"GLWorldScene::moleculesAtomRemoved() - signal from old molecule "
+toString(molid)+", but different one "+toString(othercheckmol)
+" present in RemovedMolecules.");
QMetaObject::invokeMethod(removedmoliter->second, // pointer to a QObject
"atomRemoved", // member name (no parameters here)
Qt::QueuedConnection, // connection type
Q_ARG(ObservedValue_Index_t, _atomid)); // parameters
}
} else {
const RemovedMoleculesMap_t::iterator removedmoliter = RemovedMolecules.find(_mol);
if (removedmoliter != RemovedMolecules.end()) {
ASSERT( removedmoliter != RemovedMolecules.end(),
"GLWorldScene::moleculesAtomRemoved() - signal from old molecule "
+toString(molid)+", but not present in RemovedMolecules");
#ifndef NDEBUG
const QtObservedMolecule::ptr &othercheckmol = removedmoliter->second->ObservedMolecule;
#endif
ASSERT( othercheckmol.get() == _mol,
"GLWorldScene::moleculesAtomRemoved() - signal from old molecule "
+toString(molid)+", but different one "+toString(othercheckmol)
+" present in RemovedMolecules.");
QMetaObject::invokeMethod(removedmoliter->second, // pointer to a QObject
"atomRemoved", // member name (no parameters here)
Qt::QueuedConnection, // connection type
Q_ARG(ObservedValue_Index_t, _atomid)); // parameters
} else {
boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
// only record missed state for molecule if (still) present but not instantiated
if (QtObservedMoleculeMap.count(molid)) {
// store signal for when it is instantiated
if (MoleculeMissedStateMap.count(molid) == 0)
MoleculeMissedStateMap.insert( std::make_pair(molid, StateChangeMap_t()) );
MoleculeMissedStateMap[molid].insert( std::make_pair(_atomid, atomRemovedState) );
LOG(3, "INFO: GLWorldScene: Placing atomRemoved for atom " << _atomid
<< " and molecule " << molid << " into missed state map.");
}
}
}
}
void GLWorldScene::moleculeSignOn(QtObservedMolecule::ptr _mol)
{
// sign on to QtObservedMolecule to get atomInserted/..Removed signals from same
// source as GLMoleculeObject_molecule would
connect(_mol.get(), SIGNAL(atomInserted(QtObservedAtom::ptr, QtObservedMolecule *)),
this, SLOT(moleculesAtomInserted(QtObservedAtom::ptr, QtObservedMolecule *)) );
connect(_mol.get(), SIGNAL(atomRemoved(ObservedValue_Index_t, QtObservedMolecule *)),
this, SLOT(moleculesAtomRemoved(ObservedValue_Index_t, QtObservedMolecule *)) );
const ObservedValue_Index_t molid = _mol->getIndex();
ASSERT( QtObservedMoleculeMap.find(molid) == QtObservedMoleculeMap.end(),
"GLWorldScene::moleculeSignOn() - molecule with id "+toString(_mol->getMolIndex())
+" is already present in QtObservedMoleculeMap.");
QtObservedMoleculeMap[molid] = _mol;
LOG(3, "INFO: GLWorldScene: Received signal moleculeSignOn for molecule " << _mol->getMolIndex());
emit insertMolecule(_mol);
}
void GLWorldScene::moleculeSignOff(ObservedValue_Index_t _id)
{
const QtObservedMoleculeMap_t::iterator eraseiter = QtObservedMoleculeMap.find(_id);
ASSERT( eraseiter != QtObservedMoleculeMap.end(),
"GLWorldScene::moleculeSignOff() - cannot find id "+toString(_id)+" in map.");
QtObservedMolecule * mol = eraseiter->second.get();
QtObservedMoleculeMap.erase(eraseiter);
LOG(3, "INFO: GLWorldScene: Received signal moleculeSignOff for molecule " << mol->getMolIndex());
emit removeMolecule(mol);
}
/** Inserts a molecule into the scene.
*
* @param _mol molecule to insert
*/
void GLWorldScene::moleculeInserted(QtObservedMolecule::ptr _mol)
{
ASSERT (_mol,
"GLWorldScene::moleculeInserted() - received shared_ptr for molecule is empty?");
const ObservedValue_Index_t molid = _mol->getIndex();
LOG(3, "INFO: GLWorldScene: Received signal moleculeInserted for molecule "
<< _mol->getMolIndex());
boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
MoleculeNodeMap::const_iterator iter = MoleculesinSceneMap.find(molid);
ASSERT( iter == MoleculesinSceneMap.end(),
"GLWorldScene::moleculeInserted() - molecule's id "+toString(_mol->getMolIndex())
+" already present.");
// add new object
LOG(1, "DEBUG: Adding GLMoleculeObject_molecule to id " << _mol->getMolIndex());
GLMoleculeObject_molecule *molObject =
new GLMoleculeObject_molecule(
GLMoleculeObject::meshEmpty,
this,
*board,
_mol);
ASSERT( molObject != NULL,
"GLWorldScene::moleculeInserted - could not create molecule object for "
+toString(_mol->getMolIndex()));
#ifndef NDEBUG
std::pair inserter =
#endif
MoleculesinSceneMap.insert( make_pair(molid, molObject) );
ASSERT(inserter.second,
"GLWorldScene::moleculeInserted() - molecule "+toString(_mol->getMolIndex())
+" already present in scene.");
// now handle all state changes that came up before the instantiation
if (MoleculeMissedStateMap.count(molid) != 0) {
// ASSERT( !MoleculeMissedStateMap[molid].empty(),
// "GLWorldScene::moleculeInserted() - we have an empty state change map for molecule with id "
// +toString(molid));
boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
for (StateChangeMap_t::iterator iter = MoleculeMissedStateMap[molid].begin();
!MoleculeMissedStateMap[molid].empty();
iter = MoleculeMissedStateMap[molid].begin()) {
std::pair rangeiter =
MoleculeMissedStateMap[molid].equal_range(iter->first);
const size_t StateCounts = std::distance(rangeiter.first, rangeiter.second);
if (StateCounts > 1) {
// more than one state change, have to combine
typedef std::map StateChangeAmounts_t;
StateChangeAmounts_t StateChangeAmounts;
for (StateChangeMap_t::const_iterator stateiter = rangeiter.first;
stateiter != rangeiter.second; ++stateiter)
++StateChangeAmounts[stateiter->second];
ASSERT( StateChangeAmounts[atomInsertedState] >= StateChangeAmounts[atomRemovedState],
"GLWorldScene::moleculeInserted() - more atomRemoved states "
+toString(StateChangeAmounts[atomRemovedState])+" than atomInserted "
+toString(StateChangeAmounts[atomInsertedState])+" for atom "+toString(iter->first));
if (StateChangeAmounts[atomInsertedState] > StateChangeAmounts[atomRemovedState]) {
LOG(1, "INFO: invoking atomInserted for atom " << iter->first);
QMetaObject::invokeMethod(molObject, // pointer to a QObject
"atomInserted", // member name (no parameters here)
Qt::QueuedConnection, // connection type
Q_ARG(QtObservedAtom::ptr, QtObservedAtomMap[iter->first])); // parameters
} else {
LOG(1, "INFO: Atom " << iter->first << " has been inserted and removed already.");
}
// removed all state changes for this atom
MoleculeMissedStateMap[molid].erase(rangeiter.first, rangeiter.second);
} else {
// can only be an insertion
switch (rangeiter.first->second) {
case atomRemovedState:
ASSERT( 0,
"GLWorldScene::moleculeInserted() - atomRemoved state without atomInserted for atom "
+toString(iter->first));
break;
case atomInsertedState:
{
LOG(1, "INFO: invoking atomInserted for atom " << iter->first);
QMetaObject::invokeMethod(molObject, // pointer to a QObject
"atomInserted", // member name (no parameters here)
Qt::QueuedConnection, // connection type
Q_ARG(QtObservedAtom::ptr, QtObservedAtomMap[iter->first])); // parameters
break;
}
default:
ASSERT( 0,
"GLWorldScene::moleculeInserted() - there are unknown change states.");
break;
}
// removed state changes for this atom
MoleculeMissedStateMap[molid].erase(iter);
}
}
}
connect (molObject, SIGNAL(changed()), this, SIGNAL(changed()));
connect (molObject, SIGNAL(changeOccured()), this, SIGNAL(changeOccured()));
connect (molObject, SIGNAL(atomClicked(atomId_t)), this, SLOT(atomClicked(atomId_t)));
connect (molObject, SIGNAL(moleculeClicked(moleculeId_t)), this, SLOT(moleculeClicked(moleculeId_t)));
connect (molObject, SIGNAL(moleculeEmptied(QtObservedMolecule::ptr)), this, SLOT(moleculeEmpty(QtObservedMolecule::ptr)));
connect (molObject, SIGNAL(selectionChanged()), this, SIGNAL(changed()));
connect (molObject, SIGNAL(selectionChanged()), this, SIGNAL(changed()));
connect (molObject, SIGNAL(hoverChanged(const atomId_t)), this, SIGNAL(hoverChanged(const atomId_t)));
connect (molObject, SIGNAL(hoverChanged(const moleculeId_t, int)), this, SIGNAL(hoverChanged(const moleculeId_t, int)));
connect (molObject, SIGNAL(hoverChanged(const moleculeId_t, int)), this, SIGNAL(hoverChanged(const moleculeId_t, int)));
emit changed();
emit changeOccured();
// remove state change map for the molecule
{
boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
MoleculeMissedStateMap.erase(molid);
}
}
/** Removes a molecule from the scene.
*
* @param _mol QtObservedMolecule instance of molecule to remove
*/
void GLWorldScene::moleculeRemoved(QtObservedMolecule* _mol)
{
const ObservedValue_Index_t molid = _mol->getIndex();
LOG(3, "INFO: GLWorldScene: Received signal moleculeRemoved for molecule "+toString(molid)+".");
boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(molid);
ASSERT ( iter != MoleculesinSceneMap.end(),
"GLWorldScene::moleculeRemoved() - to be removed molecule "+toString(_mol->getMolIndex())
+" is already gone.");
// check if it's already empty
const RemovedMoleculesMap_t::iterator emptyiter = EmptyMolecules.find(_mol);
if (emptyiter != EmptyMolecules.end()) {
LOG(1, "DEBUG: Removing empty GLMoleculeObject_molecule to id " << _mol->getMolIndex()
<< " from scene.");
// it's already empty, remove it
ASSERT( emptyiter->second == iter->second,
"GLWorldScene::moleculeRemoved() - empty molecule "
+toString(emptyiter->second)+" and removed molecule "
+toString(iter->second)+" don't match.");
LOG(1, "DEBUG: Deleting already empty GLMoleculeObject_molecule to id " << _mol->getMolIndex());
GLMoleculeObject_molecule *molObject = emptyiter->second;
EmptyMolecules.erase(emptyiter);
molObject->disconnect();
delete molObject;
emit changed();
emit changeOccured();
} else {
// otherwise note it as removal candidate
RemovedMolecules.insert( std::make_pair(_mol, iter->second) );
}
MoleculesinSceneMap.erase(iter);
// remove any possible state changes left
{
boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
MoleculeMissedStateMap.erase(molid);
}
}
void GLWorldScene::moleculeEmpty(QtObservedMolecule::ptr _mol)
{
LOG(3, "INFO: GLWorldScene: Received signal moleculeEmpty for molecule "
+toString(_mol->getMolIndex())+".");
boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
const ObservedValue_Index_t molid = _mol->getIndex();
MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(molid);
if ( iter == MoleculesinSceneMap.end()) {
RemovedMoleculesMap_t::iterator removeiter = RemovedMolecules.find(_mol.get());
ASSERT ( removeiter != RemovedMolecules.end(),
"GLWorldScene::moleculeEmpty() - to be removed molecule "+toString(_mol->getMolIndex())
+" is neither in MoleculesinSceneMap, nor in RemovedMolecules.");
// it's noted for removal already, remove it
LOG(1, "DEBUG: Deleting empty GLMoleculeObject_molecule to id " << _mol->getMolIndex());
GLMoleculeObject_molecule *molObject = removeiter->second;
RemovedMolecules.erase(removeiter);
molObject->disconnect();
delete molObject;
emit changed();
emit changeOccured();
} else {
// otherwise just note it as empty
EmptyMolecules.insert( std::make_pair(_mol.get(), iter->second) );
}
// // remove any possible state changes left
// {
// boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
// MoleculeMissedStateMap.erase(molid);
// }
}
void GLWorldScene::moleculesVisibilityChanged(ObservedValue_Index_t _id, bool _visible)
{
boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_id);
ASSERT( iter != MoleculesinSceneMap.end(),
"GLWorldScene::moleculeInserted() - molecule's id "
+toString(board->getMoleculeIdToIndex(_id))+" is unknown.");
GLMoleculeObject_molecule *molObject = iter->second;
molObject->setVisible(_visible);
emit changed();
emit changeOccured();
}
/** Adds a shape to the scene.
*
*/
void GLWorldScene::addShape(const std::string &_name)
{
Shape * const shape = ShapeRegistry::getInstance().getByName(_name);
if (shape != NULL) {
GLMoleculeObject_shape *shapeObject = new GLMoleculeObject_shape(*shape, this);
ShapeNodeMap::iterator iter = ShapesinSceneMap.find(_name);
ASSERT(iter == ShapesinSceneMap.end(),
"GLWorldScene::addShape() - same shape "+_name+" added again.");
ShapesinSceneMap.insert( make_pair(_name, shapeObject) );
} else
ELOG(2, "GLWorldScene::addShape() - shape disappeared before we could draw it.");
emit changed();
}
void GLWorldScene::removeShape(const std::string &_name)
{
ShapeNodeMap::iterator iter = ShapesinSceneMap.find(_name);
ASSERT(iter != ShapesinSceneMap.end(),
"GLWorldScene::removeShape() - shape "+_name+" not in scene.");
ShapesinSceneMap.erase(iter);
delete(iter->second);
emit changed();
}
void GLWorldScene::updateSelectedShapes()
{
foreach (QObject *obj, children()) {
GLMoleculeObject_shape *shapeobj = qobject_cast(obj);
if (shapeobj){
shapeobj->enable(ShapeRegistry::getInstance().isSelected(shapeobj->getShape()));
}
}
emit changed();
}
void GLWorldScene::initialize(QGLView *view, QGLPainter *painter) const
{
// Initialize all of the mesh objects that we have as children.
foreach (QObject *obj, children()) {
GLMoleculeObject *meshobj = qobject_cast(obj);
if (meshobj)
meshobj->initialize(view, painter);
}
}
void GLWorldScene::draw(QGLPainter *painter, const QVector4D &cameraPlane) const
{
// Draw all of the mesh objects that we have as children.
foreach (QObject *obj, children()) {
GLMoleculeObject *meshobj = qobject_cast(obj);
if (meshobj)
meshobj->draw(painter, cameraPlane);
}
}
void GLWorldScene::setSelectionMode(SelectionModeType mode)
{
selectionMode = mode;
// TODO send update to toolbar
}
void GLWorldScene::setSelectionModeAtom()
{
setSelectionMode(SelectAtom);
}
void GLWorldScene::setSelectionModeMolecule()
{
setSelectionMode(SelectMolecule);
}