Panda3D
|
00001 // Filename: pandaSystem.cxx 00002 // Created by: drose (26Jan05) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "pandaSystem.h" 00016 #include "pandaVersion.h" 00017 #include "dtool_platform.h" 00018 00019 PandaSystem *PandaSystem::_global_ptr = NULL; 00020 TypeHandle PandaSystem::_type_handle; 00021 00022 //////////////////////////////////////////////////////////////////// 00023 // Function: PandaSystem::Constructor 00024 // Access: Protected 00025 // Description: Don't try to construct a PandaSystem object; there is 00026 // only one of these, and it constructs itself. Use 00027 // get_global_ptr() to get a pointer to the one 00028 // PandaSystem. 00029 //////////////////////////////////////////////////////////////////// 00030 PandaSystem:: 00031 PandaSystem() : 00032 _systems(get_class_type()) 00033 { 00034 _system_names_dirty = false; 00035 00036 // These are settable via Config.prc, but only in development 00037 // (!NDEBUG) mode, and only if they are not already defined. 00038 _package_version_string = PANDA_PACKAGE_VERSION_STR; 00039 _package_host_url = PANDA_PACKAGE_HOST_URL; 00040 } 00041 00042 //////////////////////////////////////////////////////////////////// 00043 // Function: PandaSystem::Destructor 00044 // Access: Protected 00045 // Description: Don't try to destruct the global PandaSystem object. 00046 //////////////////////////////////////////////////////////////////// 00047 PandaSystem:: 00048 ~PandaSystem() { 00049 } 00050 00051 //////////////////////////////////////////////////////////////////// 00052 // Function: PandaSystem::get_version_string 00053 // Access: Published, Static 00054 // Description: Returns the current version of Panda, expressed as a 00055 // string, e.g. "1.0.0". The string will end in the 00056 // letter "c" if this build does not represent an 00057 // official version. 00058 //////////////////////////////////////////////////////////////////// 00059 string PandaSystem:: 00060 get_version_string() { 00061 return PANDA_VERSION_STR; 00062 } 00063 00064 //////////////////////////////////////////////////////////////////// 00065 // Function: PandaSystem::get_package_version_string 00066 // Access: Published, Static 00067 // Description: Returns the version of the Panda3D distributable 00068 // package that provides this build of Panda. 00069 // 00070 // When the currently-executing version of Panda was 00071 // loaded from a distributable package, such as via the 00072 // browser plugin, then this string will be nonempty and 00073 // will contain the corresponding version string. You 00074 // can build applications that use this particular 00075 // version of Panda by requesting it in the pdef file, 00076 // using "panda3d", this version string, and the 00077 // download host provided by get_package_host_url(). 00078 // 00079 // If this string is empty, then the currently-executing 00080 // Panda was built independently, and is not part of a 00081 // distributable package. 00082 // 00083 // This string is set explicitly at compilation time. 00084 // Normally, it should be set to a nonempty string only 00085 // when building a Panda3D package for distribution. 00086 //////////////////////////////////////////////////////////////////// 00087 string PandaSystem:: 00088 get_package_version_string() { 00089 #ifdef NDEBUG 00090 return PANDA_PACKAGE_VERSION_STR; 00091 #else 00092 return get_global_ptr()->_package_version_string; 00093 #endif 00094 } 00095 00096 //////////////////////////////////////////////////////////////////// 00097 // Function: PandaSystem::get_package_host_url 00098 // Access: Published, Static 00099 // Description: Returns the URL of the download server that provides 00100 // the Panda3D distributable package currently running. 00101 // This can be used, along with the 00102 // get_package_version_string(), to uniquely identify 00103 // the running version of Panda among distributable 00104 // Panda versions. 00105 // 00106 // See get_package_version_string() for more information. 00107 // 00108 // This string is set explicitly at compilation time. 00109 // Normally, it should be set to a nonempty string only 00110 // when building a Panda3D package for distribution. 00111 //////////////////////////////////////////////////////////////////// 00112 string PandaSystem:: 00113 get_package_host_url() { 00114 #ifdef NDEBUG 00115 return PANDA_PACKAGE_HOST_URL; 00116 #else 00117 return get_global_ptr()->_package_host_url; 00118 #endif 00119 } 00120 00121 //////////////////////////////////////////////////////////////////// 00122 // Function: PandaSystem::get_p3d_coreapi_version_string 00123 // Access: Published, Static 00124 // Description: Returns the current version of Panda's Core API, 00125 // expressed as a string of dot-delimited integers. 00126 // There are usually four integers in this version, but 00127 // this is not guaranteed. 00128 // 00129 // The Core API is used during the runtime (plugin) 00130 // environment only. This may be the empty string if 00131 // the current version of Panda is not built to provide 00132 // a particular Core API, which will be the normal case 00133 // in a development SDK. However, you should not use 00134 // this method to determine whether you are running in a 00135 // runtime environment or not. 00136 //////////////////////////////////////////////////////////////////// 00137 string PandaSystem:: 00138 get_p3d_coreapi_version_string() { 00139 #ifndef P3D_COREAPI_VERSION_STR 00140 return ""; 00141 #else 00142 return P3D_COREAPI_VERSION_STR; 00143 #endif 00144 } 00145 00146 //////////////////////////////////////////////////////////////////// 00147 // Function: PandaSystem::get_major_version 00148 // Access: Published, Static 00149 // Description: Returns the major version number of the current 00150 // version of Panda. This is the first number of the 00151 // dotted triple returned by get_version_string(). It 00152 // changes very rarely. 00153 //////////////////////////////////////////////////////////////////// 00154 int PandaSystem:: 00155 get_major_version() { 00156 return PANDA_MAJOR_VERSION; 00157 } 00158 00159 //////////////////////////////////////////////////////////////////// 00160 // Function: PandaSystem::get_minor_version 00161 // Access: Published, Static 00162 // Description: Returns the minor version number of the current 00163 // version of Panda. This is the second number of the 00164 // dotted triple returned by get_version_string(). It 00165 // changes with each release that introduces new 00166 // features. 00167 //////////////////////////////////////////////////////////////////// 00168 int PandaSystem:: 00169 get_minor_version() { 00170 return PANDA_MINOR_VERSION; 00171 } 00172 00173 //////////////////////////////////////////////////////////////////// 00174 // Function: PandaSystem::get_sequence_version 00175 // Access: Published, Static 00176 // Description: Returns the sequence version number of the current 00177 // version of Panda. This is the third number of the 00178 // dotted triple returned by get_version_string(). It 00179 // changes with bugfix updates and very minor feature 00180 // updates. 00181 //////////////////////////////////////////////////////////////////// 00182 int PandaSystem:: 00183 get_sequence_version() { 00184 return PANDA_SEQUENCE_VERSION; 00185 } 00186 00187 //////////////////////////////////////////////////////////////////// 00188 // Function: PandaSystem::is_official_version 00189 // Access: Published, Static 00190 // Description: Returns true if current version of Panda claims to be 00191 // an "official" version, that is, one that was compiled 00192 // by an official distributor of Panda using a specific 00193 // version of the panda source tree. If this is true, 00194 // there will not be a "c" at the end of the version 00195 // string returned by get_version_string(). 00196 // 00197 // Note that we must take the distributor's word for it 00198 // here. 00199 //////////////////////////////////////////////////////////////////// 00200 bool PandaSystem:: 00201 is_official_version() { 00202 #ifdef PANDA_OFFICIAL_VERSION 00203 return true; 00204 #else 00205 return false; 00206 #endif 00207 } 00208 00209 //////////////////////////////////////////////////////////////////// 00210 // Function: PandaSystem::get_distributor 00211 // Access: Published, Static 00212 // Description: Returns the string defined by the distributor of this 00213 // version of Panda, or "homebuilt" if this version was 00214 // built directly from the sources by the end-user. 00215 // This is a completely arbitrary string. 00216 //////////////////////////////////////////////////////////////////// 00217 string PandaSystem:: 00218 get_distributor() { 00219 return PANDA_DISTRIBUTOR; 00220 } 00221 00222 //////////////////////////////////////////////////////////////////// 00223 // Function: PandaSystem::get_compiler 00224 // Access: Published, Static 00225 // Description: Returns a string representing the compiler that was 00226 // used to generate this version of Panda, if it is 00227 // available, or "unknown" if it is not. 00228 //////////////////////////////////////////////////////////////////// 00229 string PandaSystem:: 00230 get_compiler() { 00231 #if defined(_MSC_VER) 00232 // MSVC defines this macro. It's an integer; we need to format it. 00233 ostringstream strm; 00234 strm << "MSC v." << _MSC_VER; 00235 00236 // We also get this suite of macros that tells us what the build 00237 // platform is. 00238 #if defined(_M_IX86) 00239 #ifdef MS_WIN64 00240 strm << " 64 bit (Intel)"; 00241 #else // MS_WIN64 00242 strm << " 32 bit (Intel)"; 00243 #endif // MS_WIN64 00244 #elif defined(_M_IA64) 00245 strm << " 64 bit (Itanium)"; 00246 #elif defined(_M_AMD64) 00247 strm << " 64 bit (AMD64)"; 00248 #endif 00249 00250 return strm.str(); 00251 00252 #elif defined(__GNUC__) 00253 // GCC defines this simple macro. 00254 return "GCC " __VERSION__; 00255 00256 #else 00257 // For other compilers, you're on your own. 00258 return "unknown"; 00259 #endif 00260 } 00261 00262 //////////////////////////////////////////////////////////////////// 00263 // Function: PandaSystem::get_build_date 00264 // Access: Published, Static 00265 // Description: Returns a string representing the date and time at 00266 // which this version of Panda (or at least dtool) was 00267 // compiled, if available. 00268 //////////////////////////////////////////////////////////////////// 00269 string PandaSystem:: 00270 get_build_date() { 00271 return __DATE__ " " __TIME__; 00272 } 00273 00274 //////////////////////////////////////////////////////////////////// 00275 // Function: PandaSystem::get_platform 00276 // Access: Published, Static 00277 // Description: Returns a string representing the runtime platform 00278 // that we are currently running on. This will be 00279 // something like "win32" or "osx.i386" or 00280 // "linux.amd64". 00281 //////////////////////////////////////////////////////////////////// 00282 string PandaSystem:: 00283 get_platform() { 00284 return DTOOL_PLATFORM; 00285 } 00286 00287 //////////////////////////////////////////////////////////////////// 00288 // Function: PandaSystem::has_system 00289 // Access: Published 00290 // Description: Returns true if the current version of Panda claims 00291 // to have the indicated subsystem installed, false 00292 // otherwise. The set of available subsystems is 00293 // implementation defined. 00294 //////////////////////////////////////////////////////////////////// 00295 bool PandaSystem:: 00296 has_system(const string &system) const { 00297 Systems::const_iterator si; 00298 si = _systems.find(system); 00299 return (si != _systems.end()); 00300 } 00301 00302 //////////////////////////////////////////////////////////////////// 00303 // Function: PandaSystem::get_num_systems 00304 // Access: Published 00305 // Description: Returns the number of Panda subsystems that have 00306 // registered themselves. This can be used with 00307 // get_system() to iterate through the entire list of 00308 // available Panda subsystems. 00309 //////////////////////////////////////////////////////////////////// 00310 int PandaSystem:: 00311 get_num_systems() const { 00312 return _systems.size(); 00313 } 00314 00315 //////////////////////////////////////////////////////////////////// 00316 // Function: PandaSystem::get_system 00317 // Access: Published 00318 // Description: Returns the nth Panda subsystem that has registered 00319 // itself. This list will be sorted in alphabetical 00320 // order. 00321 //////////////////////////////////////////////////////////////////// 00322 string PandaSystem:: 00323 get_system(int n) const { 00324 if (n < 0 || n >= (int)_systems.size()) { 00325 return string(); 00326 } 00327 00328 if (_system_names_dirty) { 00329 ((PandaSystem *)this)->reset_system_names(); 00330 } 00331 00332 return _system_names[n]; 00333 } 00334 00335 //////////////////////////////////////////////////////////////////// 00336 // Function: PandaSystem::get_system_tag 00337 // Access: Published 00338 // Description: Returns the value associated with the indicated tag 00339 // for the given system. This provides a standard way 00340 // to query each subsystem's advertised capabilities. 00341 // The set of tags and values are per-system and 00342 // implementation-defined. 00343 // 00344 // The return value is the empty string if the indicated 00345 // system is undefined or if does not define the 00346 // indicated tag. 00347 //////////////////////////////////////////////////////////////////// 00348 string PandaSystem:: 00349 get_system_tag(const string &system, const string &tag) const { 00350 Systems::const_iterator si; 00351 si = _systems.find(system); 00352 if (si != _systems.end()) { 00353 const SystemTags &tags = (*si).second; 00354 SystemTags::const_iterator ti; 00355 ti = tags.find(tag); 00356 if (ti != tags.end()) { 00357 return (*ti).second; 00358 } 00359 } 00360 00361 return string(); 00362 } 00363 00364 //////////////////////////////////////////////////////////////////// 00365 // Function: PandaSystem::add_system 00366 // Access: Published 00367 // Description: Intended for use by each subsystem to register itself 00368 // at startup. 00369 //////////////////////////////////////////////////////////////////// 00370 void PandaSystem:: 00371 add_system(const string &system) { 00372 bool inserted = _systems.insert(Systems::value_type(system, SystemTags(get_class_type()))).second; 00373 if (inserted) { 00374 _system_names_dirty = true; 00375 } 00376 } 00377 00378 //////////////////////////////////////////////////////////////////// 00379 // Function: PandaSystem::set_system_tag 00380 // Access: Published 00381 // Description: Intended for use by each subsystem to register its 00382 // set of capabilities at startup. 00383 //////////////////////////////////////////////////////////////////// 00384 void PandaSystem:: 00385 set_system_tag(const string &system, const string &tag, 00386 const string &value) { 00387 pair<Systems::iterator, bool> result; 00388 result = _systems.insert(Systems::value_type(system, SystemTags(get_class_type()))); 00389 if (result.second) { 00390 _system_names_dirty = true; 00391 } 00392 00393 SystemTags &tags = (*result.first).second; 00394 tags[tag] = value; 00395 } 00396 00397 //////////////////////////////////////////////////////////////////// 00398 // Function: PandaSystem::heap_trim 00399 // Access: Published 00400 // Description: Attempts to release memory back to the system, if 00401 // possible. The pad argument is the minimum amount of 00402 // unused memory to keep in the heap (against future 00403 // allocations). Any memory above that may be released 00404 // to the system, reducing the memory size of this 00405 // process. There is no guarantee that any memory may 00406 // be released. 00407 // 00408 // Returns true if any memory was actually released, 00409 // false otherwise. 00410 //////////////////////////////////////////////////////////////////// 00411 bool PandaSystem:: 00412 heap_trim(size_t pad) { 00413 // This actually just vectors into _memory_hook, which isn't 00414 // published. This method only exists on PandaSystem for the 00415 // convenience of Python programmers. 00416 return memory_hook->heap_trim(pad); 00417 } 00418 00419 //////////////////////////////////////////////////////////////////// 00420 // Function: PandaSystem::output 00421 // Access: Published 00422 // Description: 00423 //////////////////////////////////////////////////////////////////// 00424 void PandaSystem:: 00425 output(ostream &out) const { 00426 out << "Panda version " << get_version_string(); 00427 } 00428 00429 //////////////////////////////////////////////////////////////////// 00430 // Function: PandaSystem::write 00431 // Access: Published 00432 // Description: 00433 //////////////////////////////////////////////////////////////////// 00434 void PandaSystem:: 00435 write(ostream &out) const { 00436 out << *this << "\n" 00437 << "compiled on " << get_build_date() << " by " 00438 << get_distributor() << "\n" 00439 << "with compiler " << PandaSystem::get_compiler() << "\n\n"; 00440 00441 out << "Optional systems:\n"; 00442 for (Systems::const_iterator si = _systems.begin(); 00443 si != _systems.end(); 00444 ++si) { 00445 out << " " << (*si).first << "\n"; 00446 const SystemTags &tags = (*si).second; 00447 SystemTags::const_iterator ti; 00448 for (ti = tags.begin(); ti != tags.end(); ++ti) { 00449 out << " " << (*ti).first << " " << (*ti).second << "\n"; 00450 } 00451 } 00452 } 00453 00454 00455 //////////////////////////////////////////////////////////////////// 00456 // Function: PandaSystem::get_global_ptr 00457 // Access: Published, Static 00458 // Description: Returns the global PandaSystem object. 00459 //////////////////////////////////////////////////////////////////// 00460 PandaSystem *PandaSystem:: 00461 get_global_ptr() { 00462 if (_global_ptr == (PandaSystem *)NULL) { 00463 _global_ptr = new PandaSystem; 00464 } 00465 00466 return _global_ptr; 00467 } 00468 00469 //////////////////////////////////////////////////////////////////// 00470 // Function: PandaSystem::reset_system_names 00471 // Access: Private 00472 // Description: Refills the _system_names vector, which is used for 00473 // get_system_name(), from the current set of available 00474 // system names. 00475 //////////////////////////////////////////////////////////////////// 00476 void PandaSystem:: 00477 reset_system_names() { 00478 _system_names.clear(); 00479 _system_names.reserve(_systems.size()); 00480 00481 Systems::const_iterator si; 00482 for (si = _systems.begin(); si != _systems.end(); ++si) { 00483 _system_names.push_back((*si).first); 00484 } 00485 00486 _system_names_dirty = false; 00487 } 00488 00489 //////////////////////////////////////////////////////////////////// 00490 // Function: PandaSystem::set_package_version_string 00491 // Access: Private 00492 // Description: Loads the value returned by 00493 // get_package_version_string(). This is intended to be 00494 // called by ConfigPageManager to preload the value from 00495 // the panda-package-version config variable, for 00496 // developer's convenience. This has no effect if the 00497 // PANDA_PACKAGE_VERSION_STR configure variable is 00498 // defined at compilation time. This also has no effect 00499 // in NDEBUG mode. 00500 //////////////////////////////////////////////////////////////////// 00501 void PandaSystem:: 00502 set_package_version_string(const string &package_version_string) { 00503 _package_version_string = PANDA_PACKAGE_VERSION_STR; 00504 if (_package_version_string.empty()) { 00505 _package_version_string = package_version_string; 00506 } 00507 } 00508 00509 //////////////////////////////////////////////////////////////////// 00510 // Function: PandaSystem::set_package_host_url 00511 // Access: Private 00512 // Description: Loads the value returned by 00513 // get_package_host_url(). This is intended to be 00514 // called by ConfigPageManager to preload the value from 00515 // the panda-package-host-url config variable, for 00516 // developer's convenience. This has no effect if the 00517 // PANDA_PACKAGE_HOST_URL configure variable is defined 00518 // at compilation time. This also has no effect in 00519 // NDEBUG mode. 00520 //////////////////////////////////////////////////////////////////// 00521 void PandaSystem:: 00522 set_package_host_url(const string &package_host_url) { 00523 _package_host_url = PANDA_PACKAGE_HOST_URL; 00524 if (_package_host_url.empty()) { 00525 _package_host_url = package_host_url; 00526 } 00527 }