summaryrefslogtreecommitdiff
path: root/cad/plugins/NanoVision-1/include/Nanorex/Interface/NXRenderingEngine.h
blob: f90cfc1849fb83315ba4f59cafea9f9824f065e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
// Copyright 2008 Nanorex, Inc.  See LICENSE file for details.

#ifndef NX_RENDERINGENGINE_H
#define NX_RENDERINGENGINE_H

#include <Nanorex/Utility/NXCommandResult.h>
#include <Nanorex/Interface/NXSceneGraph.h>
#include <Nanorex/Interface/NXMoleculeSet.h>
#include <Nanorex/Interface/NXNamedView.h>
#include <Nanorex/Interface/NXNanoVisionResultCodes.h>
#include <openbabel/mol.h>
#include <vector>
#include <map>
#include <string>
#include <iostream>
#include <cassert>

#include <QtPlugin>
#include <QtGui>

class QWidget;

namespace Nanorex {

class NXGraphicsManager;
class NXRendererPlugin;

/*
/// integer id for each subclass the completes an implementation
enum RenderingEngineID {
	OPENGL=0 // NXOpenGLRenderingEngine
};
*/


/* CLASS: NXRenderingEngine */
/**
 * Abstracts the rendering mechanism.
 * Graphics engines that actually render must inherit the Qt class
 * corresponding to the implementation method. For example, engines
 * that render using OpenGL must inherit this class as well as
 * QGLWidget. An implementation using Irrlicht's software rendering,
 * for example, must inherit QWidget instead because it bypasses
 * OpenGL.
 *
 * Forms designed using Qt Designer have placeholder widgets for
 * the rendering engines. At instantiation, they will be deleted and a dynamically
 * allocated rendering-engine instance will replace them. At that time, because
 * layout calculations are performed, the rendering-engine class must have the
 * characteristics of a QWidget. Because all rendering-engine instances will be
 * accessed through this interface, we must allow for this interface to appear
 * as a QWidget. Suppose we make QWidget a base class for this interface. Then
 * in cases like the OpenGL engine where QGLWidget must be inherited
 * instead of QWidget an additional subclassing of QGLWidget will only lead to
 * two QWidget subobjects instead of 1 in the derived class. The Qt meta-object
 * compiler then has difficulty handling two QObject subobjects of our derived
 * class. Therefore, derived classes must implement the pure virtual method
 * asQWidget() based on whichever subclass of QWidget they inherit, and must
 * perform the appropriate static_cast
 *
 * @ingroup NanorexInterface, PluginArchitecture, GraphicsArchitecture
 */
class NXRenderingEngine
{
public:
	
	NXRenderingEngine();
	virtual ~NXRenderingEngine();
	
	// --- pure virtual methods ---
	
	/// Derived classes must implement after inheriting an appropriate
	/// subclass of QWidget and after performing an appropriate type-cast
	virtual QWidget* asQWidget(void) = 0;
	
	// /// Derived classes must override to identify themselves
	// virtual RenderingEngineID getID(void) const = 0;
	
	/// Derived classes must override to initialize plugins and set
	/// pluginsInitialized to true if successful. A valid graphics-manager
	/// must be set with setGraphicsManager() before calling this.
	/// importRendererPluginsFromGraphicsManager() may be called to create
	/// new instances of the plugins for various render-styles but the
	/// developer may opt to bypass that perform custom plugin instance creation
	/// here.
	virtual bool initializePlugins() = 0;
	
	/// Derived classes must override to cleanup plugins
	virtual bool cleanupPlugins() = 0;
	
	/// Fully-implemented derived classes have enough information to create a
	/// functioning engine and must return an instance created using the 'new'
	/// operator
	virtual NXRenderingEngine* newInstance(QWidget *parent=0) const = 0;
	
	/// Derived classes must implement and return the result of the qobject_cast
	/// to a compatible plugin-type. If the cast fails then the result is a NULL
	/// pointer which must be checked as failure-condition.
	virtual NXRendererPlugin* renderer_cast(QObject *plugin) const = 0;
	
	// @TODO: consume the events in the following default implementations
	virtual void mousePressEvent(QMouseEvent *mouseEvent) { }
	virtual void mouseReleaseEvent(QMouseEvent *mouseEvent) { }
	virtual void mouseMoveEvent(QMouseEvent *mouseEvent) { }

	// --- regular methods ---
	
	void setGraphicsManager(NXGraphicsManager *const gm) {
		graphicsManager = gm;
	}
	NXGraphicsManager *const getGraphicsManager(void) {
		return graphicsManager;
	}
	
	void setRenderer(std::string const& renderStyleCode,
	                 NXRendererPlugin *const rendererPlugin)
	{
		renderStyleMap[renderStyleCode] = rendererPlugin;
	}
	
