mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
more work on outbound scripting
This commit is contained in:
parent
b2906cda8b
commit
59210bf718
@ -173,7 +173,7 @@ set_wparams(const P3DWindowParams &wparams) {
|
||||
// of the instance, to be used by JavaScript code in the
|
||||
// browser to control this program.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DObject *P3DInstance::
|
||||
P3D_object *P3DInstance::
|
||||
get_panda_script_object() const {
|
||||
assert(_session != NULL);
|
||||
nout << "Called P3DInstance::get_panda_script_object()\n";
|
||||
@ -188,13 +188,13 @@ get_panda_script_object() const {
|
||||
TiXmlDocument *response = _session->command_and_response(doc);
|
||||
nout << "response pointer: " << response << "\n" << flush;
|
||||
|
||||
P3DObject *result = NULL;
|
||||
P3D_object *result = NULL;
|
||||
if (response != NULL) {
|
||||
TiXmlElement *xresponse = response->FirstChildElement("response");
|
||||
if (xresponse != NULL) {
|
||||
TiXmlElement *xvalue = xresponse->FirstChildElement("value");
|
||||
if (xvalue != NULL) {
|
||||
result = _session->xml_to_object(xvalue);
|
||||
result = _session->xml_to_p3dobj(xvalue);
|
||||
}
|
||||
}
|
||||
delete response;
|
||||
@ -464,7 +464,7 @@ send_browser_script_object() {
|
||||
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));
|
||||
xcommand->LinkEndChild(_session->p3dobj_to_xml(_browser_script_object));
|
||||
}
|
||||
|
||||
doc->LinkEndChild(decl);
|
||||
@ -534,7 +534,7 @@ handle_script_request(P3D_request *request) {
|
||||
doc->LinkEndChild(decl);
|
||||
doc->LinkEndChild(xcommand);
|
||||
if (value != NULL) {
|
||||
xcommand->LinkEndChild(_session->object_to_xml(value));
|
||||
xcommand->LinkEndChild(_session->p3dobj_to_xml(value));
|
||||
P3D_OBJECT_FINISH(value);
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
void set_wparams(const P3DWindowParams &wparams);
|
||||
inline const P3DWindowParams &get_wparams() const;
|
||||
|
||||
P3DObject *get_panda_script_object() const;
|
||||
P3D_object *get_panda_script_object() const;
|
||||
void set_browser_script_object(P3D_object *object);
|
||||
|
||||
bool has_request();
|
||||
|
@ -194,7 +194,7 @@ call(const string &method_name, P3D_object *params[], int num_params) const {
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_params; ++i) {
|
||||
TiXmlElement *xparams = _session->object_to_xml(params[i]);
|
||||
TiXmlElement *xparams = _session->p3dobj_to_xml(params[i]);
|
||||
xcommand->LinkEndChild(xparams);
|
||||
|
||||
// Now we're done with the params object passed in, we can delete
|
||||
@ -207,13 +207,13 @@ call(const string &method_name, P3D_object *params[], int num_params) const {
|
||||
TiXmlDocument *response = _session->command_and_response(doc);
|
||||
nout << "call response pointer: " << response << "\n" << flush;
|
||||
|
||||
P3DObject *result = NULL;
|
||||
P3D_object *result = NULL;
|
||||
if (response != NULL) {
|
||||
TiXmlElement *xresponse = response->FirstChildElement("response");
|
||||
if (xresponse != NULL) {
|
||||
TiXmlElement *xvalue = xresponse->FirstChildElement("value");
|
||||
if (xvalue != NULL) {
|
||||
result = _session->xml_to_object(xvalue);
|
||||
result = _session->xml_to_p3dobj(xvalue);
|
||||
}
|
||||
}
|
||||
delete response;
|
||||
|
@ -172,7 +172,7 @@ run_python() {
|
||||
|
||||
|
||||
// Now add check_comm() as a task.
|
||||
_check_comm_task = new GenericAsyncTask("check_comm", st_check_comm, this);
|
||||
_check_comm_task = new GenericAsyncTask("check_comm", task_check_comm, this);
|
||||
AsyncTaskManager *task_mgr = AsyncTaskManager::get_global_ptr();
|
||||
task_mgr->add(_check_comm_task);
|
||||
|
||||
@ -244,7 +244,7 @@ handle_command(TiXmlDocument *doc) {
|
||||
} else if (strcmp(cmd, "script_response") == 0) {
|
||||
// Response from a script request.
|
||||
assert(!needs_response);
|
||||
handle_script_response_command(xcommand);
|
||||
nout << "Ignoring unexpected script_response\n";
|
||||
|
||||
} else {
|
||||
nout << "Unhandled command " << cmd << "\n";
|
||||
@ -408,41 +408,16 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::check_comm
|
||||
// Access: Private
|
||||
// Description: This method is added to the Python task manager (via
|
||||
// py_check_comm, below) so that it gets a call every
|
||||
// Description: This method is added to the task manager (via
|
||||
// task_check_comm, below) so that it gets a call every
|
||||
// frame. Its job is to check for commands received
|
||||
// from the plugin host in the parent process.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AsyncTask::DoneStatus P3DPythonRun::
|
||||
check_comm(GenericAsyncTask *task) {
|
||||
void P3DPythonRun::
|
||||
check_comm() {
|
||||
ACQUIRE_LOCK(_commands_lock);
|
||||
while (!_commands.empty()) {
|
||||
TiXmlDocument *doc = _commands.front();
|
||||
@ -461,21 +436,82 @@ check_comm(GenericAsyncTask *task) {
|
||||
}
|
||||
|
||||
RELEASE_LOCK(_commands_lock);
|
||||
|
||||
return AsyncTask::DS_cont;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::st_check_comm
|
||||
// Function: P3DPythonRun::task_check_comm
|
||||
// Access: Private, Static
|
||||
// Description: This static function wrapper around check_comm is
|
||||
// necessary to add the method function to the
|
||||
// GenericAsyncTask object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AsyncTask::DoneStatus P3DPythonRun::
|
||||
st_check_comm(GenericAsyncTask *task, void *user_data) {
|
||||
task_check_comm(GenericAsyncTask *task, void *user_data) {
|
||||
P3DPythonRun *self = (P3DPythonRun *)user_data;
|
||||
return self->check_comm(task);
|
||||
self->check_comm();
|
||||
return AsyncTask::DS_cont;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::wait_script_response
|
||||
// Access: Private
|
||||
// Description: This method is similar to check_comm(), above, but
|
||||
// instead of handling all events, it waits for a
|
||||
// specific script_response ID to come back from the
|
||||
// browser, and leaves all other events in the queue.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TiXmlDocument *P3DPythonRun::
|
||||
wait_script_response(int response_id) {
|
||||
while (true) {
|
||||
ACQUIRE_LOCK(_commands_lock);
|
||||
|
||||
Commands::iterator ci;
|
||||
for (ci = _commands.begin(); ci != _commands.end(); ++ci) {
|
||||
TiXmlDocument *doc = (*ci);
|
||||
|
||||
TiXmlElement *xcommand = doc->FirstChildElement("command");
|
||||
if (xcommand != NULL) {
|
||||
const char *cmd = xcommand->Attribute("cmd");
|
||||
if (cmd != NULL && strcmp(cmd, "script_response") == 0) {
|
||||
int unique_id;
|
||||
if (xcommand->QueryIntAttribute("unique_id", &unique_id) == TIXML_SUCCESS) {
|
||||
if (unique_id == response_id) {
|
||||
// This is the response we were waiting for.
|
||||
_commands.erase(ci);
|
||||
RELEASE_LOCK(_commands_lock);
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It's not the response we're waiting for, but maybe we need
|
||||
// to handle it anyway.
|
||||
bool needs_response = false;
|
||||
int want_response_id;
|
||||
if (xcommand->QueryIntAttribute("want_response_id", &want_response_id) == TIXML_SUCCESS) {
|
||||
// This command will be wanting a response. We'd better
|
||||
// honor it right away, or we risk deadlock with the browser
|
||||
// process and the Python process waiting for each other.
|
||||
_commands.erase(ci);
|
||||
RELEASE_LOCK(_commands_lock);
|
||||
handle_command(doc);
|
||||
delete doc;
|
||||
ACQUIRE_LOCK(_commands_lock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_program_continue) {
|
||||
terminate_session();
|
||||
}
|
||||
|
||||
RELEASE_LOCK(_commands_lock);
|
||||
|
||||
// It hasn't shown up yet. Give the sub-thread a chance to
|
||||
// process the input and append it to the queue.
|
||||
Thread::force_yield();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -494,6 +530,38 @@ py_request_func(PyObject *args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(request_type, "wait_script_response") == 0) {
|
||||
// This is a special case. Instead of generating a new request,
|
||||
// this means to wait for a particular script_response to come in
|
||||
// on the wire.
|
||||
int response_id;
|
||||
if (!PyArg_ParseTuple(extra_args, "i", &response_id)) {
|
||||
Py_DECREF(extra_args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nout << "Waiting for script_response " << response_id << "\n";
|
||||
TiXmlDocument *doc = wait_script_response(response_id);
|
||||
nout << "got: " << *doc << "\n";
|
||||
TiXmlElement *xcommand = doc->FirstChildElement("command");
|
||||
assert(xcommand != NULL);
|
||||
TiXmlElement *xvalue = xcommand->FirstChildElement("value");
|
||||
|
||||
PyObject *value = NULL;
|
||||
if (xvalue != NULL) {
|
||||
nout << "Converting xvalue: " << *xvalue << "\n";
|
||||
value = xml_to_pyobj(xvalue);
|
||||
} else {
|
||||
value = Py_None;
|
||||
Py_INCREF(value);
|
||||
}
|
||||
nout << "Got script_response " << response_id << ", xvalue = " << xvalue << "\n";
|
||||
|
||||
delete doc;
|
||||
Py_DECREF(extra_args);
|
||||
return value;
|
||||
}
|
||||
|
||||
TiXmlDocument doc;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||
TiXmlElement *xrequest = new TiXmlElement("request");
|
||||
@ -506,6 +574,7 @@ py_request_func(PyObject *args) {
|
||||
// A general notification to be sent directly to the instance.
|
||||
const char *message;
|
||||
if (!PyArg_ParseTuple(extra_args, "s", &message)) {
|
||||
Py_DECREF(extra_args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -522,8 +591,10 @@ py_request_func(PyObject *args) {
|
||||
int unique_id;
|
||||
if (!PyArg_ParseTuple(extra_args, "sOsOi",
|
||||
&operation, &object, &property_name, &value, &unique_id)) {
|
||||
Py_DECREF(extra_args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xrequest->SetAttribute("operation", operation);
|
||||
xrequest->SetAttribute("property_name", property_name);
|
||||
xrequest->SetAttribute("unique_id", unique_id);
|
||||
@ -542,6 +613,7 @@ py_request_func(PyObject *args) {
|
||||
const char *expression;
|
||||
int unique_id;
|
||||
if (!PyArg_ParseTuple(extra_args, "si", &expression, &unique_id)) {
|
||||
Py_DECREF(extra_args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -554,9 +626,11 @@ py_request_func(PyObject *args) {
|
||||
} else {
|
||||
string message = string("Unsupported request type: ") + string(request_type);
|
||||
PyErr_SetString(PyExc_ValueError, message.c_str());
|
||||
Py_DECREF(extra_args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_DECREF(extra_args);
|
||||
return Py_BuildValue("");
|
||||
}
|
||||
|
||||
@ -780,6 +854,11 @@ terminate_session() {
|
||||
}
|
||||
Py_DECREF(result);
|
||||
nout << "done calling stop()\n";
|
||||
|
||||
// The task manager is cleaned up. Let's exit immediately here,
|
||||
// rather than returning all the way up. This just makes it easier
|
||||
// when we call terminate_session() from a deeply-nested loop.
|
||||
exit(0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -921,7 +1000,8 @@ xml_to_pyobj(TiXmlElement *xvalue) {
|
||||
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);
|
||||
return PyObject_CallFunction(_browser_object_class, (char *)"Oi",
|
||||
_runner, object_id);
|
||||
}
|
||||
|
||||
} else if (strcmp(type, "python") == 0) {
|
||||
|
@ -74,8 +74,9 @@ private:
|
||||
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);
|
||||
void check_comm();
|
||||
static AsyncTask::DoneStatus task_check_comm(GenericAsyncTask *task, void *user_data);
|
||||
TiXmlDocument *wait_script_response(int response_id);
|
||||
|
||||
PyObject *py_request_func(PyObject *args);
|
||||
static PyObject *st_request_func(PyObject *, PyObject *args);
|
||||
|
@ -312,14 +312,14 @@ command_and_response(TiXmlDocument *command) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::xml_to_object
|
||||
// Function: P3DSession::xml_to_p3dobj
|
||||
// Access: Public
|
||||
// Description: Converts the XML representation of the particular
|
||||
// object value into a corresponding P3DObject object.
|
||||
// object value into a corresponding P3D_object.
|
||||
// Returns the newly-allocated object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DObject *P3DSession::
|
||||
xml_to_object(const TiXmlElement *xvalue) {
|
||||
P3D_object *P3DSession::
|
||||
xml_to_p3dobj(const TiXmlElement *xvalue) {
|
||||
const char *type = xvalue->Attribute("type");
|
||||
if (strcmp(type, "none") == 0) {
|
||||
return new P3DNoneObject;
|
||||
@ -350,6 +350,15 @@ xml_to_object(const TiXmlElement *xvalue) {
|
||||
return new P3DStringObject(*value);
|
||||
}
|
||||
|
||||
} else if (strcmp(type, "browser") == 0) {
|
||||
int object_id;
|
||||
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
|
||||
P3D_object *obj = (P3D_object *)object_id;
|
||||
nout << "Found object " << obj << "\n" << flush;
|
||||
nout << " formatted is " << *obj << "\n" << flush;
|
||||
return P3D_OBJECT_COPY(obj);
|
||||
}
|
||||
|
||||
} else if (strcmp(type, "python") == 0) {
|
||||
int object_id;
|
||||
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
|
||||
@ -362,14 +371,14 @@ xml_to_object(const TiXmlElement *xvalue) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::object_to_xml
|
||||
// Function: P3DSession::p3dobj_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) {
|
||||
p3dobj_to_xml(const P3D_object *obj) {
|
||||
TiXmlElement *xvalue = new TiXmlElement("value");
|
||||
|
||||
switch (P3D_OBJECT_GET_TYPE(obj)) {
|
||||
@ -681,7 +690,11 @@ rt_make_p3d_request(TiXmlElement *xrequest) {
|
||||
xrequest->Attribute("unique_id", &unique_id);
|
||||
|
||||
if (operation != NULL && xobject != NULL) {
|
||||
P3D_object *object = xml_to_object(xobject);
|
||||
nout << "xobject = " << *xobject << "\n" << flush;
|
||||
P3D_object *object = xml_to_p3dobj(xobject);
|
||||
nout << "converted to " << object << "\n" << flush;
|
||||
nout << "object = " << *object << "\n" << flush;
|
||||
nout << "operation = " << *operation << "\n" << flush;
|
||||
if (strcmp(operation, "get_property") == 0 && property_name != NULL) {
|
||||
request = new P3D_request;
|
||||
request->_request_type = P3D_RT_script;
|
||||
|
@ -49,8 +49,8 @@ public:
|
||||
|
||||
void send_command(TiXmlDocument *command);
|
||||
TiXmlDocument *command_and_response(TiXmlDocument *command);
|
||||
P3DObject *xml_to_object(const TiXmlElement *xvalue);
|
||||
TiXmlElement *object_to_xml(const P3D_object *obj);
|
||||
P3D_object *xml_to_p3dobj(const TiXmlElement *xvalue);
|
||||
TiXmlElement *p3dobj_to_xml(const P3D_object *obj);
|
||||
|
||||
private:
|
||||
void install_progress(P3DPackage *package, double progress);
|
||||
|
@ -128,7 +128,7 @@ get_property(const string &property) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
P3D_object *object = _instance->variant_to_object(&result);
|
||||
P3D_object *object = _instance->variant_to_p3dobj(&result);
|
||||
browser->releasevariantvalue(&result);
|
||||
return object;
|
||||
}
|
||||
|
@ -499,13 +499,13 @@ get_panda_script_object() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::object_to_variant
|
||||
// Function: PPInstance::p3dobj_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) {
|
||||
p3dobj_to_variant(NPVariant *result, const P3D_object *object) {
|
||||
switch (P3D_OBJECT_GET_TYPE(object)) {
|
||||
case P3D_OT_none:
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
@ -542,7 +542,7 @@ object_to_variant(NPVariant *result, const P3D_object *object) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::variant_to_object
|
||||
// Function: PPInstance::variant_to_p3dobj
|
||||
// Access: Private
|
||||
// Description: Converts the indicated NPVariant to the equivalent
|
||||
// P3D_object, and returns it (newly-allocated). The
|
||||
@ -550,7 +550,7 @@ object_to_variant(NPVariant *result, const P3D_object *object) {
|
||||
// later.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_object *PPInstance::
|
||||
variant_to_object(const NPVariant *variant) {
|
||||
variant_to_p3dobj(const NPVariant *variant) {
|
||||
if (NPVARIANT_IS_VOID(*variant) ||
|
||||
NPVARIANT_IS_NULL(*variant)) {
|
||||
return P3D_new_none_object();
|
||||
@ -564,8 +564,7 @@ variant_to_object(const NPVariant *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();
|
||||
return new PPBrowserObject(this, NPVARIANT_TO_OBJECT(*variant));
|
||||
}
|
||||
|
||||
// Hmm, none of the above?
|
||||
@ -826,37 +825,6 @@ show_np_variant(const NPVariant &result) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::np_variant_to_object
|
||||
// Access: Private
|
||||
// Description: Returns a freshly-allocated P3D_object corresponding
|
||||
// to the indicated NPVariant.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_object *PPInstance::
|
||||
np_variant_to_object(const NPVariant &result) {
|
||||
if (NPVARIANT_IS_NULL(result)) {
|
||||
return NULL;
|
||||
} else if (NPVARIANT_IS_VOID(result)) {
|
||||
return P3D_new_none_object();
|
||||
} else if (NPVARIANT_IS_BOOLEAN(result)) {
|
||||
return P3D_new_bool_object(NPVARIANT_TO_BOOLEAN(result));
|
||||
} else if (NPVARIANT_IS_INT32(result)) {
|
||||
return P3D_new_int_object(NPVARIANT_TO_INT32(result));
|
||||
} else if (NPVARIANT_IS_DOUBLE(result)) {
|
||||
return P3D_new_float_object(NPVARIANT_TO_DOUBLE(result));
|
||||
} else if (NPVARIANT_IS_STRING(result)) {
|
||||
NPString str = NPVARIANT_TO_STRING(result);
|
||||
return P3D_new_string_object(str.utf8characters, str.utf8length);
|
||||
} else if (NPVARIANT_IS_OBJECT(result)) {
|
||||
// TODO?
|
||||
return P3D_new_none_object();
|
||||
// NPVARIANT_TO_OBJECT(result);
|
||||
}
|
||||
|
||||
// Huh, what is this?
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -52,8 +52,8 @@ public:
|
||||
|
||||
NPObject *get_panda_script_object();
|
||||
|
||||
void object_to_variant(NPVariant *result, const P3D_object *object);
|
||||
P3D_object *variant_to_object(const NPVariant *variant);
|
||||
void p3dobj_to_variant(NPVariant *result, const P3D_object *object);
|
||||
P3D_object *variant_to_p3dobj(const NPVariant *variant);
|
||||
|
||||
private:
|
||||
bool read_contents_file(const string &filename);
|
||||
@ -65,7 +65,6 @@ private:
|
||||
void send_window();
|
||||
|
||||
void show_np_variant(const NPVariant &result);
|
||||
P3D_object *np_variant_to_object(const NPVariant &result);
|
||||
|
||||
#ifdef _WIN32
|
||||
static LONG
|
||||
|
@ -175,7 +175,7 @@ get_property(NPIdentifier name, NPVariant *result) {
|
||||
}
|
||||
|
||||
// We have the property, and its value is stored in value.
|
||||
_instance->object_to_variant(result, value);
|
||||
_instance->p3dobj_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 = _instance->variant_to_object(value);
|
||||
P3D_object *object = _instance->variant_to_p3dobj(value);
|
||||
bool result = P3D_OBJECT_SET_PROPERTY(_p3d_object, property_name.c_str(), object);
|
||||
return result;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ See pack3d.py for a script that generates these p3d files.
|
||||
import sys
|
||||
from direct.showbase import VFSImporter
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, HTTPClient
|
||||
from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, HTTPClient, Thread
|
||||
from direct.stdpy import file
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from direct.showbase import AppRunnerGlobal
|
||||
@ -155,8 +155,9 @@ class AppRunner(DirectObject):
|
||||
""" 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
|
||||
print "setBrowserScriptObject(%s)" % (window)
|
||||
|
||||
def setP3DFilename(self, p3dFilename, tokens = [],
|
||||
instanceId = None):
|
||||
@ -261,7 +262,8 @@ class AppRunner(DirectObject):
|
||||
self.requestFunc = func
|
||||
|
||||
def sendRequest(self, request, *args):
|
||||
self.requestFunc(self.instanceId, request, args)
|
||||
assert self.requestFunc
|
||||
return self.requestFunc(self.instanceId, request, args)
|
||||
|
||||
def windowEvent(self, win):
|
||||
print "Got window event in runp3d"
|
||||
@ -271,7 +273,9 @@ class AppRunner(DirectObject):
|
||||
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.
|
||||
or modifies one of the browser's DOM properties. This method
|
||||
blocks until the return value is received from the browser,
|
||||
and then it returns that value.
|
||||
|
||||
operation may be one of [ 'get_property', 'set_property',
|
||||
'call', 'evaluate' ].
|
||||
@ -291,10 +295,10 @@ class AppRunner(DirectObject):
|
||||
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)
|
||||
# Now wait for the response to come in.
|
||||
result = self.sendRequest('wait_script_response', uniqueId)
|
||||
print "result for %s.%s = %s" % (object, propertyName, result,)
|
||||
return result
|
||||
|
||||
def parseSysArgs(self):
|
||||
""" Converts sys.argv into (p3dFilename, tokens). """
|
||||
@ -333,9 +337,47 @@ class BrowserObject:
|
||||
actually exists in the plugin host's namespace, e.g. a JavaScript
|
||||
or DOM object. """
|
||||
|
||||
def __init__(self, objectId):
|
||||
self.__objectId = objectId
|
||||
|
||||
def __init__(self, runner, objectId):
|
||||
self.__dict__['_BrowserObject__runner'] = runner
|
||||
self.__dict__['_BrowserObject__objectId'] = objectId
|
||||
|
||||
def __str__(self):
|
||||
return "BrowserObject(%s)" % (self.__objectId)
|
||||
|
||||
def __nonzero__(self):
|
||||
return True
|
||||
|
||||
def __getattr__(self, name):
|
||||
""" Remaps attempts to query an attribute into the appropriate
|
||||
calls to query the actual browser object under the hood. """
|
||||
|
||||
print "__getattr_(self, %s)" % (name)
|
||||
print "runner = %s" % (self.__runner)
|
||||
value = self.__runner.scriptRequest('get_property', self,
|
||||
propertyName = name)
|
||||
return value
|
||||
# raise AttributeError(name)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name in self.__dict__:
|
||||
self.__dict__[name] = value
|
||||
return
|
||||
|
||||
value = self.__runner.scriptRequest('set_property', self,
|
||||
propertyName = name,
|
||||
value = value)
|
||||
if not value:
|
||||
raise AttributeError(name)
|
||||
|
||||
def __delattr__(self, name):
|
||||
if name in self.__dict__:
|
||||
del self.__dict__[name]
|
||||
return
|
||||
|
||||
value = self.__runner.scriptRequest('del_property', self,
|
||||
propertyName = name)
|
||||
if not value:
|
||||
raise AttributeError(name)
|
||||
|
||||
if __name__ == '__main__':
|
||||
runner = AppRunner()
|
||||
|
Loading…
x
Reference in New Issue
Block a user