mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
more needs_response changes
This commit is contained in:
parent
e545c9193e
commit
07e714bb16
@ -900,7 +900,8 @@ handle_script_request(const string &operation, P3D_object *object,
|
||||
}
|
||||
|
||||
P3D_object *result =
|
||||
P3D_OBJECT_CALL(object, property_name.c_str(), values, num_values);
|
||||
P3D_OBJECT_CALL(object, property_name.c_str(), needs_response,
|
||||
values, num_values);
|
||||
|
||||
if (result != NULL) {
|
||||
xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
|
||||
|
@ -76,11 +76,12 @@ object_has_method(P3D_object *object, const char *method_name) {
|
||||
|
||||
static P3D_object *
|
||||
object_call(P3D_object *object, const char *method_name,
|
||||
bool needs_response,
|
||||
P3D_object *params[], int num_params) {
|
||||
if (method_name == NULL) {
|
||||
method_name = "";
|
||||
}
|
||||
return ((P3DObject *)object)->call(method_name, params, num_params);
|
||||
return ((P3DObject *)object)->call(method_name, needs_response, params, num_params);
|
||||
}
|
||||
|
||||
static P3D_object *
|
||||
@ -165,7 +166,7 @@ generic_has_method(P3D_object *object, const char *method_name) {
|
||||
|
||||
static P3D_object *
|
||||
generic_call(P3D_object *object, const char *method_name,
|
||||
P3D_object *params[], int num_params) {
|
||||
bool needs_response, P3D_object *params[], int num_params) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -294,11 +295,17 @@ has_method(const string &method_name) {
|
||||
// Access: Public, Virtual
|
||||
// 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.
|
||||
// invokes the object itself.
|
||||
//
|
||||
// If needs_response is true, the return value is a
|
||||
// new-reference P3D_object on success, or NULL on
|
||||
// failure. If needs_response is false, the return
|
||||
// value is always NULL, and there is no way to
|
||||
// determine success or failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_object *P3DObject::
|
||||
call(const string &method_name, P3D_object *params[], int num_params) {
|
||||
call(const string &method_name, bool needs_response,
|
||||
P3D_object *params[], int num_params) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
virtual bool set_property(const string &property, P3D_object *value);
|
||||
|
||||
virtual bool has_method(const string &method_name);
|
||||
virtual P3D_object *call(const string &method_name,
|
||||
virtual P3D_object *call(const string &method_name, bool needs_response,
|
||||
P3D_object *params[], int num_params);
|
||||
virtual P3D_object *eval(const string &expression);
|
||||
|
||||
|
@ -61,7 +61,7 @@ bool P3DPythonObject::
|
||||
get_bool() {
|
||||
bool bresult = 0;
|
||||
|
||||
P3D_object *result = call("__bool__", NULL, 0);
|
||||
P3D_object *result = call("__bool__", true, NULL, 0);
|
||||
if (result != NULL) {
|
||||
bresult = P3D_OBJECT_GET_BOOL(result);
|
||||
P3D_OBJECT_DECREF(result);
|
||||
@ -80,7 +80,7 @@ int P3DPythonObject::
|
||||
get_int() {
|
||||
int iresult = 0;
|
||||
|
||||
P3D_object *result = call("__int__", NULL, 0);
|
||||
P3D_object *result = call("__int__", true, NULL, 0);
|
||||
if (result != NULL) {
|
||||
iresult = P3D_OBJECT_GET_INT(result);
|
||||
P3D_OBJECT_DECREF(result);
|
||||
@ -99,7 +99,7 @@ double P3DPythonObject::
|
||||
get_float() {
|
||||
double fresult = 0.0;
|
||||
|
||||
P3D_object *result = call("__float__", NULL, 0);
|
||||
P3D_object *result = call("__float__", true, NULL, 0);
|
||||
if (result != NULL) {
|
||||
fresult = P3D_OBJECT_GET_FLOAT(result);
|
||||
P3D_OBJECT_DECREF(result);
|
||||
@ -116,7 +116,7 @@ get_float() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DPythonObject::
|
||||
make_string(string &value) {
|
||||
P3D_object *result = call("__str__", NULL, 0);
|
||||
P3D_object *result = call("__str__", true, NULL, 0);
|
||||
if (result != NULL) {
|
||||
int size = P3D_OBJECT_GET_STRING(result, NULL, 0);
|
||||
char *buffer = new char[size];
|
||||
@ -140,7 +140,7 @@ get_property(const string &property) {
|
||||
P3D_object *params[1];
|
||||
params[0] = new P3DStringObject(property);
|
||||
|
||||
P3D_object *result = call("__get_property__", params, 1);
|
||||
P3D_object *result = call("__get_property__", true, params, 1);
|
||||
P3D_OBJECT_DECREF(params[0]);
|
||||
return result;
|
||||
}
|
||||
@ -163,12 +163,12 @@ set_property(const string &property, P3D_object *value) {
|
||||
|
||||
if (value == NULL) {
|
||||
// Delete an attribute.
|
||||
result = call("__del_property__", params, 1);
|
||||
result = call("__del_property__", true, params, 1);
|
||||
|
||||
} else {
|
||||
// Set a new attribute.
|
||||
params[1] = value;
|
||||
result = call("__set_property__", params, 2);
|
||||
result = call("__set_property__", true, params, 2);
|
||||
}
|
||||
|
||||
P3D_OBJECT_DECREF(params[0]);
|
||||
@ -202,7 +202,7 @@ has_method(const string &method_name) {
|
||||
P3D_object *params[1];
|
||||
params[0] = new P3DStringObject(method_name);
|
||||
|
||||
P3D_object *result = call("__has_method__", params, 1);
|
||||
P3D_object *result = call("__has_method__", true, params, 1);
|
||||
P3D_OBJECT_DECREF(params[0]);
|
||||
|
||||
if (result != NULL) {
|
||||
@ -223,11 +223,17 @@ has_method(const string &method_name) {
|
||||
// Access: Public, Virtual
|
||||
// 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.
|
||||
// invokes the object itself.
|
||||
//
|
||||
// If needs_response is true, the return value is a
|
||||
// new-reference P3D_object on success, or NULL on
|
||||
// failure. If needs_response is false, the return
|
||||
// value is always NULL, and there is no way to
|
||||
// determine success or failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_object *P3DPythonObject::
|
||||
call(const string &method_name, P3D_object *params[], int num_params) {
|
||||
call(const string &method_name, bool needs_response,
|
||||
P3D_object *params[], int num_params) {
|
||||
TiXmlDocument *doc = new TiXmlDocument;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||
TiXmlElement *xcommand = new TiXmlElement("command");
|
||||
@ -248,6 +254,16 @@ call(const string &method_name, P3D_object *params[], int num_params) {
|
||||
|
||||
doc->LinkEndChild(decl);
|
||||
doc->LinkEndChild(xcommand);
|
||||
|
||||
// If no response is requested, send the command out in a vacuum,
|
||||
// and return NULL.
|
||||
if (!needs_response) {
|
||||
_session->send_command(doc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If a response is requested, we have to send the command and wait
|
||||
// for it.
|
||||
TiXmlDocument *response = _session->command_and_response(doc);
|
||||
|
||||
P3D_object *result = NULL;
|
||||
@ -274,7 +290,7 @@ call(const string &method_name, P3D_object *params[], int num_params) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DPythonObject::
|
||||
output(ostream &out) {
|
||||
P3D_object *result = call("__repr__", NULL, 0);
|
||||
P3D_object *result = call("__repr__", true, NULL, 0);
|
||||
out << "Python " << _object_id;
|
||||
if (result != NULL) {
|
||||
out << ": " << *result;
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
virtual bool set_property(const string &property, P3D_object *value);
|
||||
|
||||
virtual bool has_method(const string &method_name);
|
||||
virtual P3D_object *call(const string &method_name,
|
||||
virtual P3D_object *call(const string &method_name, bool needs_response,
|
||||
P3D_object *params[], int num_params);
|
||||
|
||||
virtual void output(ostream &out);
|
||||
|
@ -189,17 +189,24 @@ has_method(const string &method_name) {
|
||||
// Access: Public, Virtual
|
||||
// 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.
|
||||
// invokes the object itself.
|
||||
//
|
||||
// If needs_response is true, the return value is a
|
||||
// new-reference P3D_object on success, or NULL on
|
||||
// failure. If needs_response is false, the return
|
||||
// value is always NULL, and there is no way to
|
||||
// determine success or failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3D_object *P3DToplevelObject::
|
||||
call(const string &method_name, P3D_object *params[], int num_params) {
|
||||
call(const string &method_name, bool needs_response,
|
||||
P3D_object *params[], int num_params) {
|
||||
if (_pyobj == NULL) {
|
||||
// No methods until we get our pyobj.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return P3D_OBJECT_CALL(_pyobj, method_name.c_str(), params, num_params);
|
||||
return P3D_OBJECT_CALL(_pyobj, method_name.c_str(), needs_response,
|
||||
params, num_params);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
virtual bool set_property(const string &property, P3D_object *value);
|
||||
|
||||
virtual bool has_method(const string &method_name);
|
||||
virtual P3D_object *call(const string &method_name,
|
||||
virtual P3D_object *call(const string &method_name, bool needs_response,
|
||||
P3D_object *params[], int num_params);
|
||||
|
||||
virtual void output(ostream &out);
|
||||
|
@ -205,10 +205,12 @@ P3D_object_has_method(P3D_object *object, const char *method_name) {
|
||||
|
||||
P3D_object *
|
||||
P3D_object_call(P3D_object *object, const char *method_name,
|
||||
bool needs_response,
|
||||
P3D_object *params[], int num_params) {
|
||||
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
|
||||
ACQUIRE_LOCK(_api_lock);
|
||||
P3D_object *result = P3D_OBJECT_CALL(object, method_name, params, num_params);
|
||||
P3D_object *result = P3D_OBJECT_CALL(object, method_name, needs_response,
|
||||
params, num_params);
|
||||
RELEASE_LOCK(_api_lock);
|
||||
return result;
|
||||
}
|
||||
|
@ -406,10 +406,13 @@ P3D_object_has_method_method(P3D_object *object, const char *method_name);
|
||||
these objects' reference counts is not transferred with the call
|
||||
(you must still DECREF these objects afterwards).
|
||||
|
||||
The return value is a new-reference P3D_object on success, or NULL
|
||||
on failure. */
|
||||
If needs_response is true, the return value is a new-reference
|
||||
P3D_object on success, or NULL on failure. If needs_response is
|
||||
false, the return value is always NULL, and there is no way to
|
||||
determine success or failure. */
|
||||
typedef P3D_object *
|
||||
P3D_object_call_method(P3D_object *object, const char *method_name,
|
||||
bool needs_response,
|
||||
P3D_object *params[], int num_params);
|
||||
|
||||
/* Evaluates an arbitrary JavaScript expression in the context of the
|
||||
@ -468,7 +471,7 @@ struct _P3D_object {
|
||||
#define P3D_OBJECT_SET_PROPERTY(object, property, value) ((object)->_class->_set_property((object), (property), (value)))
|
||||
|
||||
#define P3D_OBJECT_HAS_METHOD(object, method_name) ((object)->_class->_has_method((object), (method_name)))
|
||||
#define P3D_OBJECT_CALL(object, method_name, params, num_params) ((object)->_class->_call((object), (method_name), (params), (num_params)))
|
||||
#define P3D_OBJECT_CALL(object, method_name, needs_response, params, num_params) ((object)->_class->_call((object), (method_name), (needs_response), (params), (num_params)))
|
||||
#define P3D_OBJECT_EVAL(object, expression) ((object)->_class->_eval((object), (expression)))
|
||||
|
||||
/* These macros are provided to manipulate the reference count of the
|
||||
@ -506,6 +509,7 @@ typedef bool
|
||||
P3D_object_has_method_func(P3D_object *object, const char *method_name);
|
||||
typedef P3D_object *
|
||||
P3D_object_call_func(P3D_object *object, const char *method_name,
|
||||
bool needs_response,
|
||||
P3D_object *params[], int num_params);
|
||||
typedef P3D_object *
|
||||
P3D_object_eval_func(P3D_object *object, const char *expression);
|
||||
|
@ -44,11 +44,19 @@ object_set_property(P3D_object *object, const char *property,
|
||||
|
||||
static P3D_object *
|
||||
object_call(P3D_object *object, const char *method_name,
|
||||
bool needs_response,
|
||||
P3D_object *params[], int num_params) {
|
||||
if (method_name == NULL) {
|
||||
method_name = "";
|
||||
}
|
||||
return ((const PPBrowserObject *)object)->call(method_name, params, num_params);
|
||||
P3D_object *response = ((const PPBrowserObject *)object)->call(method_name, params, num_params);
|
||||
if (!needs_response) {
|
||||
// No response was expected. Throw away the response we received,
|
||||
// so we can be consistent with defined semantics.
|
||||
P3D_OBJECT_XDECREF(response);
|
||||
response = NULL;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
static P3D_object *
|
||||
|
@ -143,7 +143,7 @@ invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount,
|
||||
}
|
||||
|
||||
P3D_object *value = P3D_OBJECT_CALL(_p3d_object, method_name.c_str(),
|
||||
p3dargs, argCount);
|
||||
true, p3dargs, argCount);
|
||||
for (i = 0; i < argCount; ++i) {
|
||||
P3D_OBJECT_DECREF(p3dargs[i]);
|
||||
}
|
||||
@ -181,7 +181,7 @@ invoke_default(const NPVariant *args, uint32_t argCount,
|
||||
p3dargs[i] = _instance->variant_to_p3dobj(&args[i]);
|
||||
}
|
||||
|
||||
P3D_object *value = P3D_OBJECT_CALL(_p3d_object, "",
|
||||
P3D_object *value = P3D_OBJECT_CALL(_p3d_object, "", true,
|
||||
p3dargs, argCount);
|
||||
for (i = 0; i < argCount; ++i) {
|
||||
P3D_OBJECT_DECREF(p3dargs[i]);
|
||||
|
@ -6,7 +6,7 @@ code that runs in a browser via the web plugin. """
|
||||
class UndefinedObject:
|
||||
""" This is a special object that is returned by the browser to
|
||||
represent an "undefined" value, typically the value for an
|
||||
uninitialize variable or undefined property. It has no
|
||||
uninitialized variable or undefined property. It has no
|
||||
attributes, similar to None, but it is a slightly different
|
||||
concept in JavaScript. """
|
||||
|
||||
@ -48,7 +48,11 @@ class BrowserObject:
|
||||
|
||||
# This element is filled in by __getattr__; it connects
|
||||
# the object to its parent.
|
||||
self.__dict__['_BrowserObject__boundMethod'] = (None, None)
|
||||
self.__dict__['_BrowserObject__childObject'] = (None, None)
|
||||
|
||||
# This is a cache of method names to MethodWrapper objects in
|
||||
# the parent object.
|
||||
self.__dict__['_BrowserObject__methods'] = {}
|
||||
|
||||
def __del__(self):
|
||||
# When the BrowserObject destructs, tell the parent process it
|
||||
@ -56,8 +60,23 @@ class BrowserObject:
|
||||
# more.
|
||||
self.__runner.dropObject(self.__objectId)
|
||||
|
||||
def __cacheMethod(self, methodName):
|
||||
""" Stores a pointer to the named method on this object, so
|
||||
that the next time __getattr__ is called, it can retrieve the
|
||||
method wrapper without having to query the browser. This
|
||||
cache assumes that callable methods don't generally come and
|
||||
go on and object.
|
||||
|
||||
The return value is the MethodWrapper object. """
|
||||
|
||||
method = self.__methods.get(methodName, None)
|
||||
if method is None:
|
||||
method = MethodWrapper(self.__runner, self, methodName)
|
||||
self.__methods[methodName] = method
|
||||
return method
|
||||
|
||||
def __str__(self):
|
||||
parentObj, attribName = self.__boundMethod
|
||||
parentObj, attribName = self.__childObject
|
||||
if parentObj:
|
||||
# Format it from its parent.
|
||||
return "%s.%s" % (parentObj, attribName)
|
||||
@ -77,7 +96,7 @@ class BrowserObject:
|
||||
raise ArgumentError, 'Keyword arguments not supported'
|
||||
|
||||
try:
|
||||
parentObj, attribName = self.__boundMethod
|
||||
parentObj, attribName = self.__childObject
|
||||
if parentObj:
|
||||
# Call it as a method.
|
||||
if parentObj is self.__runner.dom and attribName == 'alert':
|
||||
@ -102,6 +121,12 @@ class BrowserObject:
|
||||
except EnvironmentError:
|
||||
# Problem on the call. Maybe no such method?
|
||||
raise AttributeError
|
||||
|
||||
# Hey, the method call appears to have succeeded.
|
||||
# Cache the method object on the parent so we won't
|
||||
# have to look up the method wrapper again next time.
|
||||
parentObj.__cacheMethod(attribName)
|
||||
|
||||
else:
|
||||
# Call it as a plain function.
|
||||
result = self.__runner.scriptRequest('call', self, value = args, needsResponse = needsResponse)
|
||||
@ -116,6 +141,13 @@ class BrowserObject:
|
||||
into the appropriate calls to query the actual browser object
|
||||
under the hood. """
|
||||
|
||||
# First check to see if there's a cached method wrapper from a
|
||||
# previous call.
|
||||
method = self.__methods.get(name, None)
|
||||
if method:
|
||||
return method
|
||||
|
||||
# No cache. Go query the browser for the desired value.
|
||||
try:
|
||||
value = self.__runner.scriptRequest('get_property', self,
|
||||
propertyName = name)
|
||||
@ -124,7 +156,7 @@ class BrowserObject:
|
||||
# method instead?
|
||||
if self.__runner.scriptRequest('has_method', self, propertyName = name):
|
||||
# Yes, so create a method wrapper for it.
|
||||
return MethodWrapper(self.__runner, self, name)
|
||||
return self.__cacheMethod(name)
|
||||
|
||||
raise AttributeError(name)
|
||||
|
||||
@ -133,7 +165,7 @@ class BrowserObject:
|
||||
# properly call a method. (Javascript needs to know the
|
||||
# method container at the time of the call, and doesn't
|
||||
# store it on the function object.)
|
||||
value.__dict__['_BrowserObject__boundMethod'] = (self, name)
|
||||
value.__dict__['_BrowserObject__childObject'] = (self, name)
|
||||
|
||||
return value
|
||||
|
||||
@ -205,10 +237,10 @@ class MethodWrapper:
|
||||
|
||||
def __init__(self, runner, parentObj, objectId):
|
||||
self.__dict__['_MethodWrapper__runner'] = runner
|
||||
self.__dict__['_MethodWraper__boundMethod'] = (parentObj, objectId)
|
||||
self.__dict__['_MethodWrapper__childObject'] = (parentObj, objectId)
|
||||
|
||||
def __str__(self):
|
||||
parentObj, attribName = self.__boundMethod
|
||||
parentObj, attribName = self.__childObject
|
||||
return "%s.%s" % (parentObj, attribName)
|
||||
|
||||
def __nonzero__(self):
|
||||
@ -223,7 +255,7 @@ class MethodWrapper:
|
||||
raise ArgumentError, 'Keyword arguments not supported'
|
||||
|
||||
try:
|
||||
parentObj, attribName = self.__boundMethod
|
||||
parentObj, attribName = self.__childObject
|
||||
# Call it as a method.
|
||||
if parentObj is self.__runner.dom and attribName == 'alert':
|
||||
# As a special hack, we don't wait for the return
|
||||
|
Loading…
x
Reference in New Issue
Block a user