mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -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
|
// of the instance, to be used by JavaScript code in the
|
||||||
// browser to control this program.
|
// browser to control this program.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
P3DObject *P3DInstance::
|
P3D_object *P3DInstance::
|
||||||
get_panda_script_object() const {
|
get_panda_script_object() const {
|
||||||
assert(_session != NULL);
|
assert(_session != NULL);
|
||||||
nout << "Called P3DInstance::get_panda_script_object()\n";
|
nout << "Called P3DInstance::get_panda_script_object()\n";
|
||||||
@ -188,13 +188,13 @@ get_panda_script_object() const {
|
|||||||
TiXmlDocument *response = _session->command_and_response(doc);
|
TiXmlDocument *response = _session->command_and_response(doc);
|
||||||
nout << "response pointer: " << response << "\n" << flush;
|
nout << "response pointer: " << response << "\n" << flush;
|
||||||
|
|
||||||
P3DObject *result = NULL;
|
P3D_object *result = NULL;
|
||||||
if (response != NULL) {
|
if (response != NULL) {
|
||||||
TiXmlElement *xresponse = response->FirstChildElement("response");
|
TiXmlElement *xresponse = response->FirstChildElement("response");
|
||||||
if (xresponse != NULL) {
|
if (xresponse != NULL) {
|
||||||
TiXmlElement *xvalue = xresponse->FirstChildElement("value");
|
TiXmlElement *xvalue = xresponse->FirstChildElement("value");
|
||||||
if (xvalue != NULL) {
|
if (xvalue != NULL) {
|
||||||
result = _session->xml_to_object(xvalue);
|
result = _session->xml_to_p3dobj(xvalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete response;
|
delete response;
|
||||||
@ -464,7 +464,7 @@ send_browser_script_object() {
|
|||||||
xcommand->SetAttribute("cmd", "pyobj");
|
xcommand->SetAttribute("cmd", "pyobj");
|
||||||
xcommand->SetAttribute("op", "set_browser_script_object");
|
xcommand->SetAttribute("op", "set_browser_script_object");
|
||||||
if (_browser_script_object != NULL) {
|
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);
|
doc->LinkEndChild(decl);
|
||||||
@ -534,7 +534,7 @@ handle_script_request(P3D_request *request) {
|
|||||||
doc->LinkEndChild(decl);
|
doc->LinkEndChild(decl);
|
||||||
doc->LinkEndChild(xcommand);
|
doc->LinkEndChild(xcommand);
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
xcommand->LinkEndChild(_session->object_to_xml(value));
|
xcommand->LinkEndChild(_session->p3dobj_to_xml(value));
|
||||||
P3D_OBJECT_FINISH(value);
|
P3D_OBJECT_FINISH(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ public:
|
|||||||
void set_wparams(const P3DWindowParams &wparams);
|
void set_wparams(const P3DWindowParams &wparams);
|
||||||
inline const P3DWindowParams &get_wparams() const;
|
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);
|
void set_browser_script_object(P3D_object *object);
|
||||||
|
|
||||||
bool has_request();
|
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) {
|
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);
|
xcommand->LinkEndChild(xparams);
|
||||||
|
|
||||||
// Now we're done with the params object passed in, we can delete
|
// 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);
|
TiXmlDocument *response = _session->command_and_response(doc);
|
||||||
nout << "call response pointer: " << response << "\n" << flush;
|
nout << "call response pointer: " << response << "\n" << flush;
|
||||||
|
|
||||||
P3DObject *result = NULL;
|
P3D_object *result = NULL;
|
||||||
if (response != NULL) {
|
if (response != NULL) {
|
||||||
TiXmlElement *xresponse = response->FirstChildElement("response");
|
TiXmlElement *xresponse = response->FirstChildElement("response");
|
||||||
if (xresponse != NULL) {
|
if (xresponse != NULL) {
|
||||||
TiXmlElement *xvalue = xresponse->FirstChildElement("value");
|
TiXmlElement *xvalue = xresponse->FirstChildElement("value");
|
||||||
if (xvalue != NULL) {
|
if (xvalue != NULL) {
|
||||||
result = _session->xml_to_object(xvalue);
|
result = _session->xml_to_p3dobj(xvalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete response;
|
delete response;
|
||||||
|
@ -172,7 +172,7 @@ run_python() {
|
|||||||
|
|
||||||
|
|
||||||
// Now add check_comm() as a task.
|
// 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();
|
AsyncTaskManager *task_mgr = AsyncTaskManager::get_global_ptr();
|
||||||
task_mgr->add(_check_comm_task);
|
task_mgr->add(_check_comm_task);
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ handle_command(TiXmlDocument *doc) {
|
|||||||
} else if (strcmp(cmd, "script_response") == 0) {
|
} else if (strcmp(cmd, "script_response") == 0) {
|
||||||
// Response from a script request.
|
// Response from a script request.
|
||||||
assert(!needs_response);
|
assert(!needs_response);
|
||||||
handle_script_response_command(xcommand);
|
nout << "Ignoring unexpected script_response\n";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
nout << "Unhandled command " << cmd << "\n";
|
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
|
// Function: P3DPythonRun::check_comm
|
||||||
// Access: Private
|
// Access: Private
|
||||||
// Description: This method is added to the Python task manager (via
|
// Description: This method is added to the task manager (via
|
||||||
// py_check_comm, below) so that it gets a call every
|
// task_check_comm, below) so that it gets a call every
|
||||||
// frame. Its job is to check for commands received
|
// frame. Its job is to check for commands received
|
||||||
// from the plugin host in the parent process.
|
// from the plugin host in the parent process.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
AsyncTask::DoneStatus P3DPythonRun::
|
void P3DPythonRun::
|
||||||
check_comm(GenericAsyncTask *task) {
|
check_comm() {
|
||||||
ACQUIRE_LOCK(_commands_lock);
|
ACQUIRE_LOCK(_commands_lock);
|
||||||
while (!_commands.empty()) {
|
while (!_commands.empty()) {
|
||||||
TiXmlDocument *doc = _commands.front();
|
TiXmlDocument *doc = _commands.front();
|
||||||
@ -461,21 +436,82 @@ check_comm(GenericAsyncTask *task) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RELEASE_LOCK(_commands_lock);
|
RELEASE_LOCK(_commands_lock);
|
||||||
|
|
||||||
return AsyncTask::DS_cont;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DPythonRun::st_check_comm
|
// Function: P3DPythonRun::task_check_comm
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
// Description: This static function wrapper around check_comm is
|
// Description: This static function wrapper around check_comm is
|
||||||
// necessary to add the method function to the
|
// necessary to add the method function to the
|
||||||
// GenericAsyncTask object.
|
// GenericAsyncTask object.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
AsyncTask::DoneStatus P3DPythonRun::
|
AsyncTask::DoneStatus P3DPythonRun::
|
||||||
st_check_comm(GenericAsyncTask *task, void *user_data) {
|
task_check_comm(GenericAsyncTask *task, void *user_data) {
|
||||||
P3DPythonRun *self = (P3DPythonRun *)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;
|
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;
|
TiXmlDocument doc;
|
||||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||||
TiXmlElement *xrequest = new TiXmlElement("request");
|
TiXmlElement *xrequest = new TiXmlElement("request");
|
||||||
@ -506,6 +574,7 @@ py_request_func(PyObject *args) {
|
|||||||
// A general notification to be sent directly to the instance.
|
// A general notification to be sent directly to the instance.
|
||||||
const char *message;
|
const char *message;
|
||||||
if (!PyArg_ParseTuple(extra_args, "s", &message)) {
|
if (!PyArg_ParseTuple(extra_args, "s", &message)) {
|
||||||
|
Py_DECREF(extra_args);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,8 +591,10 @@ py_request_func(PyObject *args) {
|
|||||||
int unique_id;
|
int unique_id;
|
||||||
if (!PyArg_ParseTuple(extra_args, "sOsOi",
|
if (!PyArg_ParseTuple(extra_args, "sOsOi",
|
||||||
&operation, &object, &property_name, &value, &unique_id)) {
|
&operation, &object, &property_name, &value, &unique_id)) {
|
||||||
|
Py_DECREF(extra_args);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xrequest->SetAttribute("operation", operation);
|
xrequest->SetAttribute("operation", operation);
|
||||||
xrequest->SetAttribute("property_name", property_name);
|
xrequest->SetAttribute("property_name", property_name);
|
||||||
xrequest->SetAttribute("unique_id", unique_id);
|
xrequest->SetAttribute("unique_id", unique_id);
|
||||||
@ -542,6 +613,7 @@ py_request_func(PyObject *args) {
|
|||||||
const char *expression;
|
const char *expression;
|
||||||
int unique_id;
|
int unique_id;
|
||||||
if (!PyArg_ParseTuple(extra_args, "si", &expression, &unique_id)) {
|
if (!PyArg_ParseTuple(extra_args, "si", &expression, &unique_id)) {
|
||||||
|
Py_DECREF(extra_args);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,9 +626,11 @@ py_request_func(PyObject *args) {
|
|||||||
} else {
|
} else {
|
||||||
string message = string("Unsupported request type: ") + string(request_type);
|
string message = string("Unsupported request type: ") + string(request_type);
|
||||||
PyErr_SetString(PyExc_ValueError, message.c_str());
|
PyErr_SetString(PyExc_ValueError, message.c_str());
|
||||||
|
Py_DECREF(extra_args);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Py_DECREF(extra_args);
|
||||||
return Py_BuildValue("");
|
return Py_BuildValue("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,6 +854,11 @@ terminate_session() {
|
|||||||
}
|
}
|
||||||
Py_DECREF(result);
|
Py_DECREF(result);
|
||||||
nout << "done calling stop()\n";
|
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;
|
int object_id;
|
||||||
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
|
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
|
||||||
// Construct a new BrowserObject wrapper around this object.
|
// 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) {
|
} else if (strcmp(type, "python") == 0) {
|
||||||
|
@ -74,8 +74,9 @@ private:
|
|||||||
int want_response_id);
|
int want_response_id);
|
||||||
void handle_script_response_command(TiXmlElement *xcommand);
|
void handle_script_response_command(TiXmlElement *xcommand);
|
||||||
|
|
||||||
AsyncTask::DoneStatus check_comm(GenericAsyncTask *task);
|
void check_comm();
|
||||||
static AsyncTask::DoneStatus st_check_comm(GenericAsyncTask *task, void *user_data);
|
static AsyncTask::DoneStatus task_check_comm(GenericAsyncTask *task, void *user_data);
|
||||||
|
TiXmlDocument *wait_script_response(int response_id);
|
||||||
|
|
||||||
PyObject *py_request_func(PyObject *args);
|
PyObject *py_request_func(PyObject *args);
|
||||||
static PyObject *st_request_func(PyObject *, 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
|
// Access: Public
|
||||||
// Description: Converts the XML representation of the particular
|
// 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.
|
// Returns the newly-allocated object.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
P3DObject *P3DSession::
|
P3D_object *P3DSession::
|
||||||
xml_to_object(const TiXmlElement *xvalue) {
|
xml_to_p3dobj(const TiXmlElement *xvalue) {
|
||||||
const char *type = xvalue->Attribute("type");
|
const char *type = xvalue->Attribute("type");
|
||||||
if (strcmp(type, "none") == 0) {
|
if (strcmp(type, "none") == 0) {
|
||||||
return new P3DNoneObject;
|
return new P3DNoneObject;
|
||||||
@ -350,6 +350,15 @@ xml_to_object(const TiXmlElement *xvalue) {
|
|||||||
return new P3DStringObject(*value);
|
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) {
|
} else if (strcmp(type, "python") == 0) {
|
||||||
int object_id;
|
int object_id;
|
||||||
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
|
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
|
// Access: Public
|
||||||
// Description: Allocates and returns a new XML structure
|
// Description: Allocates and returns a new XML structure
|
||||||
// corresponding to the indicated value. The supplied
|
// corresponding to the indicated value. The supplied
|
||||||
// P3DObject passed in is *not* deleted.
|
// P3DObject passed in is *not* deleted.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
TiXmlElement *P3DSession::
|
TiXmlElement *P3DSession::
|
||||||
object_to_xml(const P3D_object *obj) {
|
p3dobj_to_xml(const P3D_object *obj) {
|
||||||
TiXmlElement *xvalue = new TiXmlElement("value");
|
TiXmlElement *xvalue = new TiXmlElement("value");
|
||||||
|
|
||||||
switch (P3D_OBJECT_GET_TYPE(obj)) {
|
switch (P3D_OBJECT_GET_TYPE(obj)) {
|
||||||
@ -681,7 +690,11 @@ rt_make_p3d_request(TiXmlElement *xrequest) {
|
|||||||
xrequest->Attribute("unique_id", &unique_id);
|
xrequest->Attribute("unique_id", &unique_id);
|
||||||
|
|
||||||
if (operation != NULL && xobject != NULL) {
|
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) {
|
if (strcmp(operation, "get_property") == 0 && property_name != NULL) {
|
||||||
request = new P3D_request;
|
request = new P3D_request;
|
||||||
request->_request_type = P3D_RT_script;
|
request->_request_type = P3D_RT_script;
|
||||||
|
@ -49,8 +49,8 @@ public:
|
|||||||
|
|
||||||
void send_command(TiXmlDocument *command);
|
void send_command(TiXmlDocument *command);
|
||||||
TiXmlDocument *command_and_response(TiXmlDocument *command);
|
TiXmlDocument *command_and_response(TiXmlDocument *command);
|
||||||
P3DObject *xml_to_object(const TiXmlElement *xvalue);
|
P3D_object *xml_to_p3dobj(const TiXmlElement *xvalue);
|
||||||
TiXmlElement *object_to_xml(const P3D_object *obj);
|
TiXmlElement *p3dobj_to_xml(const P3D_object *obj);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void install_progress(P3DPackage *package, double progress);
|
void install_progress(P3DPackage *package, double progress);
|
||||||
|
@ -128,7 +128,7 @@ get_property(const string &property) const {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
P3D_object *object = _instance->variant_to_object(&result);
|
P3D_object *object = _instance->variant_to_p3dobj(&result);
|
||||||
browser->releasevariantvalue(&result);
|
browser->releasevariantvalue(&result);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
@ -499,13 +499,13 @@ get_panda_script_object() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PPInstance::object_to_variant
|
// Function: PPInstance::p3dobj_to_variant
|
||||||
// Access: Private
|
// Access: Private
|
||||||
// Description: Converts the indicated P3D_object to the equivalent
|
// Description: Converts the indicated P3D_object to the equivalent
|
||||||
// NPVariant, and stores it in result.
|
// NPVariant, and stores it in result.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PPInstance::
|
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)) {
|
switch (P3D_OBJECT_GET_TYPE(object)) {
|
||||||
case P3D_OT_none:
|
case P3D_OT_none:
|
||||||
VOID_TO_NPVARIANT(*result);
|
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
|
// Access: Private
|
||||||
// Description: Converts the indicated NPVariant to the equivalent
|
// Description: Converts the indicated NPVariant to the equivalent
|
||||||
// P3D_object, and returns it (newly-allocated). The
|
// P3D_object, and returns it (newly-allocated). The
|
||||||
@ -550,7 +550,7 @@ object_to_variant(NPVariant *result, const P3D_object *object) {
|
|||||||
// later.
|
// later.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
P3D_object *PPInstance::
|
P3D_object *PPInstance::
|
||||||
variant_to_object(const NPVariant *variant) {
|
variant_to_p3dobj(const NPVariant *variant) {
|
||||||
if (NPVARIANT_IS_VOID(*variant) ||
|
if (NPVARIANT_IS_VOID(*variant) ||
|
||||||
NPVARIANT_IS_NULL(*variant)) {
|
NPVARIANT_IS_NULL(*variant)) {
|
||||||
return P3D_new_none_object();
|
return P3D_new_none_object();
|
||||||
@ -564,8 +564,7 @@ variant_to_object(const NPVariant *variant) {
|
|||||||
NPString str = NPVARIANT_TO_STRING(*variant);
|
NPString str = NPVARIANT_TO_STRING(*variant);
|
||||||
return P3D_new_string_object(str.utf8characters, str.utf8length);
|
return P3D_new_string_object(str.utf8characters, str.utf8length);
|
||||||
} else if (NPVARIANT_IS_OBJECT(*variant)) {
|
} else if (NPVARIANT_IS_OBJECT(*variant)) {
|
||||||
// TODO.
|
return new PPBrowserObject(this, NPVARIANT_TO_OBJECT(*variant));
|
||||||
return P3D_new_none_object();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hmm, none of the above?
|
// 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
|
#ifdef _WIN32
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -52,8 +52,8 @@ public:
|
|||||||
|
|
||||||
NPObject *get_panda_script_object();
|
NPObject *get_panda_script_object();
|
||||||
|
|
||||||
void object_to_variant(NPVariant *result, const P3D_object *object);
|
void p3dobj_to_variant(NPVariant *result, const P3D_object *object);
|
||||||
P3D_object *variant_to_object(const NPVariant *variant);
|
P3D_object *variant_to_p3dobj(const NPVariant *variant);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool read_contents_file(const string &filename);
|
bool read_contents_file(const string &filename);
|
||||||
@ -65,7 +65,6 @@ private:
|
|||||||
void send_window();
|
void send_window();
|
||||||
|
|
||||||
void show_np_variant(const NPVariant &result);
|
void show_np_variant(const NPVariant &result);
|
||||||
P3D_object *np_variant_to_object(const NPVariant &result);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static LONG
|
static LONG
|
||||||
|
@ -175,7 +175,7 @@ get_property(NPIdentifier name, NPVariant *result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We have the property, and its value is stored in value.
|
// 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);
|
P3D_OBJECT_FINISH(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -195,7 +195,7 @@ set_property(NPIdentifier name, const NPVariant *value) {
|
|||||||
return false;
|
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);
|
bool result = P3D_OBJECT_SET_PROPERTY(_p3d_object, property_name.c_str(), object);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ See pack3d.py for a script that generates these p3d files.
|
|||||||
import sys
|
import sys
|
||||||
from direct.showbase import VFSImporter
|
from direct.showbase import VFSImporter
|
||||||
from direct.showbase.DirectObject import DirectObject
|
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.stdpy import file
|
||||||
from direct.task.TaskManagerGlobal import taskMgr
|
from direct.task.TaskManagerGlobal import taskMgr
|
||||||
from direct.showbase import AppRunnerGlobal
|
from direct.showbase import AppRunnerGlobal
|
||||||
@ -155,8 +155,9 @@ class AppRunner(DirectObject):
|
|||||||
""" Replaces self.window with the browser's toplevel DOM
|
""" Replaces self.window with the browser's toplevel DOM
|
||||||
object, for controlling the JavaScript and the document in the
|
object, for controlling the JavaScript and the document in the
|
||||||
same page with the Panda3D plugin. """
|
same page with the Panda3D plugin. """
|
||||||
print "setBrowserScriptObject(%s)" % (window)
|
|
||||||
self.window = window
|
self.window = window
|
||||||
|
print "setBrowserScriptObject(%s)" % (window)
|
||||||
|
|
||||||
def setP3DFilename(self, p3dFilename, tokens = [],
|
def setP3DFilename(self, p3dFilename, tokens = [],
|
||||||
instanceId = None):
|
instanceId = None):
|
||||||
@ -261,7 +262,8 @@ class AppRunner(DirectObject):
|
|||||||
self.requestFunc = func
|
self.requestFunc = func
|
||||||
|
|
||||||
def sendRequest(self, request, *args):
|
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):
|
def windowEvent(self, win):
|
||||||
print "Got window event in runp3d"
|
print "Got window event in runp3d"
|
||||||
@ -271,7 +273,9 @@ class AppRunner(DirectObject):
|
|||||||
def scriptRequest(self, operation, object, propertyName = None,
|
def scriptRequest(self, operation, object, propertyName = None,
|
||||||
value = None):
|
value = None):
|
||||||
""" Issues a new script request to the browser. This queries
|
""" 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',
|
operation may be one of [ 'get_property', 'set_property',
|
||||||
'call', 'evaluate' ].
|
'call', 'evaluate' ].
|
||||||
@ -291,10 +295,10 @@ class AppRunner(DirectObject):
|
|||||||
self.sendRequest('script', operation, object,
|
self.sendRequest('script', operation, object,
|
||||||
propertyName, value, uniqueId);
|
propertyName, value, uniqueId);
|
||||||
|
|
||||||
def scriptResponse(self, uniqueId, value):
|
# Now wait for the response to come in.
|
||||||
""" Called by the browser in response to a scriptRequest,
|
result = self.sendRequest('wait_script_response', uniqueId)
|
||||||
above. """
|
print "result for %s.%s = %s" % (object, propertyName, result,)
|
||||||
print "Got scriptResponse: %s, %s" % (uniqueId, value)
|
return result
|
||||||
|
|
||||||
def parseSysArgs(self):
|
def parseSysArgs(self):
|
||||||
""" Converts sys.argv into (p3dFilename, tokens). """
|
""" Converts sys.argv into (p3dFilename, tokens). """
|
||||||
@ -333,9 +337,47 @@ class BrowserObject:
|
|||||||
actually exists in the plugin host's namespace, e.g. a JavaScript
|
actually exists in the plugin host's namespace, e.g. a JavaScript
|
||||||
or DOM object. """
|
or DOM object. """
|
||||||
|
|
||||||
def __init__(self, objectId):
|
def __init__(self, runner, objectId):
|
||||||
self.__objectId = 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__':
|
if __name__ == '__main__':
|
||||||
runner = AppRunner()
|
runner = AppRunner()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user