Prechádzať zdrojové kódy

cleaner p3d scripts

David Rose 16 rokov pred
rodič
commit
ec23ed2a43

+ 6 - 2
direct/src/plugin/Sources.pp

@@ -25,8 +25,10 @@
     p3dPackage.h p3dPackage.I \
     p3dProgressWindow.h p3dProgressWindow.I \
     p3dSession.h p3dSession.I \
+    p3dSplashWindow.h p3dSplashWindow.I \
     p3dWindowParams.h p3dWindowParams.I \
-    p3dWinProgressWindow.h p3dWinProgressWindow.I
+    p3dWinProgressWindow.h p3dWinProgressWindow.I \
+    p3dWinSplashWindow.h p3dWinSplashWindow.I
 
   #define INCLUDED_SOURCES \
     p3d_plugin.cxx \
@@ -38,9 +40,11 @@
     p3dMultifileReader.cxx \
     p3dPackage.cxx \
     p3dProgressWindow.cxx \
+    p3dSplashWindow.cxx \
     p3dSession.cxx \
     p3dWindowParams.cxx \
-    p3dWinProgressWindow.cxx
+    p3dWinProgressWindow.cxx \
+    p3dWinSplashWindow.cxx
 
   #define INSTALL_HEADERS \
     p3d_plugin.h

+ 31 - 0
direct/src/plugin/p3dInstance.cxx

@@ -17,10 +17,18 @@
 #include "p3dDownload.h"
 #include "p3dSession.h"
 #include "p3dPackage.h"
+#include "p3dSplashWindow.h"
+#include "p3dWinSplashWindow.h"
 
 #include <sstream>
 #include <algorithm>
 
+#ifdef _WIN32
+typedef P3DWinSplashWindow SplashWindowType;
+#else
+typedef P3DSplashWindow SplashWindowType;
+#endif
+
 int P3DInstance::_next_instance_id = 0;
 
 ////////////////////////////////////////////////////////////////////
@@ -43,6 +51,8 @@ P3DInstance(P3D_request_ready_func *func, void *user_data) :
   INIT_LOCK(_request_lock);
 
   _session = NULL;
+  _splash_window = NULL;
+  _instance_window_opened = false;
   _requested_stop = false;
 }
 
@@ -65,6 +75,11 @@ P3DInstance::
   }
   _packages.clear();
 
+  if (_splash_window != NULL) {
+    delete _splash_window;
+    _splash_window = NULL;
+  }
+
   // TODO: empty _pending_requests queue and _downloads map.
 
   // TODO: Is it possible for someone to delete an instance while a
