Panda3D
Loading...
Searching...
No Matches
factoryBase.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file factoryBase.cxx
10 * @author drose
11 * @date 2000-05-08
12 */
13
14#include "factoryBase.h"
15#include "indent.h"
16#include "config_putil.h"
17
18/**
19 * Attempts to create a new instance of some class of the indicated type, or
20 * some derivative if necessary. If an instance of the exact type cannot be
21 * created, the specified preferred will specify which derived class will be
22 * preferred.
23 */
25make_instance(TypeHandle handle, const FactoryParams &params) {
26 TypedObject *instance = nullptr;
27
28 instance = make_instance_exact(handle, params);
29 if (instance == nullptr) {
30 // Can't create an exact instance; try for a derived type.
31 instance = make_instance_more_specific(handle, params);
32 }
33
34 if (util_cat.is_debug()) {
35 util_cat.debug()
36 << "make_instance(" << handle << ", params) returns "
37 << (void *)instance;
38 if (instance != nullptr) {
39 util_cat.debug(false)
40 << ", of type " << instance->get_type();
41 }
42 util_cat.debug(false) << "\n";
43 }
44 return instance;
45}
46
47/**
48 * Attempts to create an instance of the type requested, or some base type of
49 * the type requested. Returns the new instance created, or NULL if the
50 * instance could not be created.
51 */
54 TypedObject *object = make_instance_exact(handle, params);
55
56 if (object == nullptr) {
57 // Recursively search through the entire inheritance tree until we find
58 // something we know about.
59 if (handle.get_num_parent_classes() == 0) {
60 return nullptr;
61 }
62
63 int num_parents = handle.get_num_parent_classes();
64 for (int i = 0; i < num_parents && object == nullptr; i++) {
65 object = make_instance_more_general(handle.get_parent_class(i), params);
66 }
67 }
68
69 if (util_cat.is_debug()) {
70 util_cat.debug()
71 << "make_instance(" << handle << ", params) returns "
72 << (void *)object;
73 if (object != nullptr) {
74 util_cat.debug(false)
75 << ", of type " << object->get_type();
76 }
77 util_cat.debug(false) << "\n";
78 }
79
80 return object;
81}
82
83/**
84 * Returns the TypeHandle given, if it is a registered type, or if it is not
85 * registered, searches for the nearest ancestor of the indicated type that is
86 * registered and returns it. If no ancestor of the indicated type is
87 * registered, returns TypeHandle::none().
88 */
91 Creators::const_iterator ci = _creators.find(handle);
92 if (ci != _creators.end()) {
93 // This type is registered.
94 return handle;
95 }
96
97 // Recursively search through the entire inheritance tree until we find
98 // something we know about.
99 if (handle.get_num_parent_classes() == 0) {
100 return TypeHandle::none();
101 }
102
103 int num_parents = handle.get_num_parent_classes();
104 for (int i = 0; i < num_parents; i++) {
106 if (result != TypeHandle::none()) {
107 return result;
108 }
109 }
110
111 // No known types.
112 return TypeHandle::none();
113}
114
115/**
116 * Registers a new kind of thing the Factory will be able to create.
117 *
118 * @param user_data an optional pointer to be passed along to the function.
119 */
121register_factory(TypeHandle handle, BaseCreateFunc *func, void *user_data) {
122 nassertv(handle != TypeHandle::none());
123 nassertv(func != nullptr);
124
125 Creator creator;
126 creator._func = func;
127 creator._user_data = user_data;
128 _creators[handle] = creator;
129}
130
131/**
132 * Returns the number of different types the Factory knows how to create.
133 */
135get_num_types() const {
136 return _creators.size();
137}
138
139/**
140 * Returns the nth type the Factory knows how to create. This is not a
141 * terribly efficient function; it's included primarily for debugging output.
142 * Normally you wouldn't need to traverse the list of the Factory's types.
143 */
145get_type(size_t n) const {
146 nassertr(n < get_num_types(), TypeHandle::none());
147 Creators::const_iterator ci;
148 for (ci = _creators.begin(); ci != _creators.end(); ++ci) {
149 if (n == 0) {
150 return (*ci).first;
151 }
152 n--;
153 }
154
155 // We shouldn't get here.
156 nassertr(false, TypeHandle::none());
157 return TypeHandle::none();
158}
159
160/**
161 * Empties the list of preferred types.
162 */
165 _preferred.clear();
166}
167
168/**
169 * Adds the indicated type to the end of the list of preferred types. On the
170 * next call to make_instance(), if the exact type requested cannot be
171 * created, the preferred types are first tried in the order specified.
172 */
175 nassertv(handle != TypeHandle::none());
176 _preferred.push_back(handle);
177}
178
179/**
180 * Returns the number of types added to the preferred-type list.
181 */
183get_num_preferred() const {
184 return _preferred.size();
185}
186
187/**
188 * Returns the nth type added to the preferred-type list.
189 */
191get_preferred(size_t n) const {
192 nassertr(n < get_num_preferred(), TypeHandle::none());
193 return _preferred[n];
194}
195
196/**
197 * Writes a list of all known types the Factory can create to the indicated
198 * output stream, one per line.
199 */
201write_types(std::ostream &out, int indent_level) const {
202 Creators::const_iterator ci;
203 for (ci = _creators.begin(); ci != _creators.end(); ++ci) {
204 indent(out, indent_level) << (*ci).first << "\n";
205 }
206}
207
208/**
209 * Attempts to create an instance of the exact type requested by the given
210 * handle. Returns the new instance created, or NULL if the instance could
211 * not be created.
212 */
213TypedObject *FactoryBase::
214make_instance_exact(TypeHandle handle, FactoryParams params) {
215 Creators::const_iterator ci = _creators.find(handle);
216 if (ci == _creators.end()) {
217 return nullptr;
218 }
219
220 Creator creator = (*ci).second;
221 nassertr(creator._func != nullptr, nullptr);
222 params._user_data = creator._user_data;
223 return (*creator._func)(params);
224}
225
226/**
227 * Attempts to create an instance of some derived type of the type requested
228 * by the given handle. Returns the new instance created, or NULL if the
229 * instance could not be created.
230 */
231TypedObject *FactoryBase::
232make_instance_more_specific(TypeHandle handle, FactoryParams params) {
233 // First, walk through the established preferred list. Maybe one of these
234 // qualifies.
235
236 for (TypeHandle ptype : _preferred) {
237 if (ptype.is_derived_from(handle)) {
238 TypedObject *object = make_instance_exact(ptype, params);
239 if (object != nullptr) {
240 return object;
241 }
242 }
243 }
244
245 // No, we couldn't create anything on the preferred list, so create the
246 // first thing we know about that derives from the indicated type.
247 Creators::const_iterator ci;
248 for (ci = _creators.begin(); ci != _creators.end(); ++ci) {
249 TypeHandle ctype = (*ci).first;
250 if (ctype.is_derived_from(handle)) {
251 Creator creator = (*ci).second;
252 nassertr(creator._func != nullptr, nullptr);
253 params._user_data = creator._user_data;
254 TypedObject *object = (*creator._func)(params);
255 if (object != nullptr) {
256 return object;
257 }
258 }
259 }
260
261 return nullptr;
262}
void register_factory(TypeHandle handle, BaseCreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
TypeHandle find_registered_type(TypeHandle handle)
Returns the TypeHandle given, if it is a registered type, or if it is not registered,...
void write_types(std::ostream &out, int indent_level=0) const
Writes a list of all known types the Factory can create to the indicated output stream,...
TypeHandle get_type(size_t n) const
Returns the nth type the Factory knows how to create.
TypedObject * make_instance(TypeHandle handle, const FactoryParams &params)
Attempts to create a new instance of some class of the indicated type, or some derivative if necessar...
size_t get_num_preferred() const
Returns the number of types added to the preferred-type list.
void add_preferred(TypeHandle handle)
Adds the indicated type to the end of the list of preferred types.
TypeHandle get_preferred(size_t n) const
Returns the nth type added to the preferred-type list.
void clear_preferred()
Empties the list of preferred types.
TypedObject * make_instance_more_general(TypeHandle handle, const FactoryParams &params)
Attempts to create an instance of the type requested, or some base type of the type requested.
size_t get_num_types() const
Returns the number of different types the Factory knows how to create.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
get_parent_class
Returns the nth parent class of this type.
Definition typeHandle.h:137
bool is_derived_from(TypeHandle parent, TypedObject *object=nullptr) const
Returns true if this type is derived from the indicated type, false otherwise.
Definition typeHandle.I:105
get_num_parent_classes
Returns the number of parent classes that this type is known to have.
Definition typeHandle.h:137
This is an abstract class that all classes which use TypeHandle, and also provide virtual functions t...
Definition typedObject.h:88
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.