	/// Create new instances of plugins local to this context from those in the
	/// graphics-manager. Returns true if successful, false if at least one
	/// plugin instantiation failed.
// 	virtual bool importRendererPluginsFromGraphicsManager(void);
	
	/// Access chemical entity at index idx - returns NULL if not found
	/// which happens if index is out of bounds
	NXMoleculeSet *const getFrame(int idx);
	
	/// Append a molecule-set to the list of frames
	NXCommandResult const *const addFrame(NXMoleculeSet *const molSetPtr);
	
	/// Set the current frame for display - fails silently if out of bounds
	virtual void setCurrentFrame(int frameIdx);
	
	/// Number of frames capable of being displayed
	int getFrameCount(void) const { return frames.size(); }
	
	/// Clear all frame info
	void clearFrames(void) { deleteFrames(); moleculeSets.clear(); }
	
	/// Derived classes can implement to adjust view based on current frame's
	/// molecule-set
	virtual void resetView(void) { }
	
	virtual void setNamedView(NXNamedView const& view) { }
	// virtual NXNamedView const& getNamedView(void) const { }
	
	/// Result of the last command
	NXCommandResult const* getCommandResult(void) const
	{ return &commandResult; }
	
#ifdef NX_DEBUG
	void writeDotGraph(std::ostream& o);
#endif
	
protected:
	
	/// Track renderer-plugins initialized in local context and delete in
	/// destructor
	// std::vector<NXRendererPlugin*> rendererSet;
	
	/// Local map render-style to plugin
	typedef std::map<std::string, NXRendererPlugin*> RenderStyleMap;
	RenderStyleMap renderStyleMap;
	
	NXGraphicsManager *graphicsManager;
	
	// for structure- and trajectory-graphics
	std::vector<NXMoleculeSet*> moleculeSets;
	// for trajectory-graphics
	std::vector<NXSGNode*> frames;
	
	/// Current-frame indexer, initialized to -1
	int currentFrameIndex;
	bool pluginsInitialized;
	
	// NXNamedView namedView; /// @note does this have to be stored?
	
	/// Result of the last public method call
	NXCommandResult commandResult;
	
	/// Derived classes must override to create a scenegraph within local
	/// (graphics) context
	virtual NXSGNode* createSceneGraph(NXMoleculeSet *const molSetPtr) = 0;
	
	void deleteFrames(void);
	
	static void SetResult(NXCommandResult& cmdResult,
	                      int errCode, std::string const& errMsg);
	static void ClearResult(NXCommandResult& cmdResult);
	
	
	/// @todo remove following unused, commented from older drafts
	
#if 0
	/// Access molecule-set at index idx - returns NULL if not found which
	/// happens if index is out of bounds or the engine is rendering single
	/// molecules as indicated by the inSingleMoleculeMode property.
	NXMoleculeSet *const getMoleculeSet(int idx);

	/// Append a molecule-set to the list if !inSingleMoleculeMode
	NXCommandResult* addMoleculeSet(NXMoleculeSet *const molSetPtr);

	/// Access molecule at index idx - returns NULL if not found which
	/// happens if index is out of bounds or the engine is rendering single
	/// molecule-sets as indicated by the !inSingleMoleculeMode property.
	OpenBabel::OBMol *const getMolecule(int idx);

	/// Append a molecule to the list if inSingleMoleculeMode
		NXCommandResult* addMolecule(OpenBabel::OBMol *const molPtr);
#endif	
	
    // NXMoleculeSet *const getRootMoleculeSet(void) { return rootMoleculeSet; }
    // virtual bool setRootMoleculeSet(NXMoleculeSet *const moleculeSet)
    // { rootMoleculeSet = moleculeSet; return true; }
	
    // OpenBabel::OBMol*const getRootMolecule(void) { return rootMolecule; }
    // virtual bool setRootMolecule(OpenBabel::OBMol *const molecule)
    // { rootMolecule = molecule; return true; }
	
};


inline void NXRenderingEngine::deleteFrames(void) {
	std::vector<NXSGNode*>::iterator frameIter;
	for(frameIter=frames.begin(); frameIter!=frames.end(); ++frameIter) {
		NXSGNode *frameTopLevelNode = *frameIter;
		assert(frameTopLevelNode->getRefCount() == 0);
		delete frameTopLevelNode;
	}
	frames.clear();
}

#ifdef NX_DEBUG
inline void NXRenderingEngine::writeDotGraph(std::ostream& o)
{
	vector<NXSGNode*>::const_iterator frameIter;
	for(frameIter = frames.begin(); frameIter != frames.end(); ++frameIter)
		(*frameIter)->writeDotGraph(o);
}
#endif

} // Nanorex

Q_DECLARE_INTERFACE(Nanorex::NXRenderingEngine,
                    "com.Nanorex.Interface.NXRenderingEngine/0.1.0")

#endif // NX_RENDERINGENGINE_H