@@ -82,6 +97,11 @@ set_fparams(const P3DFileParams &fparams) {
   _got_fparams = true;
   _fparams = fparams;
 
+  // Update the splash window.
+  if (_splash_window != NULL) {
+    _splash_window->set_fparams(_fparams);
+  }
+
   // This also sets up some internal data based on the contents of the
   // above file and the associated tokens.
 
@@ -106,6 +126,17 @@ set_wparams(const P3DWindowParams &wparams) {
   _got_wparams = true;
   _wparams = wparams;
 
+  // Update or create the splash window.
+  if (!_instance_window_opened) {
+    if (_splash_window == NULL) {
+      _splash_window = new SplashWindowType(this);
+      _splash_window->open_window();
+    } else {
+      _splash_window->set_wparams(_wparams);
+    }
+  }
+
+  // Update the instance in the sub-process.
   if (_session != NULL) {
     TiXmlDocument *doc = new TiXmlDocument;
     TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", "");

+ 3 - 0
direct/src/plugin/p3dInstance.h

@@ -25,6 +25,7 @@
 #include <tinyxml.h>
 
 class P3DSession;
+class P3DSplashWindow;
 class P3DDownload;
 class P3DPackage;
 
@@ -85,6 +86,8 @@ private:
   string _session_key;
   string _python_version;
   P3DSession *_session;
+  P3DSplashWindow *_splash_window;
+  bool _instance_window_opened;
 
   typedef vector<P3DPackage *> Packages;
   Packages _packages;

+ 28 - 19
direct/src/plugin/p3dPythonRun.cxx

@@ -88,37 +88,46 @@ P3DPythonRun::
 ////////////////////////////////////////////////////////////////////
 bool P3DPythonRun::
 run_python() {
-  // Now load runappmf.pyd.
-  PyObject *runappmf = PyImport_ImportModule("runappmf");
-  if (runappmf == NULL) {
+  // First, load runp3d_frozen.pyd.  Since this is a magic frozen pyd,
+  // importing it automatically makes all of its frozen contents
+  // available to import as well.
+  PyObject *runp3d_frozen = PyImport_ImportModule("runp3d_frozen");
+  if (runp3d_frozen == NULL) {
     PyErr_Print();
     return false;
   }
-  Py_DECREF(runappmf);
+  Py_DECREF(runp3d_frozen);
 
-  // And get the pointers to the functions needed within the module.
-  PyObject *appmf = PyImport_ImportModule("direct.showbase.RunAppMF");
-  if (appmf == NULL) {
+  // So now we can import the module itself.
+  PyObject *runp3d = PyImport_ImportModule("direct.showutil.runp3d");
+  if (runp3d == NULL) {
     PyErr_Print();
     return false;
   }
-  _setP3DFilename = PyObject_GetAttrString(appmf, "setP3DFilename");
-  if (_setP3DFilename == NULL) {
+
+  // Get the pointers to the objects needed within the module.
+  PyObject *AppRunner = PyObject_GetAttrString(runp3d, "AppRunner");
+  if (AppRunner == NULL) {
     PyErr_Print();
     return false;
   }
-  _setupWindow = PyObject_GetAttrString(appmf, "setupWindow");
-  if (_setupWindow == NULL) {
+
+  // Construct an instance of AppRunner.
+  _runner = PyObject_CallFunction(AppRunner, "");
+  if (_runner == NULL) {
     PyErr_Print();
     return false;
   }
-  _taskMgr = PyObject_GetAttrString(appmf, "taskMgr");
+  Py_DECREF(AppRunner);
+
+  // Get the global TaskManager.
+  _taskMgr = PyObject_GetAttrString(runp3d, "taskMgr");
   if (_taskMgr == NULL) {
     PyErr_Print();
     return false;
   }
 
-  Py_DECREF(appmf);
+  Py_DECREF(runp3d);
 
   // Now add check_comm() as a task.
   _check_comm_task = new GenericAsyncTask("check_comm", st_check_comm, this);
@@ -359,8 +368,8 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
     xtoken = xtoken->NextSiblingElement("token");
   }
   
-  PyObject *result = PyObject_CallFunction
-    (_setP3DFilename, "sO", p3d_filename.c_str(), token_list);
+  PyObject *result = PyObject_CallMethod
+    (_runner, "setP3DFilename", "sO", p3d_filename.c_str(), token_list);
   Py_DECREF(token_list);
 
   if (result == NULL) {
@@ -415,10 +424,10 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
   }
 #endif
 
-  // TODO: direct this into the particular instance.  Requires
-  // specialized ShowBase replacement.
-  PyObject *result = PyObject_CallFunction
-    (_setupWindow, "siiiii", window_type.c_str(),
+  // TODO: direct this into the particular instance.  This will
+  // require a specialized ShowBase replacement.
+  PyObject *result = PyObject_CallMethod
+    (_runner, "setupWindow", "siiiii", window_type.c_str(),
      win_x, win_y, win_width, win_height,
      parent_window_handle);
   if (result == NULL) {

+ 1 - 2
direct/src/plugin/p3dPythonRun.h

@@ -95,8 +95,7 @@ private:
   int _py_argc;
   char **_py_argv;
 
-  PyObject *_setP3DFilename;
-  PyObject *_setupWindow;
+  PyObject *_runner;
   PyObject *_taskMgr;
 
   PT(GenericAsyncTask) _check_comm_task;

+ 4 - 4
direct/src/plugin/p3dSession.cxx

@@ -24,9 +24,9 @@
 #endif
 
 #ifdef _WIN32
-typedef P3DWinProgressWindow ProgressWinType;
+typedef P3DWinProgressWindow ProgressWindowType;
 #else
-typedef P3DProgressWindow ProgressWinType;
+typedef P3DProgressWindow ProgressWindowType;
 #endif
 
 ////////////////////////////////////////////////////////////////////
@@ -173,9 +173,9 @@ start_instance(P3DInstance *inst) {
         _panda3d_callback = new P3DProgressWindow(_panda3d, this, inst);
       } else {
         // For a non-hidden window, create an instance of
-        // ProgressWinType, which is typedeffed above to be the kind
+        // ProgressWindowType, which is typedeffed above to be the kind
         // of class that actually does manifest a window.
-        _panda3d_callback = new ProgressWinType(_panda3d, this, inst);
+        _panda3d_callback = new ProgressWindowType(_panda3d, this, inst);
       }
       */
       _panda3d->set_callback(_panda3d_callback);

+ 34 - 0
direct/src/plugin/p3dSplashWindow.I

@@ -0,0 +1,34 @@
+// Filename: p3dSplashWindow.I
+// Created by:  drose (17Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::get_fparams
+//       Access: Public
+//  Description: Returns the current file parameters.
+////////////////////////////////////////////////////////////////////
+inline const P3DFileParams &P3DSplashWindow::
+get_fparams() const {
+  return _fparams;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::get_wparams
+//       Access: Public
+//  Description: Returns the current window parameters.
+////////////////////////////////////////////////////////////////////
+inline const P3DWindowParams &P3DSplashWindow::
+get_wparams() const {
+  return _wparams;
+}

+ 79 - 0
direct/src/plugin/p3dSplashWindow.cxx

@@ -0,0 +1,79 @@
+// Filename: p3dSplashWindow.cxx
+// Created by:  drose (17Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "p3dSplashWindow.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DSplashWindow::
+P3DSplashWindow(P3DInstance *inst) : 
+  _inst(inst),
+  _fparams(inst->get_fparams()),
+  _wparams(inst->get_wparams())
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DSplashWindow::
+~P3DSplashWindow() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::set_fparams
+//       Access: Public, Virtual
+//  Description: Sets up the file parameters for the window.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+set_fparams(const P3DFileParams &fparams) {
+  _fparams = fparams;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::set_wparams
+//       Access: Public, Virtual
+//  Description: Changes the window parameters, e.g. to resize or
+//               reposition the window; or sets the parameters for the
+//               first time, creating the initial window.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+set_wparams(const P3DWindowParams &wparams) {
+  _wparams = wparams;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::open_window
+//       Access: Public, Virtual
+//  Description: Creates the splash window.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+open_window() {
+  nout << "P3DSplashWindow::open_window()\n" << flush;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::close_window
+//       Access: Public, Virtual
+//  Description: Closes the window created above.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+close_window() {
+  nout << "P3DSplashWindow::close_window()\n" << flush;
+}

+ 57 - 0
direct/src/plugin/p3dSplashWindow.h

@@ -0,0 +1,57 @@
+// Filename: p3dSplashWindow.h
+// Created by:  drose (17Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+
+#ifndef P3DSPLASHWINDOW_H
+#define P3DSPLASHWINDOW_H
+
+#include "p3d_plugin_common.h"
+#include "p3dFileParams.h"
+#include "p3dWindowParams.h"
+
+class P3DInstance;
+
+////////////////////////////////////////////////////////////////////
+//       Class : P3DSplashWindow
+// Description : This window is displayed temporarily, in place of an
+//               instance's actual window, during the initial launch
+//               of an applet, and also during the initial download of
+//               Panda3D code if necessary.
+//
+//               This is the base implementation; it contains no
+//               specific code to open a window.
+////////////////////////////////////////////////////////////////////
+class P3DSplashWindow {
+public:
+  P3DSplashWindow(P3DInstance *inst);
+  virtual ~P3DSplashWindow();
+
+  virtual void set_fparams(const P3DFileParams &fparams);
+  inline const P3DFileParams &get_fparams() const;
+
+  virtual void set_wparams(const P3DWindowParams &wparams);
+  inline const P3DWindowParams &get_wparams() const;
+
+  virtual void open_window();
+  virtual void close_window();
+
+protected:
+  P3DInstance *_inst;
+  P3DFileParams _fparams;
+  P3DWindowParams _wparams;
+};
+
+#include "p3dSplashWindow.I"
+
+#endif

+ 14 - 0
direct/src/plugin/p3dWinSplashWindow.I

@@ -0,0 +1,14 @@
+// Filename: p3dWinSplashWindow.I
+// Created by:  drose (17Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+

+ 170 - 0
direct/src/plugin/p3dWinSplashWindow.cxx

@@ -0,0 +1,170 @@
+// Filename: p3dWinSplashWindow.cxx
+// Created by:  drose (17Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "p3dWinSplashWindow.h"
+
+#ifdef _WIN32
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DWinSplashWindow::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DWinSplashWindow::
+P3DWinSplashWindow(P3DInstance *inst) : 
+  P3DSplashWindow(inst)
+{
+  _hwnd = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DWinSplashWindow::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DWinSplashWindow::
+~P3DWinSplashWindow() {
+  close_window();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DWinSplashWindow::open_window
+//       Access: Public, Virtual
+//  Description: Creates the splash window.
+////////////////////////////////////////////////////////////////////
+void P3DWinSplashWindow::
+open_window() {
+  P3DSplashWindow::open_window();
+  WNDCLASS wc;
+
+  HINSTANCE application = GetModuleHandle(NULL);
+
+  static bool registered_class = false;
+  if (!registered_class) {
+    ZeroMemory(&wc, sizeof(WNDCLASS));
+    wc.lpfnWndProc = window_proc;
+    wc.hInstance = application;
+    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+    wc.lpszClassName = "panda3d_splash";
+    
+    if (!RegisterClass(&wc)) {
+      nout << "Could not register window class!\n";
+    }
+    registered_class = true;
+  }
+  
+  int x = CW_USEDEFAULT;
+  int y = CW_USEDEFAULT;
+  if (_wparams.get_win_x() != 0 && _wparams.get_win_y() != 0) {
+    x = _wparams.get_win_x();
+    y = _wparams.get_win_y();
+  }
+  
+  int width = 320;
+  int height = 240;
+  if (_wparams.get_win_width() != 0 && _wparams.get_win_height() != 0) {
+    width = _wparams.get_win_width();
+    height = _wparams.get_win_height();
+  }
+
+  if (_wparams.get_window_type() == P3D_WT_embedded) {
+    // Create an embedded window.
+    DWORD window_style = 
+      WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+
+    HWND parent_hwnd = _wparams.get_parent_window()._hwnd;
+
+    _hwnd = 
+      CreateWindow("panda3d_splash", "Panda3D", window_style,
+                   x, y, width, height,
+                   parent_hwnd, NULL, application, 0);
+    
+    if (!_hwnd) {
+      nout << "Could not create embedded window!\n";
+      return;
+    }
+
+  } else {
+    // Create a toplevel window.
+    DWORD window_style = 
+      WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
+      WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
+      WS_SIZEBOX | WS_MAXIMIZEBOX;
+    
+    _hwnd = 
+      CreateWindow("panda3d_splash", "Panda3D", window_style,
+                   x, y, width, height,
+                   NULL, NULL, application, 0);
+    if (!_hwnd) {
+      nout << "Could not create toplevel window!\n";
+      return;
+    }
+    ShowWindow(_hwnd, SW_SHOWNORMAL);
+  }
+}
+
+  // Ensure the main window is visible now.
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DWinSplashWindow::close_window
+//       Access: Public, Virtual
+//  Description: Closes the window created above.
+////////////////////////////////////////////////////////////////////
+void P3DWinSplashWindow::
+close_window() {
+  P3DSplashWindow::close_window();
+  if (_hwnd) {
+    ShowWindow(_hwnd, SW_HIDE);
+    CloseWindow(_hwnd);
+    _hwnd = NULL;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DWinSplashWindow::window_proc
+//       Access: Private, Static
+//  Description: The windows event-processing handler.
+////////////////////////////////////////////////////////////////////
+LONG P3DWinSplashWindow::
+window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
+  switch (msg) {
+  case WM_DESTROY:
+    PostQuitMessage(0);
+    break;
+
+  case WM_DRAWITEM:
+    // Draw a text label placed within the window.
+    {
+      DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
+      FillRect(dis->hDC, &(dis->rcItem), WHITE_BRUSH);
+
+      static const int text_buffer_size = 512;
+      char text_buffer[text_buffer_size];
+      GetWindowText(dis->hwndItem, text_buffer, text_buffer_size);
+
+      HFONT font = (HFONT)GetStockObject(ANSI_VAR_FONT); 
+      SelectObject(dis->hDC, font);
+      SetBkColor(dis->hDC, 0x00ffffff);
+
+      DrawText(dis->hDC, text_buffer, -1, &(dis->rcItem), 
+               DT_BOTTOM | DT_CENTER | DT_SINGLELINE);
+    }
+  };
+
+  return DefWindowProc(hwnd, msg, wparam, lparam);
+}
+
+
+#endif  // _WIN32

+ 51 - 0
direct/src/plugin/p3dWinSplashWindow.h

@@ -0,0 +1,51 @@
+// Filename: p3dWinSplashWindow.h
+// Created by:  drose (17Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef P3DWINSPLASHWINDOW_H
+#define P3DWINSPLASHWINDOW_H
+
+#include "p3d_plugin_common.h"
+
+#ifdef _WIN32
+
+#include "p3dSplashWindow.h"
+#include "p3d_lock.h"
+
+#include <windows.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : P3DWinSplashWindow
+// Description : This is the Windows implementation of the
+//               initial-download window.
+////////////////////////////////////////////////////////////////////
+class P3DWinSplashWindow : public P3DSplashWindow {
+public:
+  P3DWinSplashWindow(P3DInstance *inst);
+  virtual ~P3DWinSplashWindow();
+
+  virtual void open_window();
+  virtual void close_window();
+
+private:
+  static LONG WINAPI window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
+
+private:
+  HWND _hwnd;
+};
+
+#include "p3dWinSplashWindow.I"
+
+#endif  // _WIN32
+
+#endif

+ 2 - 0
direct/src/plugin/p3d_plugin_composite1.cxx

@@ -7,6 +7,8 @@
 #include "p3dMultifileReader.cxx"
 #include "p3dPackage.cxx"
 #include "p3dProgressWindow.cxx"
+#include "p3dSplashWindow.cxx"
 #include "p3dSession.cxx"
 #include "p3dWindowParams.cxx"
 #include "p3dWinProgressWindow.cxx"
+#include "p3dWinSplashWindow.cxx"

+ 0 - 4
direct/src/plugin_npapi/startup.cxx

@@ -324,7 +324,6 @@ NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) {
 ////////////////////////////////////////////////////////////////////
 int32
 NPP_WriteReady(NPP instance, NPStream *stream) {
-  logfile << "WriteReady\n";
   // We're supposed to return the maximum amount of data the plugin is
   // prepared to handle.  Gee, I don't know.  As much as you can give
   // me, I guess.
@@ -340,9 +339,6 @@ NPP_WriteReady(NPP instance, NPStream *stream) {
 int32
 NPP_Write(NPP instance, NPStream *stream, int32 offset, 
           int32 len, void *buffer) {
-  logfile << "Write " << stream->url 
-          << ", " << len << "\n" << flush;
-
   PPInstance *inst = (PPInstance *)(instance->pdata);
   assert(inst != NULL);
 

+ 0 - 231
direct/src/showbase/RunAppMF.py

@@ -1,231 +0,0 @@
-""" This module can serve as a startup script to play a Panda
-application packed within a .mf file.  Run via:
-
-python RunAppMF.py app.mf
-
-This is currently experimental, but the intent is to work towards a
-prepackaged Panda distributable, designed to run applications exactly
-like this.
-
-Also see MakeAppMF.py.
-
-"""
-
-import sys
-from direct.showbase import VFSImporter
-from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, getModelPath, HTTPClient
-from direct.stdpy import file
-from direct.task.TaskManagerGlobal import taskMgr
-import os
-import __builtin__
-
-MultifileRoot = '/mf'
-
-# This defines the default prc file that is implicitly loaded with an
-# application.
-AppPrcFilename = 'App.prc'
-AppPrc = """
-default-model-extension .bam
-"""
-
-class ArgumentError(AttributeError):
-    pass
-
-__packedAppEnvironmentInitialized = False
-
-def initPackedAppEnvironment():
-    """ This function sets up the Python environment suitably for
-    running a packed app.  It should only run once in any given
-    session (and it includes logic to ensure this). """
-
-    global __packedAppEnvironmentInitialized
-    if __packedAppEnvironmentInitialized:
-        return
-
-    __packedAppEnvironmentInitialized = True
-
-    # We need to make sure sys.stdout maps to sys.stderr instead, so
-    # if someone makes an unadorned print command within Python code,
-    # it won't muck up the data stream between parent and child.
-    sys.stdout = sys.stderr
-
-    vfs = VirtualFileSystem.getGlobalPtr()
-
-    # Clear *all* the mount points, including "/", so that we no
-    # longer access the disk directly.
-    vfs.unmountAll()
-
-    # Make sure the directories on our standard Python path are mounted
-    # read-only, so we can still load Python.
-    for dirname in sys.path:
-        vfs.mount(dirname, dirname, vfs.MFReadOnly)
-
-    # Also mount some standard directories read-write (temporary and
-    # app-data directories).
-    tdir = Filename.temporary('', '')
-    for dirname in set([ tdir.getDirname(),
-                         Filename.getTempDirectory().cStr(),
-                         Filename.getUserAppdataDirectory().cStr(),
-                         Filename.getCommonAppdataDirectory().cStr() ]):
-        vfs.mount(dirname, dirname, 0)
-
-    # Now set up Python to import this stuff.
-    VFSImporter.register()
-    sys.path = [ MultifileRoot ] + sys.path
-
-    # Put our root directory on the model-path and prc-path, too.
-    getModelPath().prependDirectory(MultifileRoot)
-
-    # Load the implicit App.prc file.
-    loadPrcFileData(AppPrcFilename, AppPrc)
-
-    # Replace the builtin open and file symbols so user code will get
-    # our versions by default, which can open and read files out of
-    # the multifile.
-    __builtin__.file = file.file
-    __builtin__.open = file.open
-    os.listdir = file.listdir
-    os.walk = file.walk
-
-    # Make "/mf" our "current directory", for running the multifiles
-    # we plan to mount there.
-    vfs.chdir(MultifileRoot)
-
-gotWindow = False
-gotP3DFilename = False
-started = False
-def startIfReady():
-    global gotWindow, gotP3DFilename, started
-    if started:
-        return
-    
-    if gotWindow and gotP3DFilename:
-        started = True
-        import main
-        if hasattr(main, 'main') and callable(main.main):
-            main.main()
-
-def setP3DFilename(p3dFilename, tokens = []):
-    tokenDict = dict(tokens)
-    fname = Filename.fromOsSpecific(p3dFilename)
-    if not p3dFilename:
-        # If we didn't get a literal filename, we have to download it
-        # from the URL.  TODO: make this a smarter temporary filename?
-        fname = Filename.temporary('', 'p3d_')
-        fname.setExtension('p3d')
-        p3dFilename = fname.toOsSpecific()
-        src = tokenDict.get('src', None)
-        if not src:
-            raise ArgumentError, "No Panda app specified."
-            
-        http = HTTPClient.getGlobalPtr()
-        hc = http.getDocument(src)
-        if not hc.downloadToFile(fname):
-            fname.unlink()
-            raise ArgumentError, "Couldn't download %s" % (src)
-
-        # Set a hook on sys.exit to delete the temporary file.
-        oldexitfunc = getattr(sys, 'exitfunc', None)
-        def deleteTempFile(fname = fname, oldexitfunc = oldexitfunc):
-            fname.unlink()
-            if oldexitfunc:
-                oldexitfunc()
-
-        sys.exitfunc = deleteTempFile
-
-    vfs = VirtualFileSystem.getGlobalPtr()
-
-    if not vfs.exists(fname):
-        raise ArgumentError, "No such file: %s" % (p3dFilename)
-
-    fname.makeAbsolute()
-    initPackedAppEnvironment()
-
-    mf = Multifile()
-    if not mf.openRead(fname):
-        raise ArgumentError, "Not a Panda Multifile: %s" % (p3dFilename)
-
-    # Mount the Multifile under /mf, by convention.
-    vfs.mount(mf, MultifileRoot, vfs.MFReadOnly)
-
-    # Load any prc files in the root.  We have to load them
-    # explicitly, since the ConfigPageManager can't directly look
-    # inside the vfs.  Use the Multifile interface to find the prc
-    # files, rather than vfs.scanDirectory(), so we only pick up the
-    # files in this particular multifile.
-    for f in mf.getSubfileNames():
-        fn = Filename(f)
-        if fn.getDirname() == '' and fn.getExtension() == 'prc':
-            pathname = '%s/%s' % (MultifileRoot, f)
-            data = open(pathname, 'r').read()
-            loadPrcFileData(pathname, data)
-
-    global gotP3DFilename
-    gotP3DFilename = True
-    startIfReady()
-
-windowPrc = None
-def setupWindow(windowType, x, y, width, height, parent):
-    if windowType == 'hidden':
-        data = 'window-type none\n'
-    else:
-        data = 'window-type onscreen\n'
-
-    if windowType == 'fullscreen':
-        data += 'fullscreen 1\n'
-    else:
-        data += 'fullscreen 0\n'
-
-    if windowType == 'embedded':
-        data += 'parent-window-handle %s\n' % (parent)
-    else:
-        data += 'parent-window-handle 0\n'
-    
-    if x or y:
-        data += 'win-origin %s %s\n' % (x, y)
-    if width or height:
-        data += 'win-size %s %s\n' % (width, height)
-
-    global windowPrc
-    if windowPrc:
-        unloadPrcFile(windowPrc)
-    windowPrc = loadPrcFileData("setupWindow", data)
-
-    global gotWindow
-    gotWindow = True
-    startIfReady()
-
-def parseSysArgs():
-    """ Converts sys.argv into (p3dFilename, tokens). """
-    if len(sys.argv) < 2 or not sys.argv[1]:
-        raise ArgumentError, "No Panda app specified.  Use:\npython RunAppMF.py app.mf"
-
-    tokens = []
-    for token in sys.argv[2:]:
-        if '=' in token:
-            keyword, value = token.split('=', 1)
-        else:
-            keyword = token
-            value = ''
-        tokens.append((keyword.lower(), value))
-
-    p3dFilename = Filename.fromOsSpecific(sys.argv[1])
-    osFilename = p3dFilename.toOsSpecific()
-    if not p3dFilename.exists():
-        # If the filename doesn't exist, it must be a URL.
-        osFilename = ''
-        if 'src' not in dict(tokens):
-            tokens.append(('src', sys.argv[1]))
-
-    return (osFilename, tokens)
-        
-        
-
-if __name__ == '__main__':
-    gotWindow = True
-    try:
-        setP3DFilename(*parseSysArgs())
-    except ArgumentError, e:
-        print e.args[0]
-        sys.exit(1)
-    run()

+ 53 - 0
direct/src/showutil/Sources.pp

@@ -0,0 +1,53 @@
+#define INSTALL_SCRIPTS packp3d.py runp3d.py
+
+// Generate an appropriate script to invoke the above Python files.
+// On Windows, we generate a batch file; on other platforms (including
+// Cygwin), we generate a sh script.
+
+#define install_dir $[$[upcase $[PACKAGE]]_INSTALL]
+#define install_bin_dir $[or $[INSTALL_BIN_DIR],$[install_dir]/bin]
+
+#define python $[PYTHON_COMMAND]
+#if $[USE_DEBUG_PYTHON]
+  #define python $[PYTHON_DEBUG_COMMAND]
+#endif
+
+#foreach scriptname packp3d runp3d
+  #if $[eq $[PLATFORM],Win32]
+    #set INSTALL_SCRIPTS $[INSTALL_SCRIPTS] $[scriptname].bat
+  #else
+    #set INSTALL_SCRIPTS $[INSTALL_SCRIPTS] $[scriptname]
+  #endif
+
+  #if $[eq $[PLATFORM],Win32]
+#output $[scriptname].bat notouch
+@echo off
+rem #### Generated automatically by $[PPREMAKE] $[PPREMAKE_VERSION] from $[notdir $[THISFILENAME]].
+rem ################################# DO NOT EDIT ###########################
+
+$[python] -u $[osfilename $[install_bin_dir]/$[scriptname].py] %1 %2 %3 %4 %5 %6 %7 %8 %9
+#end $[scriptname].bat
+
+#else  // Win32
+
+#output $[scriptname] binary notouch
+#! /bin/sh
+#### Generated automatically by $[PPREMAKE] $[PPREMAKE_VERSION] from $[notdir $[THISFILENAME]].
+################################# DO NOT EDIT ###########################
+
+#if $[CTPROJS]
+# This script was generated while the user was using the ctattach
+# tools.  That had better still be the case.
+#if $[WINDOWS_PLATFORM]
+$[python] -u `cygpath -w $DIRECT/built/bin/$[scriptname].py` "$@"
+#else
+$[python] -u $DIRECT/built/bin/$[scriptname].py "$@"
+#endif
+#else
+$[python] -u '$[osfilename $[install_bin_dir]/$[scriptname].py]' "$@"
+#endif
+#end $[scriptname]
+
+#endif  // Win32
+
+#end scriptname

+ 15 - 5
direct/src/showbase/MakeAppMF.py → direct/src/showutil/packp3d.py

@@ -1,9 +1,15 @@
+#! /usr/bin/env python
+
 """
-This module will pack a Panda application, consisting of a
-directory tree of .py files and models, into a multifile for
-distribution and running with RunAppMF.py.  To run it, use:
 
-python MakeAppMF.py [opts] app.mf
+This module will pack a Panda application, consisting of a directory
+tree of .py files and models, into a p3d file for convenient
+distribution.  The resulting p3d file can be run by the Panda3D
+runtime executable, or by the Panda3D web browser plugin.
+
+Usage:
+
+  packp3d.py [opts] app.p3d
 
 Options:
 
@@ -23,6 +29,10 @@ Options:
      (this is preferable to having the module start itself immediately
      upon importing).
 
+     Note that your main.py must *not* call run().  This call should
+     not be part of the p3d file--the Panda3D runtime must be free to
+     call it, not your code!
+
   -c [py,pyc,pyo]
 
      Specifies the compilation mode of python files.  'py' means to
@@ -335,7 +345,7 @@ def makePackedApp(args):
             sys.exit(1)
     
     if not args:
-        raise ArgumentError, "No destination app specified.  Use:\npython MakeAppMF.py app.mf"
+        raise ArgumentError, "No destination app specified.  Use:\npackp3d.py app.p3d"
 
     multifile_name = args[0]
     if len(args) > 1:

+ 257 - 0
direct/src/showutil/runp3d.py

@@ -0,0 +1,257 @@
+#! /usr/bin/env python
+
+"""
+
+This module is intended to be compiled into the Panda3D runtime
+distributable, but it can also be run directly via the Python
+interpreter.  It will run a Panda3D applet--a p3d file--that has
+previously been generated via packp3d.py.
+
+Usage:
+
+  runp3d.py app.p3d [keyword=value [keyword=value ...] ]
+
+The command-line keywords mimic the additional parameters that may
+appear in HTML syntax when the p3d file appears on a web page.  These
+are passed as given to the app, which may decide what to do with them.
+
+See pack3d.py for a script that generates these p3d files.
+
+"""
+
+import sys
+from direct.showbase import VFSImporter
+from direct.showbase.DirectObject import DirectObject
+from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, getModelPath, HTTPClient
+from direct.stdpy import file
+from direct.task.TaskManagerGlobal import taskMgr
+import os
+import __builtin__
+
+MultifileRoot = '/mf'
+
+# This defines the default prc file that is implicitly loaded with an
+# application.
+AppPrcFilename = 'App.prc'
+AppPrc = """
+default-model-extension .bam
+"""
+
+class ArgumentError(AttributeError):
+    pass
+
+class AppRunner(DirectObject):
+    def __init__(self):
+        DirectObject.__init__(self)
+        
+        self.packedAppEnvironmentInitialized = False
+        self.gotWindow = False
+        self.gotP3DFilename = False
+        self.started = False
+        self.windowPrc = None
+
+    def initPackedAppEnvironment(self):
+        """ This function sets up the Python environment suitably for
+        running a packed app.  It should only run once in any given
+        session (and it includes logic to ensure this). """
+
+        if self.packedAppEnvironmentInitialized:
+            return
+
+        self.packedAppEnvironmentInitialized = True
+
+        # We need to make sure sys.stdout maps to sys.stderr instead, so
+        # if someone makes an unadorned print command within Python code,
+        # it won't muck up the data stream between parent and child.
+        sys.stdout = sys.stderr
+
+        vfs = VirtualFileSystem.getGlobalPtr()
+
+        # Clear *all* the mount points, including "/", so that we no
+        # longer access the disk directly.
+        vfs.unmountAll()
+
+        # Make sure the directories on our standard Python path are mounted
+        # read-only, so we can still load Python.
+        for dirname in sys.path:
+            vfs.mount(dirname, dirname, vfs.MFReadOnly)
+
+        # Also mount some standard directories read-write (temporary and
+        # app-data directories).
+        tdir = Filename.temporary('', '')
+        for dirname in set([ tdir.getDirname(),
+                             Filename.getTempDirectory().cStr(),
+                             Filename.getUserAppdataDirectory().cStr(),
+                             Filename.getCommonAppdataDirectory().cStr() ]):
+            vfs.mount(dirname, dirname, 0)
+
+        # Now set up Python to import this stuff.
+        VFSImporter.register()
+        sys.path = [ MultifileRoot ] + sys.path
+
+        # Put our root directory on the model-path and prc-path, too.
+        getModelPath().prependDirectory(MultifileRoot)
+
+        # Load the implicit App.prc file.
+        loadPrcFileData(AppPrcFilename, AppPrc)
+
+        # Replace the builtin open and file symbols so user code will get
+        # our versions by default, which can open and read files out of
+        # the multifile.
+        __builtin__.file = file.file
+        __builtin__.open = file.open
+        os.listdir = file.listdir
+        os.walk = file.walk
+
+        # Make "/mf" our "current directory", for running the multifiles
+        # we plan to mount there.
+        vfs.chdir(MultifileRoot)
+
+    def startIfReady(self):
+        if self.started:
+            return
+
+        if self.gotWindow and self.gotP3DFilename:
+            self.started = True
+
+            # Hang a hook so we know when the window is actually opened.
+            self.acceptOnce('window-event', self.windowEvent)
+
+            import main
+            if hasattr(main, 'main') and callable(main.main):
+                main.main()
+
+    def setP3DFilename(self, p3dFilename, tokens = []):
+        tokenDict = dict(tokens)
+        fname = Filename.fromOsSpecific(p3dFilename)
+        if not p3dFilename:
+            # If we didn't get a literal filename, we have to download it
+            # from the URL.  TODO: make this a smarter temporary filename?
+            fname = Filename.temporary('', 'p3d_')
+            fname.setExtension('p3d')
+            p3dFilename = fname.toOsSpecific()
+            src = tokenDict.get('src', None)
+            if not src:
+                raise ArgumentError, "No Panda app specified."
+
+            http = HTTPClient.getGlobalPtr()
+            hc = http.getDocument(src)
+            if not hc.downloadToFile(fname):
+                fname.unlink()
+                raise ArgumentError, "Couldn't download %s" % (src)
+
+            # Set a hook on sys.exit to delete the temporary file.
+            oldexitfunc = getattr(sys, 'exitfunc', None)
+            def deleteTempFile(fname = fname, oldexitfunc = oldexitfunc):
+                fname.unlink()
+                if oldexitfunc:
+                    oldexitfunc()
+
+            sys.exitfunc = deleteTempFile
+
+        vfs = VirtualFileSystem.getGlobalPtr()
+
+        if not vfs.exists(fname):
+            raise ArgumentError, "No such file: %s" % (p3dFilename)
+
+        fname.makeAbsolute()
+        self.initPackedAppEnvironment()
+
+        mf = Multifile()
+        if not mf.openRead(fname):
+            raise ArgumentError, "Not a Panda Multifile: %s" % (p3dFilename)
+
+        # Mount the Multifile under /mf, by convention.
+        vfs.mount(mf, MultifileRoot, vfs.MFReadOnly)
+
+        # Load any prc files in the root.  We have to load them
+        # explicitly, since the ConfigPageManager can't directly look
+        # inside the vfs.  Use the Multifile interface to find the prc
+        # files, rather than vfs.scanDirectory(), so we only pick up the
+        # files in this particular multifile.
+        for f in mf.getSubfileNames():
+            fn = Filename(f)
+            if fn.getDirname() == '' and fn.getExtension() == 'prc':
+                pathname = '%s/%s' % (MultifileRoot, f)
+                data = open(pathname, 'r').read()
+                loadPrcFileData(pathname, data)
+
+        self.gotP3DFilename = True
+        self.startIfReady()
+
+    def setupWindow(self, windowType, x, y, width, height, parent):
+        if windowType == 'hidden':
+            data = 'window-type none\n'
+        else:
+            data = 'window-type onscreen\n'
+
+        if windowType == 'fullscreen':
+            data += 'fullscreen 1\n'
+        else:
+            data += 'fullscreen 0\n'
+
+        if windowType == 'embedded':
+            data += 'parent-window-handle %s\n' % (parent)
+        else:
+            data += 'parent-window-handle 0\n'
+
+        if x or y:
+            data += 'win-origin %s %s\n' % (x, y)
+        if width or height:
+            data += 'win-size %s %s\n' % (width, height)
+
+        if self.windowPrc:
+            unloadPrcFile(self.windowPrc)
+        self.windowPrc = loadPrcFileData("setupWindow", data)
+
+        self.gotWindow = True
+        self.startIfReady()
+
+    def windowEvent(self, win):
+        print "Got window event in runp3d"
+
+        # TODO: feed this information back to the plugin host.
+
+    def parseSysArgs(self):
+        """ Converts sys.argv into (p3dFilename, tokens). """
+        import getopt
+        opts, args = getopt.getopt(sys.argv[1:], 'h')
+
+        for option, value in opts:
+            if option == '-h':
+                print __doc__
+                sys.exit(1)
+
+        if not args or not args[0]:
+            raise ArgumentError, "No Panda app specified.  Use:\nrunp3d.py app.p3d"
+
+        tokens = []
+        for token in args[1:]:
+            if '=' in token:
+                keyword, value = token.split('=', 1)
+            else:
+                keyword = token
+                value = ''
+            tokens.append((keyword.lower(), value))
+
+        p3dFilename = Filename.fromOsSpecific(sys.argv[1])
+        osFilename = p3dFilename.toOsSpecific()
+        if not p3dFilename.exists():
+            # If the filename doesn't exist, it must be a URL.
+            osFilename = ''
+            if 'src' not in dict(tokens):
+                tokens.append(('src', sys.argv[1]))
+
+        return (osFilename, tokens)
+
+        
+
+if __name__ == '__main__':
+    runner = AppRunner()
+    runner.gotWindow = True
+    try:
+        runner.setP3DFilename(*runner.parseSysArgs())
+    except ArgumentError, e:
+        print e.args[0]
+        sys.exit(1)
+    run()