diff --git a/direct/src/plugin/p3dFileParams.cxx b/direct/src/plugin/p3dFileParams.cxx index 38325b92cb..af7de5fdc2 100644 --- a/direct/src/plugin/p3dFileParams.cxx +++ b/direct/src/plugin/p3dFileParams.cxx @@ -82,6 +82,25 @@ set_tokens(const P3D_token tokens[], size_t num_tokens) { } } +//////////////////////////////////////////////////////////////////// +// Function: P3DFileParams::set_args +// Access: Public +// Description: Specifies the command-line arguments associated with +// the instance. +//////////////////////////////////////////////////////////////////// +void P3DFileParams:: +set_args(int argc, const char *argv[]) { + _args.clear(); + + for (int i = 0; i < argc; ++i) { + const char *arg = argv[i]; + if (arg == NULL) { + arg = ""; + } + _args.push_back(arg); + } +} + //////////////////////////////////////////////////////////////////// // Function: P3DFileParams::lookup_token // Access: Public @@ -136,10 +155,17 @@ make_xml() { for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) { const Token &token = (*ti); TiXmlElement *xtoken = new TiXmlElement("token"); - xtoken->SetAttribute("keyword", token._keyword.c_str()); - xtoken->SetAttribute("value", token._value.c_str()); + xtoken->SetAttribute("keyword", token._keyword); + xtoken->SetAttribute("value", token._value); xfparams->LinkEndChild(xtoken); } + Args::const_iterator ai; + for (ai = _args.begin(); ai != _args.end(); ++ai) { + TiXmlElement *xarg = new TiXmlElement("arg"); + xarg->SetAttribute("value", (*ai)); + xfparams->LinkEndChild(xarg); + } + return xfparams; } diff --git a/direct/src/plugin/p3dFileParams.h b/direct/src/plugin/p3dFileParams.h index 7495d3631c..78efa22058 100644 --- a/direct/src/plugin/p3dFileParams.h +++ b/direct/src/plugin/p3dFileParams.h @@ -32,6 +32,7 @@ public: void set_p3d_filename(const string &p3d_filename); void set_tokens(const P3D_token tokens[], size_t num_tokens); + void set_args(int argc, const char *argv[]); inline const string &get_p3d_filename() const; string lookup_token(const string &keyword) const; @@ -46,9 +47,11 @@ private: string _value; }; typedef vector Tokens; + typedef vector Args; string _p3d_filename; Tokens _tokens; + Args _args; }; #include "p3dFileParams.I" diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 3b9b0b8716..60ac763e4d 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -51,7 +51,8 @@ typedef P3DSplashWindow SplashWindowType; //////////////////////////////////////////////////////////////////// P3DInstance:: P3DInstance(P3D_request_ready_func *func, - const P3D_token tokens[], size_t num_tokens, void *user_data) : + const P3D_token tokens[], size_t num_tokens, + int argc, const char *argv[], void *user_data) : _func(func) { _browser_script_object = NULL; diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index 9fbf6d9160..b867434f10 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -49,7 +49,8 @@ class P3DToplevelObject; class P3DInstance : public P3D_instance, public P3DReferenceCount { public: P3DInstance(P3D_request_ready_func *func, - const P3D_token tokens[], size_t num_tokens, void *user_data); + const P3D_token tokens[], size_t num_tokens, + int argc, const char *argv[], void *user_data); ~P3DInstance(); void set_p3d_url(const string &p3d_url); diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index 0af9c8b5d5..084603d810 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/direct/src/plugin/p3dInstanceManager.cxx @@ -207,8 +207,9 @@ read_contents_file(const string &contents_filename) { P3DInstance *P3DInstanceManager:: create_instance(P3D_request_ready_func *func, const P3D_token tokens[], size_t num_tokens, - void *user_data) { - P3DInstance *inst = new P3DInstance(func, tokens, num_tokens, user_data); + int argc, const char *argv[], void *user_data) { + P3DInstance *inst = new P3DInstance(func, tokens, num_tokens, argc, argv, + user_data); inst->ref(); _instances.insert(inst); diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h index 52a98da86c..cb848bd903 100644 --- a/direct/src/plugin/p3dInstanceManager.h +++ b/direct/src/plugin/p3dInstanceManager.h @@ -55,7 +55,7 @@ public: P3DInstance * create_instance(P3D_request_ready_func *func, const P3D_token tokens[], size_t num_tokens, - void *user_data); + int argc, const char *argv[], void *user_data); bool set_p3d_filename(P3DInstance *inst, bool is_local, const string &p3d_filename); diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index a615518423..6e43a8e329 100755 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -942,7 +942,6 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) { } PyObject *token_list = PyList_New(0); - TiXmlElement *xtoken = xfparams->FirstChildElement("token"); while (xtoken != NULL) { string keyword, value; @@ -963,11 +962,28 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) { xtoken = xtoken->NextSiblingElement("token"); } + + PyObject *arg_list = PyList_New(0); + TiXmlElement *xarg = xfparams->FirstChildElement("arg"); + while (xarg != NULL) { + string value; + const char *value_c = xarg->Attribute("value"); + if (value_c != NULL) { + value = value_c; + } + + PyObject *str = Py_BuildValue("s", value.c_str()); + PyList_Append(arg_list, str); + Py_DECREF(str); + + xarg = xarg->NextSiblingElement("arg"); + } PyObject *result = PyObject_CallMethod - (_runner, (char *)"setP3DFilename", (char *)"sOi", p3d_filename.c_str(), - token_list, inst->get_instance_id()); + (_runner, (char *)"setP3DFilename", (char *)"sOOi", p3d_filename.c_str(), + token_list, arg_list, inst->get_instance_id()); Py_DECREF(token_list); + Py_DECREF(arg_list); if (result == NULL) { PyErr_Print(); diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index 9480443acc..db91e162e6 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -105,12 +105,13 @@ P3D_finalize() { P3D_instance * P3D_new_instance(P3D_request_ready_func *func, const P3D_token tokens[], size_t num_tokens, - void *user_data) { + int argc, const char *argv[], void *user_data) { nout << "new_instance\n"; assert(P3DInstanceManager::get_global_ptr()->is_initialized()); ACQUIRE_LOCK(_api_lock); P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); - P3DInstance *result = inst_mgr->create_instance(func, tokens, num_tokens, user_data); + P3DInstance *result = inst_mgr->create_instance(func, tokens, num_tokens, + argc, argv, user_data); RELEASE_LOCK(_api_lock); return result; } diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index 390c4c2358..123484b93e 100644 --- a/direct/src/plugin/p3d_plugin.h +++ b/direct/src/plugin/p3d_plugin.h @@ -224,6 +224,14 @@ typedef struct { passed to the application, who is free to decide how to interpret them; they have no meaning at the system level. + The argc/argv parameters are intended for when the plugin is + invoked from the command line; they should be filled a standard + C-style argc/argv parameter list, corresponding to the command-line + parameters passed to the application. They may be 0 and NULL when + the plugin is invoked from the web. As above, this array and its + string data will be copied into the core API's own internal + storage, and need not persist after this call. + The user_data pointer is any arbitrary pointer value; it will be copied into the _user_data member of the new P3D_instance object. This pointer is intended for the host to use to store private data @@ -234,6 +242,7 @@ typedef struct { typedef P3D_instance * P3D_new_instance_func(P3D_request_ready_func *func, const P3D_token tokens[], size_t num_tokens, + int argc, const char *argv[], void *user_data); /* This function should be called at some point after diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 45fcea4cfd..7c051b0688 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -957,7 +957,8 @@ create_instance() { if (!_tokens.empty()) { tokens = &_tokens[0]; } - _p3d_inst = P3D_new_instance(request_ready, tokens, _tokens.size(), this); + _p3d_inst = P3D_new_instance(request_ready, tokens, _tokens.size(), + 0, NULL, this); if (_p3d_inst != NULL) { // Now get the browser's window object, to pass to the plugin. diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index a0ab25e1a6..2376fda359 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -609,30 +609,35 @@ make_parent_window(P3D_window_handle &parent_window, // play a particular .p3d file. //////////////////////////////////////////////////////////////////// P3D_instance *Panda3D:: -create_instance(const string &arg, P3D_window_type window_type, +create_instance(const string &p3d, P3D_window_type window_type, int win_x, int win_y, int win_width, int win_height, P3D_window_handle parent_window, char **args, int num_args) { - P3D_token tokens[] = { - { "src", arg.c_str() }, - }; - int num_tokens = sizeof(tokens) / sizeof(P3D_token); - // If the supplied parameter name is a real file, pass it in on the // parameter list. Otherwise, assume it's a URL and let the plugin // download it. - Filename p3d_filename = Filename::from_os_specific(arg); - string os_p3d_filename; + Filename p3d_filename = Filename::from_os_specific(p3d); + string os_p3d_filename = p3d; + bool is_local = false; if (p3d_filename.exists()) { p3d_filename.make_absolute(); os_p3d_filename = p3d_filename.to_os_specific(); + is_local = true; } - P3D_instance *inst = P3D_new_instance(NULL, tokens, num_tokens, NULL); + // Build up the argument list, beginning with the p3d_filename. + pvector argv; + argv.push_back(os_p3d_filename.c_str()); + for (int i = 0; i < num_args; ++i) { + argv.push_back(args[i]); + } + + P3D_instance *inst = P3D_new_instance(NULL, NULL, 0, + argv.size(), &argv[0], NULL); if (inst != NULL) { P3D_instance_setup_window (inst, window_type, win_x, win_y, win_width, win_height, parent_window); - P3D_instance_start(inst, true, os_p3d_filename.c_str()); + P3D_instance_start(inst, is_local, os_p3d_filename.c_str()); } return inst; diff --git a/direct/src/plugin_standalone/panda3d.h b/direct/src/plugin_standalone/panda3d.h index d1791927bb..6929a5d85b 100755 --- a/direct/src/plugin_standalone/panda3d.h +++ b/direct/src/plugin_standalone/panda3d.h @@ -55,11 +55,11 @@ private: void make_parent_window(P3D_window_handle &parent_window, int win_width, int win_height); - P3D_instance *create_instance(const string &arg, P3D_window_type window_type, - int win_x, int win_y, int win_width, - int win_height, - P3D_window_handle parent_window, - char **args, int num_args); + P3D_instance * + create_instance(const string &p3d, P3D_window_type window_type, + int win_x, int win_y, int win_width, int win_height, + P3D_window_handle parent_window, + char **args, int num_args); void delete_instance(P3D_instance *instance); void usage(); diff --git a/direct/src/showutil/FreezeTool.py b/direct/src/showutil/FreezeTool.py index 1606e60c4c..e721287145 100644 --- a/direct/src/showutil/FreezeTool.py +++ b/direct/src/showutil/FreezeTool.py @@ -371,6 +371,9 @@ class Freezer: self.moduleName = moduleName self.filename = filename + def __repr__(self): + return 'ModuleDef(%s, %s, %s)' % (repr(self.token), repr(self.moduleName), repr(self.filename)) + def __init__(self, previous = None, debugLevel = 0): # Normally, we are freezing for our own platform. Change this # if untrue. @@ -646,7 +649,6 @@ class Freezer: parentName, baseName = newName.rsplit('.', 1) if parentName in excludeDict: token = excludeDict[parentName] - if token == self.MTInclude: includes.append(mdef) elif token == self.MTAuto or token == self.MTGuess: @@ -772,10 +774,12 @@ class Freezer: # Previously exported. pass else: - if newName in self.mf.modules or \ - newName in startupModules or \ + if mdef.moduleName in self.mf.modules or \ + mdef.moduleName in startupModules or \ mdef.filename: moduleDefs.append((newName, mdef)) + else: + print "Unknown module %s" % (mdef.moduleName) elif token == self.MTForbid: if not prev or prev.token != self.MTForbid: moduleDefs.append((newName, mdef)) diff --git a/direct/src/showutil/Packager.py b/direct/src/showutil/Packager.py index 43b4a34b58..9db3947bb1 100644 --- a/direct/src/showutil/Packager.py +++ b/direct/src/showutil/Packager.py @@ -194,8 +194,9 @@ class Packager: message = 'No main_module specified for application %s' % (self.packageName) raise PackagerError, message if self.mainModule: - if self.mainModule not in self.freezer.modules: - self.freezer.addModule(self.mainModule) + moduleName, newName = self.mainModule + if newName not in self.freezer.modules: + self.freezer.addModule(moduleName, newName = newName) # Pick up any unfrozen Python files. self.freezer.done() @@ -601,7 +602,7 @@ class Packager: if self.version: xpackage.SetAttribute('version', self.version) - xpackage.SetAttribute('main_module', self.mainModule) + xpackage.SetAttribute('main_module', self.mainModule[1]) for variable, value in self.configs.items(): if isinstance(value, types.UnicodeType): @@ -1463,15 +1464,19 @@ class Packager: def parse_main_module(self, words): """ - main_module moduleName + main_module moduleName [newName] """ + newName = None try: - command, moduleName = words + if len(words) == 2: + command, moduleName = words + else: + command, moduleName, newName = words except ValueError: raise ArgumentError - self.mainModule(moduleName) + self.mainModule(moduleName, newName = newName) def parse_freeze_exe(self, words): """ @@ -1879,11 +1884,13 @@ class Packager: if not self.currentPackage: raise OutsideOfPackageError - if self.currentPackage.mainModule and self.currentPackage.mainModule != moduleName: + if self.currentPackage.mainModule and self.currentPackage.mainModule[0] != moduleName: self.notify.warning("Replacing main_module %s with %s" % ( - self.currentPackage.mainModule, moduleName)) + self.currentPackage.mainModule[0], moduleName)) - self.currentPackage.mainModule = moduleName + if not newName: + newName = moduleName + self.currentPackage.mainModule = (moduleName, newName) def freeze(self, filename, compileToExe = False): """ Freezes all of the current Python code into either an @@ -1906,10 +1913,17 @@ class Packager: raise PackagerError, message if package.mainModule: - if package.mainModule not in freezer.modules: - freezer.addModule(package.mainModule, newName = '__main__') + moduleName, newName = package.mainModule + if compileToExe: + # If we're producing an exe, the main module must + # be called "__main__". + newName = '__main__' + package.mainModule = (moduleName, newName) + + if newName not in freezer.modules: + freezer.addModule(moduleName, newName = newName) else: - freezer.modules['__main__'] = freezer.modules[package.mainModule] + freezer.modules[newName] = freezer.modules[moduleName] freezer.done(compileToExe = compileToExe) if not package.dryRun: diff --git a/direct/src/showutil/packp3d.py b/direct/src/showutil/packp3d.py index 1e298d603b..eadbe7e55c 100755 --- a/direct/src/showutil/packp3d.py +++ b/direct/src/showutil/packp3d.py @@ -128,6 +128,12 @@ def makePackedApp(args): packager.endPackage(appBase, p3dApplication = True) +def main(appRunner): + """ This function is called when this module is invoked as + packp3d.p3d. """ + + makePackedApp(appRunner.argv[1:]) + if __name__ == '__main__': try: makePackedApp(sys.argv[1:]) diff --git a/direct/src/showutil/runp3d.py b/direct/src/showutil/runp3d.py index bacedbba05..83b5b42518 100755 --- a/direct/src/showutil/runp3d.py +++ b/direct/src/showutil/runp3d.py @@ -223,12 +223,12 @@ class AppRunner(DirectObject): v = VFSImporter.VFSImporter(MultifileRoot) loader = v.find_module(moduleName) if not loader: - message = "No %s.py found in application." % (mainName) + message = "No %s found in application." % (moduleName) raise StandardError, message main = loader.load_module(moduleName) if hasattr(main, 'main') and callable(main.main): - main.main() + main.main(self) def getPandaScriptObject(self): """ Called by the browser to query the Panda instance's @@ -251,7 +251,7 @@ class AppRunner(DirectObject): needsResponse = False) self.deferredEvals = [] - def setP3DFilename(self, p3dFilename, tokens = [], + def setP3DFilename(self, p3dFilename, tokens = [], argv = [], instanceId = None): # One day we will have support for multiple instances within a # Python session. Against that day, we save the instance ID @@ -260,6 +260,7 @@ class AppRunner(DirectObject): self.tokens = tokens self.tokenDict = dict(tokens) + self.argv = argv # Tell the browser that Python is up and running, and ready to # respond to queries.