mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -04:00
make a mac-friendly application bundle for standalone panda3d
This commit is contained in:
parent
9fe354cd7f
commit
bd79880ee1
@ -15,7 +15,7 @@ import glob
|
||||
import shutil
|
||||
|
||||
import direct
|
||||
from pandac.PandaModules import Filename
|
||||
from pandac.PandaModules import Filename, DSearchPath
|
||||
|
||||
def usage(code, msg = ''):
|
||||
print >> sys.stderr, __doc__
|
||||
@ -25,14 +25,15 @@ def usage(code, msg = ''):
|
||||
def makeBundle(startDir):
|
||||
fstartDir = Filename.fromOsSpecific(startDir)
|
||||
|
||||
# First, make sure there is only one Opt?-* directory, to avoid
|
||||
# ambiguity.
|
||||
optDirs = glob.glob(fstartDir.toOsSpecific() + '/Opt?-*')
|
||||
if len(optDirs) == 0:
|
||||
raise StandardError, 'Application has not yet been compiled.'
|
||||
if len(optDirs) > 1:
|
||||
raise StandardError, 'Too many compiled directories; ambiguous.'
|
||||
optDir = optDirs[0]
|
||||
# Search for nppandad along $DYLD_LIBRARY_PATH.
|
||||
path = DSearchPath()
|
||||
if 'LD_LIBRARY_PATH' in os.environ:
|
||||
path.appendPath(os.environ['LD_LIBRARY_PATH'])
|
||||
if 'DYLD_LIBRARY_PATH' in os.environ:
|
||||
path.appendPath(os.environ['DYLD_LIBRARY_PATH'])
|
||||
nppanda3d = path.findFile('nppanda3d')
|
||||
if not nppanda3d:
|
||||
raise StandardError, "Couldn't find nppanda3d on path."
|
||||
|
||||
# Generate the bundle directory structure
|
||||
rootFilename = Filename(fstartDir, 'bundle')
|
||||
@ -53,7 +54,7 @@ def makeBundle(startDir):
|
||||
|
||||
# Copy in Info.plist and the compiled executable.
|
||||
shutil.copyfile(Filename(fstartDir, "nppanda3d.plist").toOsSpecific(), plistFilename.toOsSpecific())
|
||||
shutil.copyfile(optDir + '/nppanda3d', exeFilename.toOsSpecific())
|
||||
shutil.copyfile(nppanda3d.toOsSpecific(), exeFilename.toOsSpecific())
|
||||
|
||||
# All done!
|
||||
bundleFilename.touch()
|
||||
|
@ -19,7 +19,8 @@
|
||||
#define OSX_SYS_FRAMEWORKS Foundation AppKit Carbon
|
||||
|
||||
#define SOURCES \
|
||||
panda3d.cxx panda3d.h panda3d.I
|
||||
panda3d.cxx panda3d.h panda3d.I \
|
||||
panda3dMain.cxx
|
||||
|
||||
#define WIN_SYS_LIBS user32.lib gdi32.lib shell32.lib ole32.lib
|
||||
|
||||
@ -32,7 +33,6 @@
|
||||
#define BUILD_TARGET $[WINDOWS_PLATFORM]
|
||||
#define USE_PACKAGES openssl zlib
|
||||
#define TARGET panda3dw
|
||||
#define EXTRA_CDEFS NON_CONSOLE
|
||||
|
||||
#define LOCAL_LIBS plugin_common
|
||||
|
||||
@ -45,8 +45,34 @@
|
||||
#define OSX_SYS_FRAMEWORKS Foundation AppKit Carbon
|
||||
|
||||
#define SOURCES \
|
||||
panda3d.cxx panda3d.h panda3d.I
|
||||
panda3d.cxx panda3d.h panda3d.I \
|
||||
panda3dWinMain.cxx
|
||||
|
||||
#define WIN_SYS_LIBS user32.lib gdi32.lib shell32.lib ole32.lib
|
||||
|
||||
#end bin_target
|
||||
|
||||
#begin bin_target
|
||||
// On Mac, we'll build panda3d_mac, which is the Carbon-friendly
|
||||
// application we wrap in a bundle, for picking a p3d file from
|
||||
// Finder.
|
||||
|
||||
#define BUILD_TARGET $[OSX_PLATFORM]
|
||||
#define USE_PACKAGES openssl zlib
|
||||
#define TARGET panda3d_mac
|
||||
|
||||
#define LOCAL_LIBS plugin_common
|
||||
|
||||
#define OTHER_LIBS \
|
||||
prc:c dtoolutil:c dtoolbase:c dtool:m \
|
||||
interrogatedb:c dconfig:c dtoolconfig:m \
|
||||
downloader:c express:c pandaexpress:m \
|
||||
pystub
|
||||
|
||||
#define OSX_SYS_FRAMEWORKS Foundation AppKit Carbon
|
||||
|
||||
#define SOURCES \
|
||||
panda3d.cxx panda3d.h panda3d.I \
|
||||
panda3dMac.cxx panda3dMac.h panda3dMac.I
|
||||
|
||||
#end bin_target
|
||||
|
@ -13,6 +13,18 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::time_to_exit
|
||||
// Access: Public
|
||||
// Description: Returns true if it is time to exit because the last
|
||||
// instance has exited, or false if we should continue
|
||||
// running.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Panda3D::
|
||||
time_to_exit() {
|
||||
return _instances.empty() && _exit_with_last_instance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::URLGetter::get_instance
|
||||
// Access: Public
|
||||
@ -23,4 +35,3 @@ P3D_instance *Panda3D::URLGetter::
|
||||
get_instance() {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
|
@ -50,24 +50,38 @@ static const double wait_cycle = 0.2;
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Panda3D::
|
||||
Panda3D() {
|
||||
Panda3D(bool console_environment) {
|
||||
_console_environment = console_environment;
|
||||
|
||||
_root_dir = find_root_dir();
|
||||
_reporting_download = false;
|
||||
_enable_security = false;
|
||||
|
||||
_window_type = P3D_WT_toplevel;
|
||||
|
||||
_win_x = 0;
|
||||
_win_y = 0;
|
||||
_win_width = 640;
|
||||
_win_height = 480;
|
||||
|
||||
_exit_with_last_instance = true;
|
||||
_host_url = PANDA_PACKAGE_HOST_URL;
|
||||
_this_platform = DTOOL_PLATFORM;
|
||||
_verify_contents = false;
|
||||
|
||||
// Seed the lame random number generator in rand(); we use it to
|
||||
// select a mirror for downloading.
|
||||
srand((unsigned int)time(NULL));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::run
|
||||
// Function: Panda3D::run_command_line
|
||||
// Access: Public
|
||||
// Description: Starts the program going. Returns 0 on success,
|
||||
// nonzero on failure.
|
||||
// Description: Starts the program going, with command-line arguments.
|
||||
// Returns 0 on success, nonzero on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Panda3D::
|
||||
run(int argc, char *argv[]) {
|
||||
run_command_line(int argc, char *argv[]) {
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
@ -77,14 +91,6 @@ run(int argc, char *argv[]) {
|
||||
const char *optstr = "+mu:M:Sp:fw:t:s:o:l:ih";
|
||||
|
||||
bool allow_multiple = false;
|
||||
_host_url = PANDA_PACKAGE_HOST_URL;
|
||||
string super_mirror_url;
|
||||
_this_platform = DTOOL_PLATFORM;
|
||||
_verify_contents = false;
|
||||
|
||||
P3D_window_type window_type = P3D_WT_toplevel;
|
||||
int win_x = 0, win_y = 0;
|
||||
int win_width = 640, win_height = 480;
|
||||
|
||||
int flag = getopt(argc, argv, optstr);
|
||||
|
||||
@ -99,7 +105,7 @@ run(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
super_mirror_url = optarg;
|
||||
_super_mirror_url = optarg;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
@ -116,13 +122,13 @@ run(int argc, char *argv[]) {
|
||||
|
||||
case 'w':
|
||||
if (strcmp(optarg, "toplevel") == 0) {
|
||||
window_type = P3D_WT_toplevel;
|
||||
_window_type = P3D_WT_toplevel;
|
||||
} else if (strcmp(optarg, "embedded") == 0) {
|
||||
window_type = P3D_WT_embedded;
|
||||
_window_type = P3D_WT_embedded;
|
||||
} else if (strcmp(optarg, "fullscreen") == 0) {
|
||||
window_type = P3D_WT_fullscreen;
|
||||
_window_type = P3D_WT_fullscreen;
|
||||
} else if (strcmp(optarg, "hidden") == 0) {
|
||||
window_type = P3D_WT_hidden;
|
||||
_window_type = P3D_WT_hidden;
|
||||
} else {
|
||||
cerr << "Invalid value for -w: " << optarg << "\n";
|
||||
return 1;
|
||||
@ -137,14 +143,14 @@ run(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (!parse_int_pair(optarg, win_width, win_height)) {
|
||||
if (!parse_int_pair(optarg, _win_width, _win_height)) {
|
||||
cerr << "Invalid value for -s: " << optarg << "\n";
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if (!parse_int_pair(optarg, win_x, win_y)) {
|
||||
if (!parse_int_pair(optarg, _win_x, _win_y)) {
|
||||
cerr << "Invalid value for -o: " << optarg << "\n";
|
||||
return 1;
|
||||
}
|
||||
@ -193,127 +199,111 @@ run(int argc, char *argv[]) {
|
||||
argc -= (optind-1);
|
||||
argv += (optind-1);
|
||||
|
||||
if (argc < 2) {
|
||||
if (argc < 2 && _exit_with_last_instance) {
|
||||
// No instances on the command line--that *might* be an error.
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set host_url_prefix to end with a slash.
|
||||
_host_url_prefix = _host_url;
|
||||
if (!_host_url_prefix.empty() && _host_url_prefix[_host_url_prefix.length() - 1] != '/') {
|
||||
_host_url_prefix += '/';
|
||||
}
|
||||
_download_url_prefix = _host_url_prefix;
|
||||
|
||||
// If the "super mirror" URL is a filename, convert it to a file:// url.
|
||||
if (!super_mirror_url.empty()) {
|
||||
if (!is_url(super_mirror_url)) {
|
||||
Filename filename = Filename::from_os_specific(super_mirror_url);
|
||||
filename.make_absolute();
|
||||
string path = filename.to_os_generic();
|
||||
if (!path.empty() && path[0] != '/') {
|
||||
// On Windows, a leading drive letter must be preceded by an
|
||||
// additional slash.
|
||||
path = "/" + path;
|
||||
}
|
||||
super_mirror_url = "file://" + path;
|
||||
}
|
||||
|
||||
// And make sure the super_mirror_url_prefix ends with a slash.
|
||||
_super_mirror_url_prefix = super_mirror_url;
|
||||
if (!_super_mirror_url_prefix.empty() && _super_mirror_url_prefix[_super_mirror_url_prefix.length() - 1] != '/') {
|
||||
_super_mirror_url_prefix += '/';
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_plugin()) {
|
||||
cerr << "Unable to load Panda3D plugin.\n";
|
||||
if (!post_arg_processing()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set up the "super mirror" URL, if specified.
|
||||
if (!super_mirror_url.empty()) {
|
||||
P3D_set_super_mirror(super_mirror_url.c_str());
|
||||
}
|
||||
|
||||
int num_instance_filenames, num_instance_args;
|
||||
char **instance_filenames, **instance_args;
|
||||
|
||||
if (allow_multiple) {
|
||||
// With -m, the remaining arguments are all instance filenames.
|
||||
num_instance_filenames = argc - 1;
|
||||
instance_filenames = argv + 1;
|
||||
num_instance_args = 0;
|
||||
instance_args = argv + argc;
|
||||
|
||||
} else {
|
||||
// Without -m, there is one instance filename, and everything else
|
||||
// gets delivered to that instance.
|
||||
num_instance_filenames = 1;
|
||||
instance_filenames = argv + 1;
|
||||
num_instance_args = argc - 2;
|
||||
instance_args = argv + 2;
|
||||
}
|
||||
|
||||
P3D_window_handle parent_window;
|
||||
if (window_type == P3D_WT_embedded) {
|
||||
// The user asked for an embedded window. Create a toplevel
|
||||
// window to be its parent, of the requested size.
|
||||
if (win_width == 0 && win_height == 0) {
|
||||
win_width = 640;
|
||||
win_height = 480;
|
||||
if (argc > 1) {
|
||||
if (allow_multiple) {
|
||||
// With -m, the remaining arguments are all instance filenames.
|
||||
num_instance_filenames = argc - 1;
|
||||
instance_filenames = argv + 1;
|
||||
num_instance_args = 0;
|
||||
instance_args = argv + argc;
|
||||
|
||||
} else {
|
||||
// Without -m, there is one instance filename, and everything else
|
||||
// gets delivered to that instance.
|
||||
num_instance_filenames = 1;
|
||||
instance_filenames = argv + 1;
|
||||
num_instance_args = argc - 2;
|
||||
instance_args = argv + 2;
|
||||
}
|
||||
|
||||
make_parent_window(parent_window, win_width, win_height);
|
||||
|
||||
// Center the child window(s) within the parent window.
|
||||
if (_window_type == P3D_WT_embedded) {
|
||||
// The user asked for an embedded window. Create a toplevel
|
||||
// window to be its parent, of the requested size.
|
||||
if (_win_width == 0 && _win_height == 0) {
|
||||
_win_width = 640;
|
||||
_win_height = 480;
|
||||
}
|
||||
|
||||
make_parent_window();
|
||||
|
||||
// Center the child window(s) within the parent window.
|
||||
#ifdef _WIN32
|
||||
RECT rect;
|
||||
GetClientRect(parent_window._hwnd, &rect);
|
||||
|
||||
win_x = (int)(rect.right * 0.1);
|
||||
win_y = (int)(rect.bottom * 0.1);
|
||||
win_width = (int)(rect.right * 0.8);
|
||||
win_height = (int)(rect.bottom * 0.8);
|
||||
RECT rect;
|
||||
GetClientRect(_parent_window._hwnd, &rect);
|
||||
|
||||
_win_x = (int)(rect.right * 0.1);
|
||||
_win_y = (int)(rect.bottom * 0.1);
|
||||
_win_width = (int)(rect.right * 0.8);
|
||||
_win_height = (int)(rect.bottom * 0.8);
|
||||
#endif
|
||||
|
||||
// Subdivide the window into num_x_spans * num_y_spans sub-windows.
|
||||
int num_y_spans = int(sqrt((double)num_instance_filenames));
|
||||
int num_x_spans = (num_instance_filenames + num_y_spans - 1) / num_y_spans;
|
||||
|
||||
int inst_width = win_width / num_x_spans;
|
||||
int inst_height = win_height / num_y_spans;
|
||||
|
||||
for (int yi = 0; yi < num_y_spans; ++yi) {
|
||||
for (int xi = 0; xi < num_x_spans; ++xi) {
|
||||
int i = yi * num_x_spans + xi;
|
||||
if (i >= num_instance_filenames) {
|
||||
continue;
|
||||
|
||||
// Subdivide the window into num_x_spans * num_y_spans sub-windows.
|
||||
int num_y_spans = int(sqrt((double)num_instance_filenames));
|
||||
int num_x_spans = (num_instance_filenames + num_y_spans - 1) / num_y_spans;
|
||||
|
||||
int inst_width = _win_width / num_x_spans;
|
||||
int inst_height = _win_height / num_y_spans;
|
||||
|
||||
for (int yi = 0; yi < num_y_spans; ++yi) {
|
||||
for (int xi = 0; xi < num_x_spans; ++xi) {
|
||||
int i = yi * num_x_spans + xi;
|
||||
if (i >= num_instance_filenames) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create instance i at window slot (xi, yi).
|
||||
int inst_x = _win_x + xi * inst_width;
|
||||
int inst_y = _win_y + yi * inst_height;
|
||||
|
||||
P3D_instance *inst = create_instance
|
||||
(instance_filenames[i], true,
|
||||
inst_x, inst_y, inst_width, inst_height,
|
||||
instance_args, num_instance_args);
|
||||
_instances.insert(inst);
|
||||
}
|
||||
|
||||
// Create instance i at window slot (xi, yi).
|
||||
int inst_x = win_x + xi * inst_width;
|
||||
int inst_y = win_y + yi * inst_height;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
// Not an embedded window. Create each window with the same parameters.
|
||||
for (int i = 0; i < num_instance_filenames; ++i) {
|
||||
P3D_instance *inst = create_instance
|
||||
(instance_filenames[i], P3D_WT_embedded,
|
||||
inst_x, inst_y, inst_width, inst_height, parent_window,
|
||||
(instance_filenames[i], true,
|
||||
_win_x, _win_y, _win_width, _win_height,
|
||||
instance_args, num_instance_args);
|
||||
_instances.insert(inst);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Not an embedded window. Create each window with the same parameters.
|
||||
for (int i = 0; i < num_instance_filenames; ++i) {
|
||||
P3D_instance *inst = create_instance
|
||||
(instance_filenames[i], window_type,
|
||||
win_x, win_y, win_width, win_height, parent_window,
|
||||
instance_args, num_instance_args);
|
||||
_instances.insert(inst);
|
||||
}
|
||||
}
|
||||
|
||||
run_main_loop();
|
||||
|
||||
// All instances have finished; we can exit.
|
||||
unload_plugin();
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::run_main_loop
|
||||
// Access: Public
|
||||
// Description: Gets lost in the application main loop, waiting for
|
||||
// system events and notifications from the open
|
||||
// instance(s).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3D::
|
||||
run_main_loop() {
|
||||
#ifdef _WIN32
|
||||
if (window_type == P3D_WT_embedded) {
|
||||
// Wait for new messages from Windows, and new requests from the
|
||||
@ -321,10 +311,10 @@ run(int argc, char *argv[]) {
|
||||
MSG msg;
|
||||
int retval;
|
||||
retval = GetMessage(&msg, NULL, 0, 0);
|
||||
while (retval != 0 && !_instances.empty()) {
|
||||
while (retval != 0 && !time_to_exit()) {
|
||||
if (retval == -1) {
|
||||
cerr << "Error processing message queue.\n";
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
@ -357,7 +347,7 @@ run(int argc, char *argv[]) {
|
||||
} else {
|
||||
// Not an embedded window, so we don't have our own window to
|
||||
// generate Windows events. Instead, just wait for requests.
|
||||
while (!_instances.empty()) {
|
||||
while (!time_to_exit()) {
|
||||
P3D_instance *inst = P3D_check_request(wait_cycle);
|
||||
if (inst != (P3D_instance *)NULL) {
|
||||
P3D_request *request = P3D_instance_get_request(inst);
|
||||
@ -391,7 +381,7 @@ run(int argc, char *argv[]) {
|
||||
#else // _WIN32, __APPLE__
|
||||
|
||||
// Now wait while we process pending requests.
|
||||
while (!_instances.empty()) {
|
||||
while (!time_to_exit()) {
|
||||
P3D_instance *inst = P3D_check_request(wait_cycle);
|
||||
if (inst != (P3D_instance *)NULL) {
|
||||
P3D_request *request = P3D_instance_get_request(inst);
|
||||
@ -403,15 +393,61 @@ run(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
#endif // _WIN32, __APPLE__
|
||||
}
|
||||
|
||||
// All instances have finished; we can exit.
|
||||
unload_plugin();
|
||||
return 0;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::post_arg_processing
|
||||
// Access: Protected
|
||||
// Description: Sets up some internal state after processing the
|
||||
// command-line arguments. Returns true on success,
|
||||
// false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Panda3D::
|
||||
post_arg_processing() {
|
||||
// Set host_url_prefix to end with a slash.
|
||||
_host_url_prefix = _host_url;
|
||||
if (!_host_url_prefix.empty() && _host_url_prefix[_host_url_prefix.length() - 1] != '/') {
|
||||
_host_url_prefix += '/';
|
||||
}
|
||||
_download_url_prefix = _host_url_prefix;
|
||||
|
||||
// If the "super mirror" URL is a filename, convert it to a file:// url.
|
||||
if (!_super_mirror_url.empty()) {
|
||||
if (!is_url(_super_mirror_url)) {
|
||||
Filename filename = Filename::from_os_specific(_super_mirror_url);
|
||||
filename.make_absolute();
|
||||
string path = filename.to_os_generic();
|
||||
if (!path.empty() && path[0] != '/') {
|
||||
// On Windows, a leading drive letter must be preceded by an
|
||||
// additional slash.
|
||||
path = "/" + path;
|
||||
}
|
||||
_super_mirror_url = "file://" + path;
|
||||
}
|
||||
|
||||
// And make sure the super_mirror_url_prefix ends with a slash.
|
||||
_super_mirror_url_prefix = _super_mirror_url;
|
||||
if (!_super_mirror_url_prefix.empty() && _super_mirror_url_prefix[_super_mirror_url_prefix.length() - 1] != '/') {
|
||||
_super_mirror_url_prefix += '/';
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_plugin()) {
|
||||
cerr << "Unable to load Panda3D plugin.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up the "super mirror" URL, if specified.
|
||||
if (!_super_mirror_url.empty()) {
|
||||
P3D_set_super_mirror(_super_mirror_url.c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::get_plugin
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Downloads the contents.xml file from the named URL
|
||||
// and attempts to use it to load the core API. Returns
|
||||
// true on success, false on failure.
|
||||
@ -497,7 +533,7 @@ get_plugin() {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::read_contents_file
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Attempts to open and read the contents.xml file on
|
||||
// disk, and uses that data to load the plugin, if
|
||||
// possible. Returns true on success, false on failure.
|
||||
@ -539,7 +575,7 @@ read_contents_file(const Filename &contents_filename) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::find_host
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Scans the <contents> element for the matching <host>
|
||||
// element.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -575,7 +611,7 @@ find_host(TiXmlElement *xcontents) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::read_xhost
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Reads the host data from the <host> (or <alt_host>)
|
||||
// entry in the contents.xml file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -611,7 +647,7 @@ read_xhost(TiXmlElement *xhost) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::add_mirror
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Adds a new URL to serve as a mirror for this host.
|
||||
// The mirrors will be consulted first, before
|
||||
// consulting the host directly.
|
||||
@ -658,7 +694,7 @@ choose_random_mirrors(vector_string &result, int num_mirrors) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::get_core_api
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Checks the core API DLL file against the
|
||||
// specification in the contents file, and downloads it
|
||||
// if necessary.
|
||||
@ -756,15 +792,9 @@ get_core_api(const Filename &contents_filename, TiXmlElement *xpackage) {
|
||||
|
||||
bool trusted_environment = !_enable_security;
|
||||
|
||||
#ifdef NON_CONSOLE
|
||||
static const bool console_environment = false;
|
||||
#else
|
||||
static const bool console_environment = true;
|
||||
#endif
|
||||
|
||||
if (!load_plugin(pathname, contents_filename.to_os_specific(),
|
||||
_host_url, _verify_contents, _this_platform, _log_dirname,
|
||||
_log_basename, trusted_environment, console_environment,
|
||||
_log_basename, trusted_environment, _console_environment,
|
||||
cerr)) {
|
||||
cerr << "Unable to launch core API in " << pathname << "\n" << flush;
|
||||
return false;
|
||||
@ -786,7 +816,7 @@ get_core_api(const Filename &contents_filename, TiXmlElement *xpackage) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::run_getters
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Polls all of the active URL requests.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3D::
|
||||
@ -810,7 +840,7 @@ run_getters() {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::handle_request
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Handles a single request received via the plugin API
|
||||
// from a p3d instance.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -871,13 +901,12 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::make_parent_window
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Creates a toplevel window to contain the embedded
|
||||
// instances. Windows implementation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3D::
|
||||
make_parent_window(P3D_window_handle &parent_window,
|
||||
int win_width, int win_height) {
|
||||
make_parent_window() {
|
||||
WNDCLASS wc;
|
||||
|
||||
HINSTANCE application = GetModuleHandle(NULL);
|
||||
@ -899,7 +928,7 @@ make_parent_window(P3D_window_handle &parent_window,
|
||||
|
||||
HWND toplevel_window =
|
||||
CreateWindow("panda3d", "Panda3D", window_style,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, win_width, win_height,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, _win_width, _win_height,
|
||||
NULL, NULL, application, 0);
|
||||
if (!toplevel_window) {
|
||||
cerr << "Could not create toplevel window!\n";
|
||||
@ -907,21 +936,20 @@ make_parent_window(P3D_window_handle &parent_window,
|
||||
}
|
||||
|
||||
ShowWindow(toplevel_window, SW_SHOWNORMAL);
|
||||
|
||||
parent_window._hwnd = toplevel_window;
|
||||
|
||||
_parent_window._hwnd = toplevel_window;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::make_parent_window
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Creates a toplevel window to contain the embedded
|
||||
// instances.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3D::
|
||||
make_parent_window(P3D_window_handle &parent_window,
|
||||
int win_width, int win_height) {
|
||||
make_parent_window() {
|
||||
// TODO.
|
||||
assert(false);
|
||||
}
|
||||
@ -930,20 +958,22 @@ make_parent_window(P3D_window_handle &parent_window,
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::create_instance
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Uses the plugin API to create a new P3D instance to
|
||||
// play a particular .p3d file.
|
||||
// play a particular .p3d file. This instance is also
|
||||
// started if start_instance is true (which requires
|
||||
// that the named p3d file exists).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_instance *Panda3D::
|
||||
create_instance(const string &p3d, P3D_window_type window_type,
|
||||
create_instance(const string &p3d, bool start_instance,
|
||||
int win_x, int win_y, int win_width, int win_height,
|
||||
P3D_window_handle parent_window, char **args, int num_args) {
|
||||
char **args, int num_args) {
|
||||
// Check to see if the p3d filename we were given is a URL, or a
|
||||
// local file.
|
||||
Filename p3d_filename = Filename::from_os_specific(p3d);
|
||||
string os_p3d_filename = p3d;
|
||||
bool is_local = !is_url(p3d);
|
||||
if (is_local) {
|
||||
if (is_local && start_instance) {
|
||||
if (!p3d_filename.exists()) {
|
||||
cerr << "No such file: " << p3d_filename << "\n";
|
||||
exit(1);
|
||||
@ -967,11 +997,11 @@ create_instance(const string &p3d, P3D_window_type window_type,
|
||||
} else {
|
||||
// Send output to the console.
|
||||
token._keyword = "console_output";
|
||||
#ifdef NON_CONSOLE
|
||||
token._value = "0";
|
||||
#else
|
||||
token._value = "1";
|
||||
#endif
|
||||
if (_console_environment) {
|
||||
token._value = "1";
|
||||
} else {
|
||||
token._value = "0";
|
||||
}
|
||||
tokens.push_back(token);
|
||||
}
|
||||
|
||||
@ -996,11 +1026,15 @@ create_instance(const string &p3d, P3D_window_type window_type,
|
||||
argv.size(), &argv[0], NULL);
|
||||
|
||||
if (inst != NULL) {
|
||||
// We call start() first, to give the core API a chance to notice
|
||||
// the "hidden" attrib before we set the window parameters.
|
||||
P3D_instance_start(inst, is_local, os_p3d_filename.c_str());
|
||||
if (start_instance) {
|
||||
// We call start() first, to give the core API a chance to
|
||||
// notice the "hidden" attrib before we set the window
|
||||
// parameters.
|
||||
P3D_instance_start(inst, is_local, os_p3d_filename.c_str());
|
||||
}
|
||||
|
||||
P3D_instance_setup_window
|
||||
(inst, window_type, win_x, win_y, win_width, win_height, parent_window);
|
||||
(inst, _window_type, _win_x, _win_y, _win_width, _win_height, _parent_window);
|
||||
}
|
||||
|
||||
return inst;
|
||||
@ -1008,7 +1042,7 @@ create_instance(const string &p3d, P3D_window_type window_type,
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::delete_instance
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Deletes the indicated instance and removes it from
|
||||
// the internal structures.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1034,7 +1068,7 @@ delete_instance(P3D_instance *inst) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::usage
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Reports the available command-line options.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3D::
|
||||
@ -1127,7 +1161,7 @@ usage() {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::parse_token
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Parses a web token of the form token=value, and
|
||||
// stores it in _tokens. Returns true on success, false
|
||||
// on failure.
|
||||
@ -1154,7 +1188,7 @@ parse_token(char *arg) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::parse_int_pair
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Parses a string into an x,y pair of integers.
|
||||
// Returns true on success, false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1175,7 +1209,7 @@ parse_int_pair(char *arg, int &x, int &y) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::is_url
|
||||
// Access: Private, Static
|
||||
// Access: Protected, Static
|
||||
// Description: Returns true if the indicated string appears to be a
|
||||
// URL, with a leading http:// or file:// or whatever,
|
||||
// or false if it must be a local filename instead.
|
||||
@ -1208,7 +1242,7 @@ is_url(const string ¶m) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::report_downloading_package
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Tells the user we have to download a package.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3D::
|
||||
@ -1234,7 +1268,7 @@ report_downloading_package(P3D_instance *instance) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::report_download_complete
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Tells the user we're done downloading packages
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3D::
|
||||
@ -1247,7 +1281,7 @@ report_download_complete(P3D_instance *instance) {
|
||||
#ifdef __APPLE__
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::st_timer_callback
|
||||
// Access: Private, Static
|
||||
// Access: Protected, Static
|
||||
// Description: Installed as a timer on the event loop, so we can
|
||||
// process local events, in the Apple implementation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1260,7 +1294,7 @@ st_timer_callback(EventLoopTimerRef timer, void *user_data) {
|
||||
#ifdef __APPLE__
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::timer_callback
|
||||
// Access: Private
|
||||
// Access: Protected
|
||||
// Description: Installed as a timer on the event loop, so we can
|
||||
// process local events, in the Apple implementation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1280,7 +1314,7 @@ timer_callback(EventLoopTimerRef timer) {
|
||||
run_getters();
|
||||
|
||||
// If we're out of instances, exit the application.
|
||||
if (_instances.empty()) {
|
||||
if (time_to_exit()) {
|
||||
QuitApplicationEventLoop();
|
||||
}
|
||||
}
|
||||
@ -1365,79 +1399,3 @@ run() {
|
||||
_bytes_sent, NULL, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(NON_CONSOLE)
|
||||
// On Windows, we may need to build panda3dw.exe, a non-console
|
||||
// version of this program.
|
||||
|
||||
// Returns a newly-allocated string representing the quoted argument
|
||||
// beginning at p. Advances p to the first character following the
|
||||
// close quote.
|
||||
static char *
|
||||
parse_quoted_arg(char *&p) {
|
||||
char quote = *p;
|
||||
++p;
|
||||
string result;
|
||||
|
||||
while (*p != '\0' && *p != quote) {
|
||||
// TODO: handle escape characters? Not sure if we need to.
|
||||
result += *p;
|
||||
++p;
|
||||
}
|
||||
if (*p == quote) {
|
||||
++p;
|
||||
}
|
||||
return strdup(result.c_str());
|
||||
}
|
||||
|
||||
// Returns a newly-allocated string representing the unquoted argument
|
||||
// beginning at p. Advances p to the first whitespace following the
|
||||
// argument.
|
||||
static char *
|
||||
parse_unquoted_arg(char *&p) {
|
||||
string result;
|
||||
while (*p != '\0' && !isspace(*p)) {
|
||||
result += *p;
|
||||
++p;
|
||||
}
|
||||
return strdup(result.c_str());
|
||||
}
|
||||
|
||||
int WINAPI
|
||||
WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
|
||||
char *command_line = GetCommandLine();
|
||||
|
||||
vector<char *> argv;
|
||||
|
||||
char *p = command_line;
|
||||
while (*p != '\0') {
|
||||
if (*p == '"') {
|
||||
char *arg = parse_quoted_arg(p);
|
||||
argv.push_back(arg);
|
||||
} else {
|
||||
char *arg = parse_unquoted_arg(p);
|
||||
argv.push_back(arg);
|
||||
}
|
||||
|
||||
// Skip whitespace.
|
||||
while (*p != '\0' && isspace(*p)) {
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
assert(!argv.empty());
|
||||
|
||||
Panda3D program;
|
||||
return program.run(argv.size(), &argv[0]);
|
||||
}
|
||||
|
||||
#else // NON_CONSOLE
|
||||
|
||||
// The normal, "console" program.
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
Panda3D program;
|
||||
return program.run(argc, argv);
|
||||
}
|
||||
#endif // NON_CONSOLE
|
||||
|
@ -38,11 +38,13 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class Panda3D {
|
||||
public:
|
||||
Panda3D();
|
||||
Panda3D(bool console_environment);
|
||||
|
||||
int run(int argc, char *argv[]);
|
||||
int run_command_line(int argc, char *argv[]);
|
||||
void run_main_loop();
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool post_arg_processing();
|
||||
bool get_plugin();
|
||||
bool read_contents_file(const Filename &contents_filename);
|
||||
void find_host(TiXmlElement *xcontents);
|
||||
@ -52,13 +54,11 @@ private:
|
||||
bool get_core_api(const Filename &contents_filename, TiXmlElement *xplugin);
|
||||
void run_getters();
|
||||
void handle_request(P3D_request *request);
|
||||
void make_parent_window(P3D_window_handle &parent_window,
|
||||
int win_width, int win_height);
|
||||
void make_parent_window();
|
||||
|
||||
P3D_instance *
|
||||
create_instance(const string &p3d, P3D_window_type window_type,
|
||||
create_instance(const string &p3d, bool start_instance,
|
||||
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);
|
||||
|
||||
@ -70,28 +70,37 @@ private:
|
||||
void report_downloading_package(P3D_instance *instance);
|
||||
void report_download_complete(P3D_instance *instance);
|
||||
|
||||
inline bool time_to_exit();
|
||||
|
||||
#ifdef __APPLE__
|
||||
static pascal void st_timer_callback(EventLoopTimerRef timer, void *user_data);
|
||||
void timer_callback(EventLoopTimerRef timer);
|
||||
#endif
|
||||
|
||||
private:
|
||||
protected:
|
||||
string _root_dir;
|
||||
string _log_dirname;
|
||||
string _log_basename;
|
||||
string _this_platform;
|
||||
bool _verify_contents;
|
||||
P3D_window_type _window_type;
|
||||
P3D_window_handle _parent_window;
|
||||
int _win_x, _win_y;
|
||||
int _win_width, _win_height;
|
||||
bool _exit_with_last_instance;
|
||||
|
||||
string _host_url;
|
||||
string _super_mirror_url_prefix;
|
||||
string _super_mirror_url;
|
||||
string _host_url_prefix;
|
||||
string _download_url_prefix;
|
||||
string _super_mirror_url_prefix;
|
||||
typedef pvector<string> Mirrors;
|
||||
Mirrors _mirrors;
|
||||
|
||||
FileSpec _core_api_dll;
|
||||
bool _reporting_download;
|
||||
bool _enable_security;
|
||||
bool _console_environment;
|
||||
|
||||
typedef pset<P3D_instance *> Instances;
|
||||
Instances _instances;
|
||||
|
14
direct/src/plugin_standalone/panda3dMac.I
Normal file
14
direct/src/plugin_standalone/panda3dMac.I
Normal file
@ -0,0 +1,14 @@
|
||||
// Filename: panda3dMac.I
|
||||
// Created by: drose (23Oct09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
153
direct/src/plugin_standalone/panda3dMac.cxx
Normal file
153
direct/src/plugin_standalone/panda3dMac.cxx
Normal file
@ -0,0 +1,153 @@
|
||||
// Filename: panda3dMac.cxx
|
||||
// Created by: drose (23Oct09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "panda3dMac.h"
|
||||
#include "load_plugin.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
|
||||
// Having a global Panda3DMac object just makes things easier.
|
||||
static Panda3DMac *this_prog;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3DMac::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Panda3DMac::
|
||||
Panda3DMac() : Panda3D(false) {
|
||||
// Mac applications traditionally keep running even when all windows
|
||||
// are closed.
|
||||
_exit_with_last_instance = false;
|
||||
|
||||
// No command-line arguments, so just run.
|
||||
if (!post_arg_processing()) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3DMac::open_p3d_file
|
||||
// Access: Public
|
||||
// Description: Opens a p3d file received via the "open documents"
|
||||
// event as its own instance.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3DMac::
|
||||
open_p3d_file(FSRef *ref) {
|
||||
OSErr err;
|
||||
|
||||
// Get the size and basename of the file.
|
||||
FSCatalogInfo catalog_info;
|
||||
HFSUniStr255 basename_unicode;
|
||||
|
||||
err = FSGetCatalogInfo(ref, kFSCatInfoDataSizes, &catalog_info,
|
||||
&basename_unicode, NULL, NULL);
|
||||
if (err) {
|
||||
cerr << "Couldn't query file information.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// A poor-man's unicode-to-ascii conversion.
|
||||
string basename;
|
||||
for (int i = 0; i < basename_unicode.length; ++i) {
|
||||
basename += (char)basename_unicode.unicode[i];
|
||||
}
|
||||
size_t data_size = (size_t)catalog_info.dataLogicalSize;
|
||||
|
||||
// We could try to figure out full pathname of the p3d file we've
|
||||
// got here, but it's probably better just to open the file and read
|
||||
// it. This way, it works regardless of the source of the p3d file,
|
||||
// even if it's not actually a file on disk.
|
||||
FSIORefNum io_ref;
|
||||
err = FSOpenFork(ref, 0, NULL, fsRdPerm, &io_ref);
|
||||
if (!err) {
|
||||
// Create an instance, and tell it we'll be sending it the p3d
|
||||
// data in a forthcoming stream.
|
||||
P3D_instance *inst = create_instance
|
||||
(basename.c_str(), false,
|
||||
_win_x, _win_y, _win_width, _win_height,
|
||||
NULL, 0);
|
||||
int stream_id = P3D_instance_start_stream(inst, basename.c_str());
|
||||
|
||||
// Now start to read the data.
|
||||
static const size_t buffer_size = 8192;
|
||||
static char buffer[buffer_size];
|
||||
ByteCount read_count;
|
||||
err = FSReadFork(io_ref, fsAtMark, 0, buffer_size, buffer, &read_count);
|
||||
while (read_count != 0) {
|
||||
P3D_instance_feed_url_stream(inst, stream_id, P3D_RC_in_progress, 0,
|
||||
data_size, buffer, read_count);
|
||||
err = FSReadFork(io_ref, fsAtMark, 0, buffer_size, buffer, &read_count);
|
||||
}
|
||||
|
||||
P3D_result_code status = P3D_RC_done;
|
||||
if (err != eofErr) {
|
||||
status = P3D_RC_generic_error;
|
||||
cerr << "Error reading file\n";
|
||||
}
|
||||
|
||||
P3D_instance_feed_url_stream
|
||||
(inst, stream_id, status, 0, data_size, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static pascal OSErr
|
||||
open_documents_handler(const AppleEvent *theAppleEvent, AppleEvent *reply,
|
||||
long handlerRefcon) {
|
||||
AEDescList docList;
|
||||
FSRef theFSRef;
|
||||
long index;
|
||||
long count = 0;
|
||||
|
||||
// Get the list of file aliases from the event.
|
||||
OSErr err = AEGetParamDesc(theAppleEvent,
|
||||
keyDirectObject, typeAEList, &docList);
|
||||
require_noerr(err, CantGetDocList);
|
||||
|
||||
err = AECountItems(&docList, &count);
|
||||
require_noerr(err, CantGetCount);
|
||||
|
||||
for (index = 1; index <= count; index++) {
|
||||
err = AEGetNthPtr(&docList, index, typeFSRef,
|
||||
NULL, NULL, &theFSRef, sizeof(FSRef), NULL);// 5
|
||||
require_noerr(err, CantGetDocDescPtr);
|
||||
|
||||
// Here's the file, do something with it.
|
||||
this_prog->open_p3d_file(&theFSRef);
|
||||
}
|
||||
|
||||
// Release list of files
|
||||
AEDisposeDesc(&docList);
|
||||
|
||||
// Error handlers.
|
||||
CantGetDocList:
|
||||
CantGetCount:
|
||||
CantGetDocDescPtr:
|
||||
return (err);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
OSErr err;
|
||||
AEEventHandlerUPP handler;
|
||||
|
||||
this_prog = new Panda3DMac;
|
||||
handler = NewAEEventHandlerUPP(open_documents_handler);
|
||||
err = AEInstallEventHandler
|
||||
(kCoreEventClass, kAEOpenDocuments, handler, NULL, false);
|
||||
|
||||
return this_prog->run_command_line(argc, argv);
|
||||
}
|
36
direct/src/plugin_standalone/panda3dMac.h
Normal file
36
direct/src/plugin_standalone/panda3dMac.h
Normal file
@ -0,0 +1,36 @@
|
||||
// Filename: panda3dMac.h
|
||||
// Created by: drose (23Oct09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 PANDA3DMAC_H
|
||||
#define PANDA3DMAC_H
|
||||
|
||||
#include "panda3d.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : Panda3DMac
|
||||
// Description : A specialization of Panda3D for running as a Carbon
|
||||
// application on OS X. Instead of taking input from
|
||||
// the command line, this program waits quietly for an
|
||||
// "open documents" Apple event.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class Panda3DMac : public Panda3D {
|
||||
public:
|
||||
Panda3DMac();
|
||||
|
||||
void open_p3d_file(FSRef *ref);
|
||||
};
|
||||
|
||||
#endif
|
22
direct/src/plugin_standalone/panda3dMain.cxx
Normal file
22
direct/src/plugin_standalone/panda3dMain.cxx
Normal file
@ -0,0 +1,22 @@
|
||||
// Filename: panda3dMain.cxx
|
||||
// Created by: drose (23Oct09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "panda3d.h"
|
||||
|
||||
// The normal, "console" program.
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
Panda3D program(true);
|
||||
return program.run_command_line(argc, argv);
|
||||
}
|
80
direct/src/plugin_standalone/panda3dWinMain.cxx
Normal file
80
direct/src/plugin_standalone/panda3dWinMain.cxx
Normal file
@ -0,0 +1,80 @@
|
||||
// Filename: panda3dWinMain.cxx
|
||||
// Created by: drose (23Oct09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "panda3d.h"
|
||||
|
||||
// On Windows, we may need to build panda3dw.exe, a non-console
|
||||
// version of this program.
|
||||
|
||||
// Returns a newly-allocated string representing the quoted argument
|
||||
// beginning at p. Advances p to the first character following the
|
||||
// close quote.
|
||||
static char *
|
||||
parse_quoted_arg(char *&p) {
|
||||
char quote = *p;
|
||||
++p;
|
||||
string result;
|
||||
|
||||
while (*p != '\0' && *p != quote) {
|
||||
// TODO: handle escape characters? Not sure if we need to.
|
||||
result += *p;
|
||||
++p;
|
||||
}
|
||||
if (*p == quote) {
|
||||
++p;
|
||||
}
|
||||
return strdup(result.c_str());
|
||||
}
|
||||
|
||||
// Returns a newly-allocated string representing the unquoted argument
|
||||
// beginning at p. Advances p to the first whitespace following the
|
||||
// argument.
|
||||
static char *
|
||||
parse_unquoted_arg(char *&p) {
|
||||
string result;
|
||||
while (*p != '\0' && !isspace(*p)) {
|
||||
result += *p;
|
||||
++p;
|
||||
}
|
||||
return strdup(result.c_str());
|
||||
}
|
||||
|
||||
int WINAPI
|
||||
WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
|
||||
char *command_line = GetCommandLine();
|
||||
|
||||
vector<char *> argv;
|
||||
|
||||
char *p = command_line;
|
||||
while (*p != '\0') {
|
||||
if (*p == '"') {
|
||||
char *arg = parse_quoted_arg(p);
|
||||
argv.push_back(arg);
|
||||
} else {
|
||||
char *arg = parse_unquoted_arg(p);
|
||||
argv.push_back(arg);
|
||||
}
|
||||
|
||||
// Skip whitespace.
|
||||
while (*p != '\0' && isspace(*p)) {
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
assert(!argv.empty());
|
||||
|
||||
Panda3D program(false);
|
||||
return program.run_command_line(argv.size(), &argv[0]);
|
||||
}
|
55
direct/src/plugin_standalone/panda3d_mac.plist
Normal file
55
direct/src/plugin_standalone/panda3d_mac.plist
Normal file
@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Panda3D Runtime</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Panda3D applet</string>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>panda3d.icns</string>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>p3d</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/x-panda3d</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>panda3d_mac</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>panda3d.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.panda3d.runtime</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Panda3D</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.9.3</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.9.3</string>
|
||||
<key>LSHasLocalizedDisplayName</key>
|
||||
<false/>
|
||||
<key>NSAppleScriptEnabled</key>
|
||||
<false/>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Binary file not shown.
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Binary file not shown.
BIN
models/plugin_images/panda3d.icns
Normal file
BIN
models/plugin_images/panda3d.icns
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user