working on inbound scripting controls
This commit is contained in:
parent
482b5f1a46
commit
13552a7041
|
|
@ -46,8 +46,8 @@ P3D_new_bool_object_func *P3D_new_bool_object;
|
|||
P3D_new_int_object_func *P3D_new_int_object;
|
||||
P3D_new_float_object_func *P3D_new_float_object;
|
||||
P3D_new_string_object_func *P3D_new_string_object;
|
||||
P3D_instance_get_script_object_func *P3D_instance_get_script_object;
|
||||
P3D_instance_set_script_object_func *P3D_instance_set_script_object;
|
||||
P3D_instance_get_panda_script_object_func *P3D_instance_get_panda_script_object;
|
||||
P3D_instance_set_browser_script_object_func *P3D_instance_set_browser_script_object;
|
||||
|
||||
P3D_instance_get_request_func *P3D_instance_get_request;
|
||||
P3D_check_request_func *P3D_check_request;
|
||||
|
|
@ -188,8 +188,8 @@ load_plugin(const string &p3d_plugin_filename) {
|
|||
P3D_new_int_object = (P3D_new_int_object_func *)get_func(module, "P3D_new_int_object");
|
||||
P3D_new_float_object = (P3D_new_float_object_func *)get_func(module, "P3D_new_float_object");
|
||||
P3D_new_string_object = (P3D_new_string_object_func *)get_func(module, "P3D_new_string_object");
|
||||
P3D_instance_get_script_object = (P3D_instance_get_script_object_func *)get_func(module, "P3D_instance_get_script_object");
|
||||
P3D_instance_set_script_object = (P3D_instance_set_script_object_func *)get_func(module, "P3D_instance_set_script_object");
|
||||
P3D_instance_get_panda_script_object = (P3D_instance_get_panda_script_object_func *)get_func(module, "P3D_instance_get_panda_script_object");
|
||||
P3D_instance_set_browser_script_object = (P3D_instance_set_browser_script_object_func *)get_func(module, "P3D_instance_set_browser_script_object");
|
||||
|
||||
P3D_instance_get_request = (P3D_instance_get_request_func *)get_func(module, "P3D_instance_get_request");
|
||||
P3D_check_request = (P3D_check_request_func *)get_func(module, "P3D_check_request");
|
||||
|
|
@ -212,8 +212,8 @@ load_plugin(const string &p3d_plugin_filename) {
|
|||
P3D_new_int_object == NULL ||
|
||||
P3D_new_float_object == NULL ||
|
||||
P3D_new_string_object == NULL ||
|
||||
P3D_instance_get_script_object == NULL ||
|
||||
P3D_instance_set_script_object == NULL ||
|
||||
P3D_instance_get_panda_script_object == NULL ||
|
||||
P3D_instance_set_browser_script_object == NULL ||
|
||||
|
||||
P3D_instance_get_request == NULL ||
|
||||
P3D_check_request == NULL ||
|
||||
|
|
@ -235,8 +235,8 @@ load_plugin(const string &p3d_plugin_filename) {
|
|||
<< "\nP3D_new_int_object = " << P3D_new_int_object
|
||||
<< "\nP3D_new_float_object = " << P3D_new_float_object
|
||||
<< "\nP3D_new_string_object = " << P3D_new_string_object
|
||||
<< "\nP3D_instance_get_script_object = " << P3D_instance_get_script_object
|
||||
<< "\nP3D_instance_set_script_object = " << P3D_instance_set_script_object
|
||||
<< "\nP3D_instance_get_panda_script_object = " << P3D_instance_get_panda_script_object
|
||||
<< "\nP3D_instance_set_browser_script_object = " << P3D_instance_set_browser_script_object
|
||||
|
||||
<< "\nP3D_instance_get_request = " << P3D_instance_get_request
|
||||
<< "\nP3D_check_request = " << P3D_check_request
|
||||
|
|
@ -313,8 +313,8 @@ unload_dso() {
|
|||
P3D_new_int_object = NULL;
|
||||
P3D_new_float_object = NULL;
|
||||
P3D_new_string_object = NULL;
|
||||
P3D_instance_get_script_object = NULL;
|
||||
P3D_instance_set_script_object = NULL;
|
||||
P3D_instance_get_panda_script_object = NULL;
|
||||
P3D_instance_set_browser_script_object = NULL;
|
||||
|
||||
P3D_instance_get_request = NULL;
|
||||
P3D_check_request = NULL;
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ extern P3D_new_bool_object_func *P3D_new_bool_object;
|
|||
extern P3D_new_int_object_func *P3D_new_int_object;
|
||||
extern P3D_new_float_object_func *P3D_new_float_object;
|
||||
extern P3D_new_string_object_func *P3D_new_string_object;
|
||||
extern P3D_instance_get_script_object_func *P3D_instance_get_script_object;
|
||||
extern P3D_instance_set_script_object_func *P3D_instance_set_script_object;
|
||||
extern P3D_instance_get_panda_script_object_func *P3D_instance_get_panda_script_object;
|
||||
extern P3D_instance_set_browser_script_object_func *P3D_instance_set_browser_script_object;
|
||||
|
||||
extern P3D_instance_get_request_func *P3D_instance_get_request;
|
||||
extern P3D_check_request_func *P3D_check_request;
|
||||
|
|
|
|||
|
|
@ -81,17 +81,3 @@ make_string(string &value) const {
|
|||
value = "False";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DBoolObject::make_xml
|
||||
// Access: Public, Virtual
|
||||
// Description: Allocates and returns a new XML structure
|
||||
// corresponding to this value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TiXmlElement *P3DBoolObject::
|
||||
make_xml() const {
|
||||
TiXmlElement *xvalue = new TiXmlElement("value");
|
||||
xvalue->SetAttribute("type", "bool");
|
||||
xvalue->SetAttribute("value", (int)_value);
|
||||
return xvalue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ public:
|
|||
virtual int get_int() const;
|
||||
virtual void make_string(string &value) const;
|
||||
|
||||
virtual TiXmlElement *make_xml() const;
|
||||
|
||||
private:
|
||||
bool _value;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -90,18 +90,3 @@ make_string(string &value) const {
|
|||
strm << _value;
|
||||
value = strm.str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DFloatObject::make_xml
|
||||
// Access: Public, Virtual
|
||||
// Description: Allocates and returns a new XML structure
|
||||
// corresponding to this value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TiXmlElement *P3DFloatObject::
|
||||
make_xml() const {
|
||||
TiXmlElement *xvalue = new TiXmlElement("value");
|
||||
xvalue->SetAttribute("type", "float");
|
||||
xvalue->SetDoubleAttribute("value", _value);
|
||||
return xvalue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ public:
|
|||
virtual double get_float() const;
|
||||
virtual void make_string(string &value) const;
|
||||
|
||||
virtual TiXmlElement *make_xml() const;
|
||||
|
||||
private:
|
||||
double _value;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ P3DInstance::
|
|||
P3DInstance(P3D_request_ready_func *func, void *user_data) :
|
||||
_func(func)
|
||||
{
|
||||
_browser_script_object = NULL;
|
||||
_user_data = user_data;
|
||||
_request_pending = false;
|
||||
_got_fparams = false;
|
||||
|
|
@ -68,6 +69,10 @@ P3DInstance::
|
|||
~P3DInstance() {
|
||||
assert(_session == NULL);
|
||||
|
||||
if (_browser_script_object != NULL) {
|
||||
P3D_OBJECT_FINISH(_browser_script_object);
|
||||
}
|
||||
|
||||
DESTROY_LOCK(_request_lock);
|
||||
|
||||
// Tell all of the packages that we're no longer in business for
|
||||
|
|
@ -162,22 +167,22 @@ set_wparams(const P3DWindowParams &wparams) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::get_script_object
|
||||
// Function: P3DInstance::get_panda_script_object
|
||||
// Access: Public
|
||||
// Description: Returns a pointer to the top-level scriptable object
|
||||
// of the instance, to be used by JavaScript code in the
|
||||
// browser to control this program.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DObject *P3DInstance::
|
||||
get_script_object() const {
|
||||
get_panda_script_object() const {
|
||||
assert(_session != NULL);
|
||||
nout << "Called P3DInstance::get_script_object()\n";
|
||||
nout << "Called P3DInstance::get_panda_script_object()\n";
|
||||
|
||||
TiXmlDocument *doc = new TiXmlDocument;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||
TiXmlElement *xcommand = new TiXmlElement("command");
|
||||
xcommand->SetAttribute("cmd", "pyobj");
|
||||
xcommand->SetAttribute("op", "get_script_object");
|
||||
xcommand->SetAttribute("op", "get_panda_script_object");
|
||||
doc->LinkEndChild(decl);
|
||||
doc->LinkEndChild(xcommand);
|
||||
TiXmlDocument *response = _session->command_and_response(doc);
|
||||
|
|
@ -202,6 +207,29 @@ get_script_object() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::set_browser_script_object
|
||||
// Access: Public
|
||||
// Description: Stores a pointer to the top-level window object
|
||||
// of the browser, to be used by Panda code to control
|
||||
// JavaScript. Ownership of this object is passed into
|
||||
// the instance.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
set_browser_script_object(P3D_object *browser_script_object) {
|
||||
nout << "Called P3DInstance::set_browser_script_object()\n";
|
||||
if (browser_script_object != _browser_script_object) {
|
||||
if (_browser_script_object != NULL) {
|
||||
P3D_OBJECT_FINISH(_browser_script_object);
|
||||
}
|
||||
_browser_script_object = browser_script_object;
|
||||
|
||||
if (_session != NULL) {
|
||||
send_browser_script_object();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::has_request
|
||||
|
|
@ -237,22 +265,22 @@ get_request() {
|
|||
}
|
||||
RELEASE_LOCK(_request_lock);
|
||||
|
||||
nout << "get_request: " << result << "\n" << flush;
|
||||
|
||||
if (result != NULL) {
|
||||
if (result->_request_type == P3D_RT_notify) {
|
||||
// If we received a notify request, process the notification
|
||||
// immediately--it might be interesting to this instance.
|
||||
const char *message = result->_request._notify._message;
|
||||
if (strcmp(message, "onwindowopen") == 0) {
|
||||
// The process told us that it just succesfully opened its
|
||||
// window.
|
||||
nout << "Instance " << this << " got onwindowopen\n" << flush;
|
||||
_instance_window_opened = true;
|
||||
if (_splash_window != NULL) {
|
||||
nout << "Deleting splash window\n" << flush;
|
||||
delete _splash_window;
|
||||
_splash_window = NULL;
|
||||
}
|
||||
}
|
||||
switch (result->_request_type) {
|
||||
case P3D_RT_notify:
|
||||
handle_notify_request(result);
|
||||
break;
|
||||
|
||||
case P3D_RT_script:
|
||||
handle_script_request(result);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Other kinds of requests don't require special handling at
|
||||
// this level; pass it up unmolested.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -422,6 +450,100 @@ make_xml() {
|
|||
return xinstance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::send_browser_script_object
|
||||
// Access: Private
|
||||
// Description: Sends the XML sequence to inform the session of our
|
||||
// browser's toplevel window object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
send_browser_script_object() {
|
||||
TiXmlDocument *doc = new TiXmlDocument;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||
TiXmlElement *xcommand = new TiXmlElement("command");
|
||||
xcommand->SetAttribute("cmd", "pyobj");
|
||||
xcommand->SetAttribute("op", "set_browser_script_object");
|
||||
if (_browser_script_object != NULL) {
|
||||
xcommand->LinkEndChild(_session->object_to_xml(_browser_script_object));
|
||||
}
|
||||
|
||||
doc->LinkEndChild(decl);
|
||||
doc->LinkEndChild(xcommand);
|
||||
|
||||
_session->send_command(doc);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::handle_notify_request
|
||||
// Access: Private
|
||||
// Description: Called (in the main thread) when a notify request is
|
||||
// received from the subprocess.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
handle_notify_request(P3D_request *request) {
|
||||
assert(request->_request_type == P3D_RT_notify);
|
||||
|
||||
// We look for certain notify events that have particular meaning
|
||||
// to this instance.
|
||||
const char *message = request->_request._notify._message;
|
||||
if (strcmp(message, "onwindowopen") == 0) {
|
||||
// The process told us that it just succesfully opened its
|
||||
// window.
|
||||
nout << "Instance " << this << " got onwindowopen\n" << flush;
|
||||
_instance_window_opened = true;
|
||||
if (_splash_window != NULL) {
|
||||
nout << "Deleting splash window\n" << flush;
|
||||
delete _splash_window;
|
||||
_splash_window = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::handle_script_request
|
||||
// Access: Private
|
||||
// Description: Called (in the main thread) when a script request is
|
||||
// received from the subprocess.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
handle_script_request(P3D_request *request) {
|
||||
assert(request->_request_type == P3D_RT_script);
|
||||
|
||||
P3D_object *object = request->_request._script._object;
|
||||
int unique_id = request->_request._script._unique_id;
|
||||
switch (request->_request._script._op) {
|
||||
case P3D_SO_get_property:
|
||||
{
|
||||
P3D_object *value = P3D_OBJECT_GET_PROPERTY(object, request->_request._script._property_name);
|
||||
nout << "get_property, object = " << object << "\n";
|
||||
if (object != NULL) {
|
||||
nout << " *object = " << *object << "\n" << flush;
|
||||
}
|
||||
nout << "value = " << value << "\n" << flush;
|
||||
if (value != NULL) {
|
||||
nout << " *value = " << *value << "\n" << flush;
|
||||
}
|
||||
// We've got the property value; feed it back down to the
|
||||
// subprocess.
|
||||
TiXmlDocument *doc = new TiXmlDocument;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||
TiXmlElement *xcommand = new TiXmlElement("command");
|
||||
xcommand->SetAttribute("cmd", "script_response");
|
||||
xcommand->SetAttribute("unique_id", unique_id);
|
||||
|
||||
doc->LinkEndChild(decl);
|
||||
doc->LinkEndChild(xcommand);
|
||||
if (value != NULL) {
|
||||
xcommand->LinkEndChild(_session->object_to_xml(value));
|
||||
P3D_OBJECT_FINISH(value);
|
||||
}
|
||||
|
||||
_session->send_command(doc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::make_splash_window
|
||||
// Access: Private
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ public:
|
|||
void set_wparams(const P3DWindowParams &wparams);
|
||||
inline const P3DWindowParams &get_wparams() const;
|
||||
|
||||
P3DObject *get_script_object() const;
|
||||
P3DObject *get_panda_script_object() const;
|
||||
void set_browser_script_object(P3D_object *object);
|
||||
|
||||
bool has_request();
|
||||
P3D_request *get_request();
|
||||
|
|
@ -86,10 +87,14 @@ private:
|
|||
P3DInstance *_inst;
|
||||
};
|
||||
|
||||
void send_browser_script_object();
|
||||
void handle_notify_request(P3D_request *request);
|
||||
void handle_script_request(P3D_request *request);
|
||||
void make_splash_window();
|
||||
void install_progress(P3DPackage *package, double progress);
|
||||
|
||||
P3D_request_ready_func *_func;
|
||||
P3D_object *_browser_script_object;
|
||||
|
||||
bool _got_fparams;
|
||||
P3DFileParams _fparams;
|
||||
|
|
|
|||
|
|
@ -301,8 +301,9 @@ signal_request_ready(P3DInstance *inst) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
P3D_class_definition *P3DInstanceManager::
|
||||
make_class_definition() const {
|
||||
// TODO.
|
||||
return NULL;
|
||||
P3D_class_definition *new_class = new P3D_class_definition(P3DObject::_generic_class);
|
||||
// TODO: save this pointer so we can delete it on destruction.
|
||||
return new_class;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -80,17 +80,3 @@ make_string(string &value) const {
|
|||
value = strm.str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DIntObject::make_xml
|
||||
// Access: Public, Virtual
|
||||
// Description: Allocates and returns a new XML structure
|
||||
// corresponding to this value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TiXmlElement *P3DIntObject::
|
||||
make_xml() const {
|
||||
TiXmlElement *xvalue = new TiXmlElement("value");
|
||||
xvalue->SetAttribute("type", "int");
|
||||
xvalue->SetAttribute("value", _value);
|
||||
return xvalue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ public:
|
|||
virtual int get_int() const;
|
||||
virtual void make_string(string &value) const;
|
||||
|
||||
virtual TiXmlElement *make_xml() const;
|
||||
|
||||
private:
|
||||
int _value;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,16 +54,3 @@ void P3DNoneObject::
|
|||
make_string(string &value) const {
|
||||
value = "None";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DNoneObject::make_xml
|
||||
// Access: Public, Virtual
|
||||
// Description: Allocates and returns a new XML structure
|
||||
// corresponding to this value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TiXmlElement *P3DNoneObject::
|
||||
make_xml() const {
|
||||
TiXmlElement *xvalue = new TiXmlElement("value");
|
||||
xvalue->SetAttribute("type", "none");
|
||||
return xvalue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@ public:
|
|||
virtual P3D_object_type get_type() const;
|
||||
virtual bool get_bool() const;
|
||||
virtual void make_string(string &value) const;
|
||||
|
||||
virtual TiXmlElement *make_xml() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include "p3dObject.h"
|
||||
#include <string.h> // strncpy
|
||||
|
||||
// The following functions are C-style wrappers around the above
|
||||
// The following functions are C-style wrappers around the below
|
||||
// P3DObject virtual methods; they are defined to allow us to create
|
||||
// the C-style P3D_class_definition method table to store in the
|
||||
// P3D_object structure.
|
||||
|
|
@ -93,6 +93,93 @@ P3D_class_definition P3DObject::_object_class = {
|
|||
&object_call,
|
||||
};
|
||||
|
||||
// The next functions are used to construct the generic
|
||||
// P3D_class_definition class returned by P3D_make_class_definition().
|
||||
// These are pointers to no-op functions, which the host may or may
|
||||
// not choose to override.
|
||||
static void
|
||||
generic_finish(P3D_object *object) {
|
||||
// You must override finish(), though, otherwise it's a leak. The
|
||||
// core API has no idea how to delete your object.
|
||||
nout << "Warning! default object_finish() method does nothing; object will leak.\n" << flush;
|
||||
}
|
||||
|
||||
static P3D_object *
|
||||
generic_copy(const P3D_object *object) {
|
||||
nout << "Warning! default object_copy() method does nothing; object pointer will be shared.\n" << flush;
|
||||
return (P3D_object *)object;
|
||||
}
|
||||
|
||||
static P3D_object_type
|
||||
generic_get_type(const P3D_object *object) {
|
||||
// We assume anyone going through the trouble of subclassing this
|
||||
// will want to return an object, not one of the other fundamental
|
||||
// types.
|
||||
return P3D_OT_object;
|
||||
}
|
||||
|
||||
static bool
|
||||
generic_get_bool(const P3D_object *object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
generic_get_int(const P3D_object *object) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static double
|
||||
generic_get_float(const P3D_object *object) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static int
|
||||
generic_get_string(const P3D_object *object, char *buffer, int buffer_length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
generic_get_repr(const P3D_object *object, char *buffer, int buffer_length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static P3D_object *
|
||||
generic_get_property(const P3D_object *object, const char *property) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
generic_set_property(P3D_object *object, const char *property,
|
||||
P3D_object *value) {
|
||||
if (value != NULL) {
|
||||
P3D_OBJECT_FINISH(value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static P3D_object *
|
||||
generic_call(const P3D_object *object, const char *method_name,
|
||||
P3D_object *params[], int num_params) {
|
||||
for (int i = 0; i < num_params; ++i) {
|
||||
P3D_OBJECT_FINISH(params[i]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
P3D_class_definition P3DObject::_generic_class = {
|
||||
&generic_finish,
|
||||
&generic_copy,
|
||||
&generic_get_type,
|
||||
&generic_get_bool,
|
||||
&generic_get_int,
|
||||
&generic_get_float,
|
||||
&generic_get_string,
|
||||
&generic_get_repr,
|
||||
&generic_get_property,
|
||||
&generic_set_property,
|
||||
&generic_call,
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DObject::Destructor
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -49,8 +49,6 @@ public:
|
|||
virtual P3D_object *call(const string &method_name,
|
||||
P3D_object *params[], int num_params) const;
|
||||
|
||||
virtual TiXmlElement *make_xml() const=0;
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
inline void ref() const;
|
||||
|
|
@ -62,28 +60,19 @@ private:
|
|||
|
||||
public:
|
||||
static P3D_class_definition _object_class;
|
||||
static P3D_class_definition _generic_class;
|
||||
};
|
||||
|
||||
#include "p3dObject.I"
|
||||
|
||||
// For classes that inherit from P3DObject, above, we can use the
|
||||
// virtual method to write the output simply.
|
||||
// virtual method to write the output simply. (For classes that
|
||||
// inherit only from P3D_object, we have to use the generic C method
|
||||
// defined in p3d_plugin_common.h, a little clumsier.)
|
||||
inline ostream &operator << (ostream &out, const P3DObject &value) {
|
||||
value.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// For classes that inherit only from P3D_object, we have to use the
|
||||
// generic C method, a little clumsier.
|
||||
inline ostream &operator << (ostream &out, const P3D_object &value) {
|
||||
int size = P3D_OBJECT_GET_REPR(&value, NULL, 0);
|
||||
char *buffer = new char[size];
|
||||
P3D_OBJECT_GET_REPR(&value, buffer, size);
|
||||
out.write(buffer, size);
|
||||
delete[] buffer;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -194,8 +194,7 @@ call(const string &method_name, P3D_object *params[], int num_params) const {
|
|||
}
|
||||
|
||||
for (int i = 0; i < num_params; ++i) {
|
||||
assert(params[i]->_class == &P3DObject::_object_class);
|
||||
TiXmlElement *xparams = ((P3DObject *)params[i])->make_xml();
|
||||
TiXmlElement *xparams = _session->object_to_xml(params[i]);
|
||||
xcommand->LinkEndChild(xparams);
|
||||
|
||||
// Now we're done with the params object passed in, we can delete
|
||||
|
|
@ -244,18 +243,14 @@ output(ostream &out) const {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonObject::make_xml
|
||||
// Access: Public, Virtual
|
||||
// Description: Allocates and returns a new XML structure
|
||||
// corresponding to this value.
|
||||
// Function: P3DPythonObject::get_object_id
|
||||
// Access: Public
|
||||
// Description: Returns the object_id number that is used to uniquely
|
||||
// identify this object in the XML stream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TiXmlElement *P3DPythonObject::
|
||||
make_xml() const {
|
||||
TiXmlElement *xvalue = new TiXmlElement("value");
|
||||
xvalue->SetAttribute("type", "python");
|
||||
xvalue->SetAttribute("object_id", _object_id);
|
||||
|
||||
return xvalue;
|
||||
int P3DPythonObject::
|
||||
get_object_id() const {
|
||||
return _object_id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,9 +47,8 @@ public:
|
|||
virtual P3D_object *call(const string &method_name,
|
||||
P3D_object *params[], int num_params) const;
|
||||
|
||||
virtual TiXmlElement *make_xml() const;
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
int get_object_id() const;
|
||||
|
||||
private:
|
||||
P3DSession *_session;
|
||||
|
|
|
|||
|
|
@ -112,19 +112,26 @@ run_python() {
|
|||
}
|
||||
|
||||
// Get the pointers to the objects needed within the module.
|
||||
PyObject *AppRunner = PyObject_GetAttrString(runp3d, "AppRunner");
|
||||
if (AppRunner == NULL) {
|
||||
PyObject *app_runner_class = PyObject_GetAttrString(runp3d, "AppRunner");
|
||||
if (app_runner_class == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Construct an instance of AppRunner.
|
||||
_runner = PyObject_CallFunction(AppRunner, (char*) "");
|
||||
_runner = PyObject_CallFunction(app_runner_class, (char *)"");
|
||||
if (_runner == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
Py_DECREF(AppRunner);
|
||||
Py_DECREF(app_runner_class);
|
||||
|
||||
// Get the BrowserObject class.
|
||||
_browser_object_class = PyObject_GetAttrString(runp3d, "BrowserObject");
|
||||
if (_browser_object_class == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the global TaskManager.
|
||||
_taskMgr = PyObject_GetAttrString(runp3d, "taskMgr");
|
||||
|
|
@ -139,7 +146,7 @@ run_python() {
|
|||
// Construct a Python wrapper around our request_func() method.
|
||||
static PyMethodDef p3dpython_methods[] = {
|
||||
{"request_func", P3DPythonRun::st_request_func, METH_VARARGS,
|
||||
"Check for communications to and from the plugin host."},
|
||||
"Send an asynchronous request to the plugin host"},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
PyObject *p3dpython = Py_InitModule("p3dpython", p3dpython_methods);
|
||||
|
|
@ -155,7 +162,7 @@ run_python() {
|
|||
|
||||
// Now pass that func pointer back to our AppRunner instance, so it
|
||||
// can call up to us.
|
||||
PyObject *result = PyObject_CallMethod(_runner, (char*) "setRequestFunc", (char*) "O", request_func);
|
||||
PyObject *result = PyObject_CallMethod(_runner, (char *)"setRequestFunc", (char *)"O", request_func);
|
||||
if (result == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
|
|
@ -171,7 +178,7 @@ run_python() {
|
|||
|
||||
// Finally, get lost in taskMgr.run().
|
||||
nout << "calling run()\n";
|
||||
PyObject *done = PyObject_CallMethod(_taskMgr, (char*) "run", (char*) "");
|
||||
PyObject *done = PyObject_CallMethod(_taskMgr, (char *)"run", (char *)"");
|
||||
if (done == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
|
|
@ -231,11 +238,13 @@ handle_command(TiXmlDocument *doc) {
|
|||
terminate_session();
|
||||
|
||||
} else if (strcmp(cmd, "pyobj") == 0) {
|
||||
// Manipulate or query a python object. Presumably this
|
||||
// command will want a response.
|
||||
assert(needs_response);
|
||||
// Manipulate or query a python object.
|
||||
handle_pyobj_command(xcommand, needs_response, want_response_id);
|
||||
|
||||
handle_pyobj_command(xcommand, want_response_id);
|
||||
} else if (strcmp(cmd, "script_response") == 0) {
|
||||
// Response from a script request.
|
||||
assert(!needs_response);
|
||||
handle_script_response_command(xcommand);
|
||||
|
||||
} else {
|
||||
nout << "Unhandled command " << cmd << "\n";
|
||||
|
|
@ -262,7 +271,8 @@ handle_command(TiXmlDocument *doc) {
|
|||
// a Python object from the browser scripts.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DPythonRun::
|
||||
handle_pyobj_command(TiXmlElement *xcommand, int want_response_id) {
|
||||
handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
||||
int want_response_id) {
|
||||
TiXmlDocument doc;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||
TiXmlElement *xresponse = new TiXmlElement("response");
|
||||
|
|
@ -272,13 +282,30 @@ handle_pyobj_command(TiXmlElement *xcommand, int want_response_id) {
|
|||
|
||||
const char *op = xcommand->Attribute("op");
|
||||
if (op != NULL) {
|
||||
if (strcmp(op, "get_script_object") == 0) {
|
||||
// Get the toplevel Python object.
|
||||
if (strcmp(op, "get_panda_script_object") == 0) {
|
||||
// Get Panda's toplevel Python object.
|
||||
PyObject *obj = PyObject_GetAttrString(_runner, "scriptRoot");
|
||||
if (obj != NULL) {
|
||||
xresponse->LinkEndChild(pyobj_to_xml(obj));
|
||||
Py_DECREF(obj);
|
||||
}
|
||||
|
||||
} else if (strcmp(op, "set_browser_script_object") == 0) {
|
||||
// Set the Browser's toplevel window object.
|
||||
PyObject *obj;
|
||||
TiXmlElement *xvalue = xcommand->FirstChildElement("value");
|
||||
if (xvalue != NULL) {
|
||||
obj = xml_to_pyobj(xvalue);
|
||||
} else {
|
||||
obj = Py_None;
|
||||
Py_INCREF(obj);
|
||||
}
|
||||
|
||||
PyObject *result = PyObject_CallMethod
|
||||
(_runner, (char *)"setBrowserScriptObject", (char *)"O", obj);
|
||||
Py_DECREF(obj);
|
||||
Py_XDECREF(result);
|
||||
|
||||
} else if (strcmp(op, "call") == 0) {
|
||||
// Call the named method on the indicated object, or the object
|
||||
// itself if method_name isn't given.
|
||||
|
|
@ -375,8 +402,35 @@ handle_pyobj_command(TiXmlElement *xcommand, int want_response_id) {
|
|||
}
|
||||
}
|
||||
|
||||
nout << "sending " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
if (needs_response) {
|
||||
nout << "sending " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::handle_script_response_command
|
||||
// Access: Private
|
||||
// Description: Handles the script_response command, a response from
|
||||
// the browser to a previous script request from this
|
||||
// process.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DPythonRun::
|
||||
handle_script_response_command(TiXmlElement *xcommand) {
|
||||
int unique_id;
|
||||
if (xcommand->QueryIntAttribute("unique_id", &unique_id) == TIXML_SUCCESS) {
|
||||
PyObject *value = NULL;
|
||||
TiXmlElement *xvalue = xcommand->FirstChildElement("value");
|
||||
if (xvalue != NULL) {
|
||||
value = xml_to_pyobj(xvalue);
|
||||
} else {
|
||||
value = Py_None;
|
||||
Py_INCREF(value);
|
||||
}
|
||||
PyObject *result = PyObject_CallMethod
|
||||
(_runner, (char *)"scriptResponse", (char *)"iO", unique_id, value);
|
||||
Py_DECREF(value);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -459,6 +513,30 @@ py_request_func(PyObject *args) {
|
|||
nout << "sending " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
|
||||
} else if (strcmp(request_type, "script") == 0) {
|
||||
// Meddling with a scripting variable on the browser side.
|
||||
const char *operation;
|
||||
PyObject *object;
|
||||
const char *property_name;
|
||||
PyObject *value;
|
||||
int unique_id;
|
||||
if (!PyArg_ParseTuple(extra_args, "sOsOi",
|
||||
&operation, &object, &property_name, &value, &unique_id)) {
|
||||
return NULL;
|
||||
}
|
||||
xrequest->SetAttribute("operation", operation);
|
||||
xrequest->SetAttribute("property_name", property_name);
|
||||
xrequest->SetAttribute("unique_id", unique_id);
|
||||
TiXmlElement *xobject = pyobj_to_xml(object);
|
||||
xobject->SetValue("object");
|
||||
xrequest->LinkEndChild(xobject);
|
||||
TiXmlElement *xvalue = pyobj_to_xml(value);
|
||||
xrequest->LinkEndChild(xvalue);
|
||||
|
||||
nout << "sending " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
|
||||
/*
|
||||
} else if (strcmp(request_type, "evaluate") == 0) {
|
||||
// An evaluate request.
|
||||
const char *expression;
|
||||
|
|
@ -471,6 +549,7 @@ py_request_func(PyObject *args) {
|
|||
xrequest->SetAttribute("unique_id", unique_id);
|
||||
nout << "sending " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
*/
|
||||
|
||||
} else {
|
||||
string message = string("Unsupported request type: ") + string(request_type);
|
||||
|
|
@ -610,7 +689,7 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
|
|||
}
|
||||
|
||||
PyObject *result = PyObject_CallMethod
|
||||
(_runner, (char*) "setP3DFilename", (char*) "sOi", p3d_filename.c_str(),
|
||||
(_runner, (char *)"setP3DFilename", (char *)"sOi", p3d_filename.c_str(),
|
||||
token_list, inst->get_instance_id());
|
||||
Py_DECREF(token_list);
|
||||
|
||||
|
|
@ -669,7 +748,7 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
|
|||
// TODO: direct this into the particular instance. This will
|
||||
// require a specialized ShowBase replacement.
|
||||
PyObject *result = PyObject_CallMethod
|
||||
(_runner, (char*)"setupWindow", (char*)"siiiii", window_type.c_str(),
|
||||
(_runner, (char *)"setupWindow", (char *)"siiiii", window_type.c_str(),
|
||||
win_x, win_y, win_width, win_height,
|
||||
parent_window_handle);
|
||||
if (result == NULL) {
|
||||
|
|
@ -694,7 +773,7 @@ terminate_session() {
|
|||
_instances.clear();
|
||||
|
||||
nout << "calling stop()\n";
|
||||
PyObject *result = PyObject_CallMethod(_taskMgr, (char*) "stop", (char*) "");
|
||||
PyObject *result = PyObject_CallMethod(_taskMgr, (char *)"stop", (char *)"");
|
||||
if (result == NULL) {
|
||||
PyErr_Print();
|
||||
return;
|
||||
|
|
@ -772,15 +851,28 @@ pyobj_to_xml(PyObject *value) {
|
|||
xvalue->SetAttribute("value", str);
|
||||
}
|
||||
|
||||
} else if (PyObject_IsInstance(value, _browser_object_class)) {
|
||||
// This is a BrowserObject, a reference to an object that actually
|
||||
// exists in the host namespace. So, pass up the appropriate
|
||||
// object ID.
|
||||
PyObject *objectId = PyObject_GetAttrString(value, (char *)"_BrowserObject__objectId");
|
||||
if (objectId != NULL) {
|
||||
int object_id = PyInt_AsLong(objectId);
|
||||
xvalue->SetAttribute("type", "browser");
|
||||
xvalue->SetAttribute("object_id", object_id);
|
||||
Py_DECREF(objectId);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Some other kind of object. Make it a generic Python object.
|
||||
// This is more expensive for the caller to deal with--it requires
|
||||
// a back-and-forth across the XML pipe--but it's much more
|
||||
// general.
|
||||
// TODO: pass pointers better.
|
||||
xvalue->SetAttribute("type", "python");
|
||||
xvalue->SetAttribute("object_id", (long)value);
|
||||
xvalue->SetAttribute("object_id", (int)value);
|
||||
|
||||
// Temporary hack.
|
||||
// TODO: fix this hack, properly manage these reference counts.
|
||||
Py_INCREF(value);
|
||||
}
|
||||
|
||||
|
|
@ -825,6 +917,13 @@ xml_to_pyobj(TiXmlElement *xvalue) {
|
|||
return PyString_FromStringAndSize(value->data(), value->length());
|
||||
}
|
||||
|
||||
} else if (strcmp(type, "browser") == 0) {
|
||||
int object_id;
|
||||
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
|
||||
// Construct a new BrowserObject wrapper around this object.
|
||||
return PyObject_CallFunction(_browser_object_class, (char *)"i", object_id);
|
||||
}
|
||||
|
||||
} else if (strcmp(type, "python") == 0) {
|
||||
int object_id;
|
||||
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,9 @@ public:
|
|||
|
||||
private:
|
||||
void handle_command(TiXmlDocument *doc);
|
||||
void handle_pyobj_command(TiXmlElement *xcommand, int want_response_id);
|
||||
void handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
||||
int want_response_id);
|
||||
void handle_script_response_command(TiXmlElement *xcommand);
|
||||
|
||||
AsyncTask::DoneStatus check_comm(GenericAsyncTask *task);
|
||||
static AsyncTask::DoneStatus st_check_comm(GenericAsyncTask *task, void *user_data);
|
||||
|
|
@ -107,6 +109,7 @@ private:
|
|||
char **_py_argv;
|
||||
|
||||
PyObject *_runner;
|
||||
PyObject *_browser_object_class;
|
||||
PyObject *_taskMgr;
|
||||
|
||||
PT(GenericAsyncTask) _check_comm_task;
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ start_instance(P3DInstance *inst) {
|
|||
xcommand->LinkEndChild(xinstance);
|
||||
|
||||
send_command(doc);
|
||||
inst->send_browser_script_object();
|
||||
|
||||
if (_panda3d->get_ready()) {
|
||||
// If it's ready immediately, go ahead and start.
|
||||
|
|
@ -212,6 +213,7 @@ void P3DSession::
|
|||
send_command(TiXmlDocument *command) {
|
||||
if (_p3dpython_running) {
|
||||
// Python is running. Send the command.
|
||||
nout << "Sending " << *command << "\n" << flush;
|
||||
_pipe_write << *command << flush;
|
||||
delete command;
|
||||
} else {
|
||||
|
|
@ -300,7 +302,7 @@ command_and_response(TiXmlDocument *command) {
|
|||
// Returns the newly-allocated object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DObject *P3DSession::
|
||||
xml_to_object(TiXmlElement *xvalue) {
|
||||
xml_to_object(const TiXmlElement *xvalue) {
|
||||
const char *type = xvalue->Attribute("type");
|
||||
if (strcmp(type, "none") == 0) {
|
||||
return new P3DNoneObject;
|
||||
|
|
@ -342,6 +344,75 @@ xml_to_object(TiXmlElement *xvalue) {
|
|||
return new P3DNoneObject;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::object_to_xml
|
||||
// Access: Public
|
||||
// Description: Allocates and returns a new XML structure
|
||||
// corresponding to the indicated value. The supplied
|
||||
// P3DObject passed in is *not* deleted.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TiXmlElement *P3DSession::
|
||||
object_to_xml(const P3D_object *obj) {
|
||||
TiXmlElement *xvalue = new TiXmlElement("value");
|
||||
|
||||
switch (P3D_OBJECT_GET_TYPE(obj)) {
|
||||
case P3D_OT_none:
|
||||
xvalue->SetAttribute("type", "none");
|
||||
break;
|
||||
|
||||
case P3D_OT_bool:
|
||||
xvalue->SetAttribute("type", "bool");
|
||||
xvalue->SetAttribute("value", (int)P3D_OBJECT_GET_BOOL(obj));
|
||||
break;
|
||||
|
||||
case P3D_OT_int:
|
||||
xvalue->SetAttribute("type", "int");
|
||||
xvalue->SetAttribute("value", P3D_OBJECT_GET_INT(obj));
|
||||
break;
|
||||
|
||||
case P3D_OT_float:
|
||||
xvalue->SetAttribute("type", "float");
|
||||
xvalue->SetDoubleAttribute("value", P3D_OBJECT_GET_FLOAT(obj));
|
||||
break;
|
||||
|
||||
case P3D_OT_string:
|
||||
{
|
||||
xvalue->SetAttribute("type", "string");
|
||||
int size = P3D_OBJECT_GET_STRING(obj, NULL, 0);
|
||||
char *buffer = new char[size];
|
||||
P3D_OBJECT_GET_STRING(obj, buffer, size);
|
||||
xvalue->SetAttribute("value", string(buffer, size));
|
||||
delete [] buffer;
|
||||
}
|
||||
break;
|
||||
|
||||
case P3D_OT_object:
|
||||
if (obj->_class == &P3DObject::_object_class) {
|
||||
// If it's one of our kind of objects, it must be a
|
||||
// P3DPythonObject. In this case, just send the object_id down,
|
||||
// since the actual implementation of this object exists (as a
|
||||
// Python object) in the sub-process space.
|
||||
int object_id = ((P3DPythonObject *)obj)->get_object_id();
|
||||
xvalue->SetAttribute("type", "python");
|
||||
xvalue->SetAttribute("object_id", object_id);
|
||||
|
||||
} else {
|
||||
// Otherwise, it must a host-provided object, which means we
|
||||
// should pass a reference down to this particular object, so
|
||||
// the Python process knows to call back up to here to query it.
|
||||
// TODO: pass pointers better.
|
||||
int object_id = (int)obj;
|
||||
xvalue->SetAttribute("type", "browser");
|
||||
xvalue->SetAttribute("object_id", object_id);
|
||||
|
||||
// TODO: manage this reference count somehow.
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return xvalue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::install_progress
|
||||
// Access: Private
|
||||
|
|
@ -584,6 +655,32 @@ rt_make_p3d_request(TiXmlElement *xrequest) {
|
|||
request->_request._notify._message = strdup(message);
|
||||
}
|
||||
|
||||
} else if (strcmp(rtype, "script") == 0) {
|
||||
const char *operation = xrequest->Attribute("operation");
|
||||
TiXmlElement *xobject = xrequest->FirstChildElement("object");
|
||||
const char *property_name = xrequest->Attribute("property_name");
|
||||
TiXmlElement *xvalue = xrequest->FirstChildElement("value");
|
||||
int unique_id = 0;
|
||||
xrequest->Attribute("unique_id", &unique_id);
|
||||
|
||||
if (operation != NULL && xobject != NULL) {
|
||||
P3D_object *object = xml_to_object(xobject);
|
||||
if (strcmp(operation, "get_property") == 0 && property_name != NULL) {
|
||||
request = new P3D_request;
|
||||
request->_request_type = P3D_RT_script;
|
||||
request->_request._script._object = object;
|
||||
request->_request._script._op = P3D_SO_get_property;
|
||||
request->_request._script._property_name = strdup(property_name);
|
||||
request->_request._script._value = NULL;
|
||||
request->_request._script._unique_id = unique_id;
|
||||
}
|
||||
if (request == NULL) {
|
||||
// If we haven't dispatched a request yet, we didn't use the
|
||||
// object, so delete it.
|
||||
P3D_OBJECT_FINISH(object);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
nout << "ignoring request of type " << rtype << "\n";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ public:
|
|||
|
||||
void send_command(TiXmlDocument *command);
|
||||
TiXmlDocument *command_and_response(TiXmlDocument *command);
|
||||
P3DObject *xml_to_object(TiXmlElement *xvalue);
|
||||
P3DObject *xml_to_object(const TiXmlElement *xvalue);
|
||||
TiXmlElement *object_to_xml(const P3D_object *obj);
|
||||
|
||||
private:
|
||||
void install_progress(P3DPackage *package, double progress);
|
||||
|
|
|
|||
|
|
@ -76,20 +76,6 @@ make_string(string &value) const {
|
|||
value = _value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DStringObject::make_xml
|
||||
// Access: Public, Virtual
|
||||
// Description: Allocates and returns a new XML structure
|
||||
// corresponding to this value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TiXmlElement *P3DStringObject::
|
||||
make_xml() const {
|
||||
TiXmlElement *xvalue = new TiXmlElement("value");
|
||||
xvalue->SetAttribute("type", "string");
|
||||
xvalue->SetAttribute("value", _value);
|
||||
return xvalue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DStringObject::output
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ public:
|
|||
virtual bool get_bool() const;
|
||||
virtual void make_string(string &value) const;
|
||||
|
||||
virtual TiXmlElement *make_xml() const;
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -188,23 +188,23 @@ P3D_new_string_object(const char *str, int length) {
|
|||
}
|
||||
|
||||
P3D_object *
|
||||
P3D_instance_get_script_object(P3D_instance *instance) {
|
||||
P3D_instance_get_panda_script_object(P3D_instance *instance) {
|
||||
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
|
||||
ACQUIRE_LOCK(_api_lock);
|
||||
|
||||
P3D_object *result = ((P3DInstance *)instance)->get_script_object();
|
||||
P3D_object *result = ((P3DInstance *)instance)->get_panda_script_object();
|
||||
|
||||
RELEASE_LOCK(_api_lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
P3D_instance_set_script_object(P3D_instance *instance,
|
||||
P3D_instance_set_browser_script_object(P3D_instance *instance,
|
||||
P3D_object *object) {
|
||||
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
|
||||
ACQUIRE_LOCK(_api_lock);
|
||||
|
||||
// TODO.
|
||||
((P3DInstance *)instance)->set_browser_script_object(object);
|
||||
|
||||
RELEASE_LOCK(_api_lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ struct _P3D_object {
|
|||
generic function pointers that have reasonable default behavior for
|
||||
all methods. The host should use this function to get a clean
|
||||
P3D_class_definition object before calling
|
||||
P3D_instance_set_script_object() (see below). Note that this
|
||||
P3D_instance_set_browser_script_object() (see below). Note that this
|
||||
pointer will automatically be freed when P3D_finalize() is
|
||||
called. */
|
||||
typedef P3D_class_definition *
|
||||
|
|
@ -481,7 +481,7 @@ P3D_new_string_object_func(const char *string, int length);
|
|||
ownership of the object is passed to the caller, who should be
|
||||
responsible for deleting it eventually. */
|
||||
typedef P3D_object *
|
||||
P3D_instance_get_script_object_func(P3D_instance *instance);
|
||||
P3D_instance_get_panda_script_object_func(P3D_instance *instance);
|
||||
|
||||
/* The inverse functionality: this supplies an object pointer to the
|
||||
instance to allow the Panda instance to control the browser. In
|
||||
|
|
@ -493,14 +493,14 @@ P3D_instance_get_script_object_func(P3D_instance *instance);
|
|||
have a custom P3D_class_definition pointer, which also must have
|
||||
been created by the host. The best way to create an appropriate
|
||||
class definition is call P3D_make_class_definition(), and then
|
||||
replace the function pointers for at least _finish, _get_property,
|
||||
_set_property, and _call. Set these pointers to the host's own
|
||||
functions that make the appropriate changes in the DOM, or invoke
|
||||
the appropriate JavaScript functions.
|
||||
replace the function pointers for at least _finish, _copy,
|
||||
_get_property, _set_property, and _call. Set these pointers to the
|
||||
host's own functions that make the appropriate changes in the DOM,
|
||||
or invoke the appropriate JavaScript functions.
|
||||
|
||||
If this function is never called, the instance will not be able to
|
||||
make outcalls to the DOM or to JavaScript, but scripts may still be
|
||||
able to control the instance via P3D_instance_get_script_object(),
|
||||
able to control the instance via P3D_instance_get_panda_script_object(),
|
||||
above.
|
||||
|
||||
Ownership of the object is passed into the instance. The caller
|
||||
|
|
@ -508,7 +508,7 @@ P3D_instance_get_script_object_func(P3D_instance *instance);
|
|||
or delete it. The instance will eventually delete it by calling
|
||||
its _finish method. */
|
||||
typedef void
|
||||
P3D_instance_set_script_object_func(P3D_instance *instance,
|
||||
P3D_instance_set_browser_script_object_func(P3D_instance *instance,
|
||||
P3D_object *object);
|
||||
|
||||
|
||||
|
|
@ -543,6 +543,7 @@ typedef enum {
|
|||
P3D_RT_get_url,
|
||||
P3D_RT_post_url,
|
||||
P3D_RT_notify,
|
||||
P3D_RT_script,
|
||||
} P3D_request_type;
|
||||
|
||||
/* Structures corresponding to the request types in the above enum. */
|
||||
|
|
@ -586,6 +587,23 @@ typedef struct {
|
|||
const char *_message;
|
||||
} P3D_request_notify;
|
||||
|
||||
/* A script object request. This is used to call out into the
|
||||
browser_script_object (above). This request is handled internally
|
||||
by the core API, and may safely be ignored by the host.
|
||||
*/
|
||||
typedef enum {
|
||||
P3D_SO_get_property,
|
||||
P3D_SO_set_property,
|
||||
P3D_SO_call,
|
||||
} P3D_script_operation;
|
||||
typedef struct {
|
||||
P3D_object *_object;
|
||||
P3D_script_operation _op;
|
||||
const char *_property_name;
|
||||
P3D_object *_value;
|
||||
int _unique_id;
|
||||
} P3D_request_script;
|
||||
|
||||
/* This is the overall structure that represents a single request. It
|
||||
is returned by P3D_instance_get_request(). */
|
||||
typedef struct {
|
||||
|
|
@ -596,6 +614,7 @@ typedef struct {
|
|||
P3D_request_get_url _get_url;
|
||||
P3D_request_post_url _post_url;
|
||||
P3D_request_notify _notify;
|
||||
P3D_request_script _script;
|
||||
} _request;
|
||||
} P3D_request;
|
||||
|
||||
|
|
@ -715,8 +734,8 @@ EXPCL_P3D_PLUGIN P3D_new_bool_object_func P3D_new_bool_object;
|
|||
EXPCL_P3D_PLUGIN P3D_new_int_object_func P3D_new_int_object;
|
||||
EXPCL_P3D_PLUGIN P3D_new_float_object_func P3D_new_float_object;
|
||||
EXPCL_P3D_PLUGIN P3D_new_string_object_func P3D_new_string_object;
|
||||
EXPCL_P3D_PLUGIN P3D_instance_get_script_object_func P3D_instance_get_script_object;
|
||||
EXPCL_P3D_PLUGIN P3D_instance_set_script_object_func P3D_instance_set_script_object;
|
||||
EXPCL_P3D_PLUGIN P3D_instance_get_panda_script_object_func P3D_instance_get_panda_script_object;
|
||||
EXPCL_P3D_PLUGIN P3D_instance_set_browser_script_object_func P3D_instance_set_browser_script_object;
|
||||
|
||||
EXPCL_P3D_PLUGIN P3D_instance_get_request_func P3D_instance_get_request;
|
||||
EXPCL_P3D_PLUGIN P3D_check_request_func P3D_check_request;
|
||||
|
|
|
|||
|
|
@ -39,5 +39,18 @@ extern string plugin_output_filename;
|
|||
extern ostream *nout_stream;
|
||||
#define nout (*nout_stream)
|
||||
|
||||
// A convenience function for formatting a generic P3D_object to an
|
||||
// ostream.
|
||||
inline ostream &
|
||||
operator << (ostream &out, const P3D_object &value) {
|
||||
int size = P3D_OBJECT_GET_REPR(&value, NULL, 0);
|
||||
char *buffer = new char[size];
|
||||
P3D_OBJECT_GET_REPR(&value, buffer, size);
|
||||
out.write(buffer, size);
|
||||
delete[] buffer;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -17,12 +17,14 @@
|
|||
|
||||
#define SOURCES \
|
||||
nppanda3d_common.h \
|
||||
ppBrowserObject.h ppBrowserObject.I \
|
||||
ppDownloadRequest.h ppDownloadRequest.I \
|
||||
ppInstance.h ppInstance.I \
|
||||
ppPandaObject.h ppPandaObject.I \
|
||||
startup.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
ppBrowserObject.cxx \
|
||||
ppDownloadRequest.cxx \
|
||||
ppInstance.cxx \
|
||||
ppPandaObject.cxx \
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include "ppBrowserObject.cxx"
|
||||
#include "ppDownloadRequest.cxx"
|
||||
#include "ppInstance.cxx"
|
||||
#include "ppPandaObject.cxx"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
// Filename: ppBrowserObject.I
|
||||
// Created by: drose (05Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
// Filename: ppBrowserObject.cxx
|
||||
// Created by: drose (05Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "ppBrowserObject.h"
|
||||
#include "ppInstance.h"
|
||||
#include <sstream>
|
||||
#include <string.h> // strncpy
|
||||
|
||||
// The following functions are C-style wrappers around the above
|
||||
// PPBrowserObject methods; they are defined to allow us to create the
|
||||
// C-style P3D_class_definition method table to store in the
|
||||
// P3D_object structure.
|
||||
static void
|
||||
object_finish(P3D_object *object) {
|
||||
delete ((PPBrowserObject *)object);
|
||||
}
|
||||
|
||||
static P3D_object *
|
||||
object_copy(const P3D_object *object) {
|
||||
return new PPBrowserObject(*(const PPBrowserObject *)object);
|
||||
}
|
||||
|
||||
static int
|
||||
object_get_repr(const P3D_object *object, char *buffer, int buffer_length) {
|
||||
return ((const PPBrowserObject *)object)->get_repr(buffer, buffer_length);
|
||||
}
|
||||
|
||||
static P3D_object *
|
||||
object_get_property(const P3D_object *object, const char *property) {
|
||||
return ((const PPBrowserObject *)object)->get_property(property);
|
||||
}
|
||||
|
||||
static bool
|
||||
object_set_property(P3D_object *object, const char *property,
|
||||
P3D_object *value) {
|
||||
return ((PPBrowserObject *)object)->set_property(property, value);
|
||||
}
|
||||
|
||||
static P3D_object *
|
||||
object_call(const P3D_object *object, const char *method_name,
|
||||
P3D_object *params[], int num_params) {
|
||||
if (method_name == NULL) {
|
||||
method_name = "";
|
||||
}
|
||||
return ((const PPBrowserObject *)object)->call(method_name, params, num_params);
|
||||
}
|
||||
|
||||
P3D_class_definition *PPBrowserObject::_browser_object_class;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPBrowserObject::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPBrowserObject::
|
||||
PPBrowserObject(PPInstance *inst, NPObject *npobj) :
|
||||
_instance(inst),
|
||||
_npobj(npobj)
|
||||
{
|
||||
_class = get_class_definition();
|
||||
browser->retainobject(_npobj);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPBrowserObject::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPBrowserObject::
|
||||
PPBrowserObject(const PPBrowserObject ©) :
|
||||
_instance(copy._instance),
|
||||
_npobj(copy._npobj)
|
||||
{
|
||||
_class = get_class_definition();
|
||||
browser->retainobject(_npobj);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPBrowserObject::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPBrowserObject::
|
||||
~PPBrowserObject() {
|
||||
browser->releaseobject(_npobj);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPBrowserObject::get_repr
|
||||
// Access: Public
|
||||
// Description: Returns a user-friendly representation of the object,
|
||||
// similar to get_string(), above.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PPBrowserObject::
|
||||
get_repr(char *buffer, int buffer_length) const {
|
||||
ostringstream strm;
|
||||
strm << "NPObject " << _npobj;
|
||||
string result = strm.str();
|
||||
strncpy(buffer, result.c_str(), buffer_length);
|
||||
return (int)result.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPBrowserObject::get_property
|
||||
// Access: Public
|
||||
// Description: Returns the named property element in the object. The
|
||||
// return value is a freshly-allocated PPBrowserObject object
|
||||
// that must be deleted by the caller, or NULL on error.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_object *PPBrowserObject::
|
||||
get_property(const string &property) const {
|
||||
NPIdentifier property_name = browser->getstringidentifier(property.c_str());
|
||||
NPVariant result;
|
||||
if (!browser->getproperty(_instance->get_npp_instance(), _npobj,
|
||||
property_name, &result)) {
|
||||
// Failed to retrieve property.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
P3D_object *object = _instance->variant_to_object(&result);
|
||||
browser->releasevariantvalue(&result);
|
||||
return object;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPBrowserObject::set_property
|
||||
// Access: Public
|
||||
// Description: Modifies (or deletes, if value is NULL) the named
|
||||
// property element in the object. Returns true on
|
||||
// success, false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPBrowserObject::
|
||||
set_property(const string &property, P3D_object *value) {
|
||||
if (value != NULL) {
|
||||
P3D_OBJECT_FINISH(value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPBrowserObject::call
|
||||
// Access: Public
|
||||
// Description: Invokes the named method on the object, passing the
|
||||
// indicated parameters. If the method name is empty,
|
||||
// invokes the object itself. Returns the return value
|
||||
// on success, NULL on error.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_object *PPBrowserObject::
|
||||
call(const string &method_name, P3D_object *params[], int num_params) const {
|
||||
for (int i = 0; i < num_params; ++i) {
|
||||
P3D_OBJECT_FINISH(params[i]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPBrowserObject::get_class_definition
|
||||
// Access: Private, Static
|
||||
// Description: Returns a pointer to the P3D_class_definition object
|
||||
// that lists all of the C-style method pointers for
|
||||
// this class object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_class_definition *PPBrowserObject::
|
||||
get_class_definition() {
|
||||
if (_browser_object_class == NULL) {
|
||||
// Create a default class_definition object, and fill in the
|
||||
// appropriate pointers.
|
||||
_browser_object_class = P3D_make_class_definition();
|
||||
_browser_object_class->_finish = &object_finish;
|
||||
_browser_object_class->_copy = &object_copy;
|
||||
|
||||
_browser_object_class->_get_repr = &object_get_repr;
|
||||
_browser_object_class->_get_property = &object_get_property;
|
||||
_browser_object_class->_set_property = &object_set_property;
|
||||
_browser_object_class->_call = &object_call;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// Filename: ppBrowserObject.h
|
||||
// Created by: drose (05Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 PPBROWSEROBJECT_H
|
||||
#define PPBROWSEROBJECT_H
|
||||
|
||||
#include "nppanda3d_common.h"
|
||||
|
||||
class PPInstance;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PPBrowserObject
|
||||
// Description : This is the interface layer between an NPObject and a
|
||||
// P3D_object. It maps calls from P3D_object into the
|
||||
// NPObject system, thus allowing Panda to view and
|
||||
// operate on a browser object.
|
||||
//
|
||||
// Also see PPPandaObject, which maps calls the other
|
||||
// way.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class PPBrowserObject : public P3D_object {
|
||||
public:
|
||||
PPBrowserObject(PPInstance *inst, NPObject *npobj);
|
||||
PPBrowserObject(const PPBrowserObject ©);
|
||||
~PPBrowserObject();
|
||||
|
||||
int get_repr(char *buffer, int buffer_length) const;
|
||||
P3D_object *get_property(const string &property) const;
|
||||
bool set_property(const string &property, P3D_object *value);
|
||||
|
||||
P3D_object *call(const string &method_name,
|
||||
P3D_object *params[], int num_params) const;
|
||||
|
||||
private:
|
||||
static P3D_class_definition *get_class_definition();
|
||||
|
||||
private:
|
||||
PPInstance *_instance;
|
||||
NPObject *_npobj;
|
||||
static P3D_class_definition *_browser_object_class;
|
||||
};
|
||||
|
||||
#include "ppBrowserObject.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "ppInstance.h"
|
||||
#include "ppPandaObject.h"
|
||||
#include "ppBrowserObject.h"
|
||||
#include "startup.h"
|
||||
#include "p3d_plugin_config.h"
|
||||
#include "find_root_dir.h"
|
||||
|
|
@ -399,7 +400,7 @@ handle_request(P3D_request *request) {
|
|||
strcmp(request->_request._notify._message, "onpythonload") == 0) {
|
||||
// Now that Python is running, initialize our script_object
|
||||
// with the proper P3D object pointer.
|
||||
P3D_object *obj = P3D_instance_get_script_object(_p3d_inst);
|
||||
P3D_object *obj = P3D_instance_get_panda_script_object(_p3d_inst);
|
||||
logfile << "late obj = " << obj << "\n" << flush;
|
||||
_script_object->set_p3d_object(obj);
|
||||
}
|
||||
|
|
@ -416,14 +417,14 @@ handle_request(P3D_request *request) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::get_script_object
|
||||
// Function: PPInstance::get_panda_script_object
|
||||
// Access: Public
|
||||
// Description: Returns a toplevel object that JavaScript or whatever
|
||||
// can read and/or modify to control the instance.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NPObject *PPInstance::
|
||||
get_script_object() {
|
||||
logfile << "get_script_object\n" << flush;
|
||||
get_panda_script_object() {
|
||||
logfile << "get_panda_script_object\n" << flush;
|
||||
if (_script_object != NULL) {
|
||||
logfile << "returning _script_object ref = " << _script_object->referenceCount << "\n";
|
||||
return _script_object;
|
||||
|
|
@ -432,7 +433,7 @@ get_script_object() {
|
|||
P3D_object *obj = NULL;
|
||||
|
||||
if (_p3d_inst != NULL) {
|
||||
obj = P3D_instance_get_script_object(_p3d_inst);
|
||||
obj = P3D_instance_get_panda_script_object(_p3d_inst);
|
||||
logfile << "obj = " << obj << "\n" << flush;
|
||||
}
|
||||
|
||||
|
|
@ -444,6 +445,80 @@ get_script_object() {
|
|||
return _script_object;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::object_to_variant
|
||||
// Access: Private
|
||||
// Description: Converts the indicated P3D_object to the equivalent
|
||||
// NPVariant, and stores it in result.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPInstance::
|
||||
object_to_variant(NPVariant *result, const P3D_object *object) {
|
||||
switch (P3D_OBJECT_GET_TYPE(object)) {
|
||||
case P3D_OT_none:
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
break;
|
||||
|
||||
case P3D_OT_bool:
|
||||
BOOLEAN_TO_NPVARIANT(P3D_OBJECT_GET_BOOL(object), *result);
|
||||
break;
|
||||
|
||||
case P3D_OT_int:
|
||||
INT32_TO_NPVARIANT(P3D_OBJECT_GET_INT(object), *result);
|
||||
break;
|
||||
|
||||
case P3D_OT_float:
|
||||
DOUBLE_TO_NPVARIANT(P3D_OBJECT_GET_FLOAT(object), *result);
|
||||
break;
|
||||
|
||||
case P3D_OT_string:
|
||||
{
|
||||
int size = P3D_OBJECT_GET_STRING(object, NULL, 0);
|
||||
char *buffer = (char *)browser->memalloc(size);
|
||||
P3D_OBJECT_GET_STRING(object, buffer, size);
|
||||
STRINGN_TO_NPVARIANT(buffer, size, *result);
|
||||
}
|
||||
break;
|
||||
|
||||
case P3D_OT_object:
|
||||
{
|
||||
PPPandaObject *ppobj = PPPandaObject::make_new(this, P3D_OBJECT_COPY(object));
|
||||
OBJECT_TO_NPVARIANT(ppobj, *result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::variant_to_object
|
||||
// Access: Private
|
||||
// Description: Converts the indicated NPVariant to the equivalent
|
||||
// P3D_object, and returns it (newly-allocated). The
|
||||
// caller is responsible for freeing the returned object
|
||||
// later.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_object *PPInstance::
|
||||
variant_to_object(const NPVariant *variant) {
|
||||
if (NPVARIANT_IS_VOID(*variant) ||
|
||||
NPVARIANT_IS_NULL(*variant)) {
|
||||
return P3D_new_none_object();
|
||||
} else if (NPVARIANT_IS_BOOLEAN(*variant)) {
|
||||
return P3D_new_bool_object(NPVARIANT_TO_BOOLEAN(*variant));
|
||||
} else if (NPVARIANT_IS_INT32(*variant)) {
|
||||
return P3D_new_int_object(NPVARIANT_TO_INT32(*variant));
|
||||
} else if (NPVARIANT_IS_DOUBLE(*variant)) {
|
||||
return P3D_new_float_object(NPVARIANT_TO_DOUBLE(*variant));
|
||||
} else if (NPVARIANT_IS_STRING(*variant)) {
|
||||
NPString str = NPVARIANT_TO_STRING(*variant);
|
||||
return P3D_new_string_object(str.utf8characters, str.utf8length);
|
||||
} else if (NPVARIANT_IS_OBJECT(*variant)) {
|
||||
// TODO.
|
||||
return P3D_new_none_object();
|
||||
}
|
||||
|
||||
// Hmm, none of the above?
|
||||
return P3D_new_none_object();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::read_contents_file
|
||||
// Access: Private
|
||||
|
|
@ -619,6 +694,18 @@ create_instance() {
|
|||
_p3d_inst = P3D_new_instance(request_ready, this);
|
||||
|
||||
if (_p3d_inst != NULL) {
|
||||
// Now get the browser's window object, to pass to the plugin.
|
||||
NPObject *window_object = NULL;
|
||||
if (browser->getvalue(_npp_instance, NPNVWindowNPObject,
|
||||
&window_object) == NPERR_NO_ERROR) {
|
||||
logfile << "Got window_object " << window_object << "\n" << flush;
|
||||
PPBrowserObject *pobj = new PPBrowserObject(this, window_object);
|
||||
P3D_instance_set_browser_script_object(_p3d_inst, pobj);
|
||||
browser->releaseobject(window_object);
|
||||
} else {
|
||||
logfile << "Couldn't get window_object\n" << flush;
|
||||
}
|
||||
|
||||
const P3D_token *tokens = NULL;
|
||||
if (!_tokens.empty()) {
|
||||
tokens = &_tokens[0];
|
||||
|
|
|
|||
|
|
@ -48,7 +48,10 @@ public:
|
|||
|
||||
void handle_request(P3D_request *request);
|
||||
|
||||
NPObject *get_script_object();
|
||||
NPObject *get_panda_script_object();
|
||||
|
||||
void object_to_variant(NPVariant *result, const P3D_object *object);
|
||||
P3D_object *variant_to_object(const NPVariant *variant);
|
||||
|
||||
private:
|
||||
bool read_contents_file(const string &filename);
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ get_property(NPIdentifier name, NPVariant *result) {
|
|||
}
|
||||
|
||||
// We have the property, and its value is stored in value.
|
||||
object_to_variant(result, value);
|
||||
_instance->object_to_variant(result, value);
|
||||
P3D_OBJECT_FINISH(value);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -195,7 +195,7 @@ set_property(NPIdentifier name, const NPVariant *value) {
|
|||
return false;
|
||||
}
|
||||
|
||||
P3D_object *object = variant_to_object(value);
|
||||
P3D_object *object = _instance->variant_to_object(value);
|
||||
bool result = P3D_OBJECT_SET_PROPERTY(_p3d_object, property_name.c_str(), object);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -267,80 +267,6 @@ identifier_to_string(NPIdentifier ident) {
|
|||
return string();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPPandaObject::object_to_variant
|
||||
// Access: Private
|
||||
// Description: Converts the indicated P3D_object to the equivalent
|
||||
// NPVariant, and stores it in result.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPPandaObject::
|
||||
object_to_variant(NPVariant *result, const P3D_object *object) {
|
||||
switch (P3D_OBJECT_GET_TYPE(object)) {
|
||||
case P3D_OT_none:
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
break;
|
||||
|
||||
case P3D_OT_bool:
|
||||
BOOLEAN_TO_NPVARIANT(P3D_OBJECT_GET_BOOL(object), *result);
|
||||
break;
|
||||
|
||||
case P3D_OT_int:
|
||||
INT32_TO_NPVARIANT(P3D_OBJECT_GET_INT(object), *result);
|
||||
break;
|
||||
|
||||
case P3D_OT_float:
|
||||
DOUBLE_TO_NPVARIANT(P3D_OBJECT_GET_FLOAT(object), *result);
|
||||
break;
|
||||
|
||||
case P3D_OT_string:
|
||||
{
|
||||
int size = P3D_OBJECT_GET_STRING(object, NULL, 0);
|
||||
char *buffer = (char *)browser->memalloc(size);
|
||||
P3D_OBJECT_GET_STRING(object, buffer, size);
|
||||
STRINGN_TO_NPVARIANT(buffer, size, *result);
|
||||
}
|
||||
break;
|
||||
|
||||
case P3D_OT_object:
|
||||
{
|
||||
PPPandaObject *ppobj = PPPandaObject::make_new(_instance, P3D_OBJECT_COPY(object));
|
||||
OBJECT_TO_NPVARIANT(ppobj, *result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPPandaObject::variant_to_object
|
||||
// Access: Private
|
||||
// Description: Converts the indicated NPVariant to the equivalent
|
||||
// P3D_object, and returns it (newly-allocated). The
|
||||
// caller is responsible for freeing the returned object
|
||||
// later.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_object *PPPandaObject::
|
||||
variant_to_object(const NPVariant *variant) {
|
||||
if (NPVARIANT_IS_VOID(*variant) ||
|
||||
NPVARIANT_IS_NULL(*variant)) {
|
||||
return P3D_new_none_object();
|
||||
} else if (NPVARIANT_IS_BOOLEAN(*variant)) {
|
||||
return P3D_new_bool_object(NPVARIANT_TO_BOOLEAN(*variant));
|
||||
} else if (NPVARIANT_IS_INT32(*variant)) {
|
||||
return P3D_new_int_object(NPVARIANT_TO_INT32(*variant));
|
||||
} else if (NPVARIANT_IS_DOUBLE(*variant)) {
|
||||
return P3D_new_float_object(NPVARIANT_TO_DOUBLE(*variant));
|
||||
} else if (NPVARIANT_IS_STRING(*variant)) {
|
||||
NPString str = NPVARIANT_TO_STRING(*variant);
|
||||
return P3D_new_string_object(str.utf8characters, str.utf8length);
|
||||
} else if (NPVARIANT_IS_OBJECT(*variant)) {
|
||||
// TODO.
|
||||
return P3D_new_none_object();
|
||||
}
|
||||
|
||||
// Hmm, none of the above?
|
||||
return P3D_new_none_object();
|
||||
}
|
||||
|
||||
|
||||
// The remaining function bodies are the C-style function wrappers
|
||||
// that are called directly by NPAPI, and which redirect into the
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
// P3D_object. It maps calls from NPAPI into the
|
||||
// P3D_object system, thus allowing the browser to
|
||||
// view and operate on a Panda object.
|
||||
//
|
||||
// Also see PPBrowserObject, which maps calls the other
|
||||
// way.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class PPPandaObject : public NPObject {
|
||||
public:
|
||||
|
|
@ -51,8 +54,6 @@ private:
|
|||
|
||||
private:
|
||||
static string identifier_to_string(NPIdentifier ident);
|
||||
void object_to_variant(NPVariant *result, const P3D_object *object);
|
||||
P3D_object *variant_to_object(const NPVariant *variant);
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
|
|||
assert(inst != NULL);
|
||||
|
||||
if (variable == NPPVpluginScriptableNPObject) {
|
||||
NPObject *obj = inst->get_script_object();
|
||||
NPObject *obj = inst->get_panda_script_object();
|
||||
if (obj != NULL) {
|
||||
*(NPObject **)value = obj;
|
||||
return NPERR_NO_ERROR;
|
||||
|
|
|
|||
|
|
@ -409,7 +409,7 @@ handle_request(P3D_request *request) {
|
|||
/*
|
||||
{
|
||||
// Temporary.
|
||||
P3D_object *obj = P3D_instance_get_script_object(request->_instance);
|
||||
P3D_object *obj = P3D_instance_get_panda_script_object(request->_instance);
|
||||
cerr << "script_object is " << obj << "\n";
|
||||
if (obj != NULL) {
|
||||
if (P3D_OBJECT_SET_PROPERTY(obj, "foo", P3D_new_int_object(1))) {
|
||||
|
|
|
|||
|
|
@ -57,10 +57,16 @@ class AppRunner(DirectObject):
|
|||
self.started = False
|
||||
self.windowPrc = None
|
||||
|
||||
# This is per session.
|
||||
self.nextScriptId = 0
|
||||
|
||||
# TODO: we need one of these per instance, not per session.
|
||||
self.instanceId = None
|
||||
self.scriptRoot = ScriptRoot()
|
||||
|
||||
# This will be the browser's toplevel window DOM object.
|
||||
self.window = None
|
||||
|
||||
# This is the default requestFunc that is installed if we
|
||||
# never call setRequestFunc().
|
||||
def defaultRequestFunc(*args):
|
||||
|
|
@ -145,6 +151,13 @@ class AppRunner(DirectObject):
|
|||
if hasattr(main, 'main') and callable(main.main):
|
||||
main.main()
|
||||
|
||||
def setBrowserScriptObject(self, window):
|
||||
""" Replaces self.window with the browser's toplevel DOM
|
||||
object, for controlling the JavaScript and the document in the
|
||||
same page with the Panda3D plugin. """
|
||||
print "setBrowserScriptObject(%s)" % (window)
|
||||
self.window = window
|
||||
|
||||
def setP3DFilename(self, p3dFilename, tokens = [],
|
||||
instanceId = None):
|
||||
# One day we will have support for multiple instances within a
|
||||
|
|
@ -255,6 +268,34 @@ class AppRunner(DirectObject):
|
|||
|
||||
self.sendRequest('notify', 'onwindowopen')
|
||||
|
||||
def scriptRequest(self, operation, object, propertyName = None,
|
||||
value = None):
|
||||
""" Issues a new script request to the browser. This queries
|
||||
or modifies one of the browser's DOM properties.
|
||||
|
||||
operation may be one of [ 'get_property', 'set_property',
|
||||
'call', 'evaluate' ].
|
||||
|
||||
object is the browser object to manipulate, or the scope in
|
||||
which to evaluate the expression.
|
||||
|
||||
propertyName is the name of the property to manipulate, if
|
||||
relevant (set to None for the default method name).
|
||||
|
||||
value is the new value to assign to the property for
|
||||
set_property, or the parameter list for call, or the string
|
||||
expression for evaluate.
|
||||
"""
|
||||
uniqueId = self.nextScriptId
|
||||
self.nextScriptId += 1
|
||||
self.sendRequest('script', operation, object,
|
||||
propertyName, value, uniqueId);
|
||||
|
||||
def scriptResponse(self, uniqueId, value):
|
||||
""" Called by the browser in response to a scriptRequest,
|
||||
above. """
|
||||
print "Got scriptResponse: %s, %s" % (uniqueId, value)
|
||||
|
||||
def parseSysArgs(self):
|
||||
""" Converts sys.argv into (p3dFilename, tokens). """
|
||||
import getopt
|
||||
|
|
@ -287,6 +328,13 @@ class AppRunner(DirectObject):
|
|||
|
||||
return (osFilename, tokens)
|
||||
|
||||
class BrowserObject:
|
||||
""" This class provides the Python wrapper around some object that
|
||||
actually exists in the plugin host's namespace, e.g. a JavaScript
|
||||
or DOM object. """
|
||||
|
||||
def __init__(self, objectId):
|
||||
self.__objectId = objectId
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
Loading…
Reference in New Issue