P3DPythonObject et al

This commit is contained in:
David Rose 2009-07-03 20:27:50 +00:00
parent aa0e91de1f
commit 6f2591c642
29 changed files with 782 additions and 251 deletions

View File

@ -32,6 +32,7 @@
p3dListObject.h \
p3dMultifileReader.h p3dMultifileReader.I \
p3dPackage.h p3dPackage.I \
p3dPythonObject.h \
p3dSession.h p3dSession.I \
p3dSplashWindow.h p3dSplashWindow.I \
p3dStringObject.h \
@ -53,6 +54,7 @@
p3dListObject.cxx \
p3dMultifileReader.cxx \
p3dPackage.cxx \
p3dPythonObject.cxx \
p3dSession.cxx \
p3dSplashWindow.cxx \
p3dStringObject.cxx \

View File

@ -20,10 +20,7 @@
// Description:
////////////////////////////////////////////////////////////////////
P3DBoolObject::
P3DBoolObject(bool value) :
P3DObject(P3D_OT_bool),
_value(value)
{
P3DBoolObject(bool value) : _value(value) {
}
////////////////////////////////////////////////////////////////////
@ -39,13 +36,13 @@ P3DBoolObject(const P3DBoolObject &copy) :
}
////////////////////////////////////////////////////////////////////
// Function: P3DBoolObject::make_copy
// Function: P3DBoolObject::get_type
// Access: Public, Virtual
// Description:
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3DObject *P3DBoolObject::
make_copy() const {
return new P3DBoolObject(*this);
P3D_object_type P3DBoolObject::
get_type() const {
return P3D_OT_bool;
}
////////////////////////////////////////////////////////////////////

View File

@ -28,7 +28,7 @@ public:
P3DBoolObject(const P3DBoolObject &copy);
public:
virtual P3DObject *make_copy() const;
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual int get_int() const;
virtual void make_string(string &value) const;

View File

@ -20,10 +20,7 @@
// Description:
////////////////////////////////////////////////////////////////////
P3DFloatObject::
P3DFloatObject(double value) :
P3DObject(P3D_OT_float),
_value(value)
{
P3DFloatObject(double value) : _value(value) {
}
////////////////////////////////////////////////////////////////////
@ -39,13 +36,13 @@ P3DFloatObject(const P3DFloatObject &copy) :
}
////////////////////////////////////////////////////////////////////
// Function: P3DFloatObject::make_copy
// Function: P3DFloatObject::get_type
// Access: Public, Virtual
// Description:
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3DObject *P3DFloatObject::
make_copy() const {
return new P3DFloatObject(*this);
P3D_object_type P3DFloatObject::
get_type() const {
return P3D_OT_float;
}
////////////////////////////////////////////////////////////////////

View File

@ -28,7 +28,7 @@ public:
P3DFloatObject(const P3DFloatObject &copy);
public:
virtual P3DObject *make_copy() const;
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual int get_int() const;
virtual double get_float() const;

View File

@ -21,6 +21,7 @@
#include "p3dWinSplashWindow.h"
#include "p3dObject.h"
#include "p3dNoneObject.h"
#include "p3dPythonObject.h"
#include <sstream>
#include <algorithm>
@ -159,54 +160,43 @@ set_wparams(const P3DWindowParams &wparams) {
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::get_property
// Function: P3DInstance::get_script_object
// Access: Public
// Description: Returns the value of the named property, or NULL
// if there is no such property. Properties are created
// by the script run within the instance; they are used
// for communicating between scripting languages (for
// instance, communication between the Python-based
// Panda application, and the Javascript on the
// containing web page).
// 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_property(const string &property_name) const {
return NULL;
}
get_script_object() const {
assert(_session != NULL);
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::get_property_list
// Access: Public
// Description: Returns a list of subordinate properties below the
// named property.
////////////////////////////////////////////////////////////////////
P3DObject *P3DInstance::
get_property_list(const string &property_name) const {
return NULL;
}
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");
doc->LinkEndChild(decl);
doc->LinkEndChild(xcommand);
TiXmlDocument *response = _session->command_and_response(doc);
nout << "response pointer: " << response << "\n" << flush;
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::set_property
// Access: Public
// Description: Changes the value of the named property, or deletes
// it if value is NULL. If the named property does not
// already exist, creates it. Returns true on success,
// false on failure.
////////////////////////////////////////////////////////////////////
bool P3DInstance::
set_property(const string &property_name, const P3DObject *value) {
return false;
}
P3DObject *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);
}
}
delete response;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::call
// Access: Public
// Description: Calls the named property as a method, supplying the
// indicated parameters.
////////////////////////////////////////////////////////////////////
P3DObject *P3DInstance::
call(const string &property_name, const P3DObject *params) {
return new P3DNoneObject;
nout << "Returning " << result << "\n" << flush;
if (result != NULL) {
nout << "result = " << *result << "\n" << flush;
}
return result;
}

View File

@ -46,11 +46,7 @@ public:
void set_wparams(const P3DWindowParams &wparams);
inline const P3DWindowParams &get_wparams() const;
P3DObject *get_property(const string &property_name) const;
P3DObject *get_property_list(const string &property_name) const;
bool set_property(const string &property_name,
const P3DObject *value);
P3DObject *call(const string &property_name, const P3DObject *params);
P3DObject *get_script_object() const;
bool has_request();
P3D_request *get_request();

View File

@ -20,10 +20,7 @@
// Description:
////////////////////////////////////////////////////////////////////
P3DIntObject::
P3DIntObject(int value) :
P3DObject(P3D_OT_int),
_value(value)
{
P3DIntObject(int value) : _value(value) {
}
////////////////////////////////////////////////////////////////////
@ -39,13 +36,13 @@ P3DIntObject(const P3DIntObject &copy) :
}
////////////////////////////////////////////////////////////////////
// Function: P3DIntObject::make_copy
// Function: P3DIntObject::get_type
// Access: Public, Virtual
// Description:
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3DObject *P3DIntObject::
make_copy() const {
return new P3DIntObject(*this);
P3D_object_type P3DIntObject::
get_type() const {
return P3D_OT_int;
}
////////////////////////////////////////////////////////////////////

View File

@ -28,7 +28,7 @@ public:
P3DIntObject(const P3DIntObject &copy);
public:
virtual P3DObject *make_copy() const;
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual int get_int() const;
virtual void make_string(string &value) const;

View File

@ -21,7 +21,7 @@
// Description:
////////////////////////////////////////////////////////////////////
P3DListObject::
P3DListObject() : P3DObject(P3D_OT_list) {
P3DListObject() {
}
////////////////////////////////////////////////////////////////////
@ -56,13 +56,26 @@ P3DListObject::
////////////////////////////////////////////////////////////////////
// Function: P3DListObject::make_copy
// Access: Public, Virtual
// Description:
// Description: Returns a new copy of the object, if necessary. If
// the object type is static and all instances are
// identical, this actually simply ups the reference
// count and returns the same object.
////////////////////////////////////////////////////////////////////
P3DObject *P3DListObject::
make_copy() const {
return new P3DListObject(*this);
}
////////////////////////////////////////////////////////////////////
// Function: P3DListObject::get_type
// Access: Public, Virtual
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DListObject::
get_type() const {
return P3D_OT_list;
}
////////////////////////////////////////////////////////////////////
// Function: P3DListObject::get_bool
// Access: Public, Virtual
@ -153,6 +166,17 @@ set_element(int n, P3D_object *value) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: P3DListObject::append
// Access: Public, Virtual
// Description: Adds a new element to the end of the list. Ownership
// is transferred to the list.
////////////////////////////////////////////////////////////////////
void P3DListObject::
append(P3D_object *value) {
_elements.push_back(value);
}
////////////////////////////////////////////////////////////////////
// Function: P3DListObject::make_xml
// Access: Public, Virtual

View File

@ -31,12 +31,15 @@ public:
virtual ~P3DListObject();
virtual P3DObject *make_copy() const;
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual void make_string(string &value) const;
virtual int get_list_length() const;
virtual P3D_object *get_element(int n) const;
virtual bool set_element(int n, P3D_object *value);
void append(P3D_object *value);
virtual TiXmlElement *make_xml() const;
private:

View File

@ -20,17 +20,17 @@
// Description:
////////////////////////////////////////////////////////////////////
P3DNoneObject::
P3DNoneObject() : P3DObject(P3D_OT_none) {
P3DNoneObject() {
}
////////////////////////////////////////////////////////////////////
// Function: P3DNoneObject::make_copy
// Function: P3DNoneObject::get_type
// Access: Public, Virtual
// Description:
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3DObject *P3DNoneObject::
make_copy() const {
return new P3DNoneObject(*this);
P3D_object_type P3DNoneObject::
get_type() const {
return P3D_OT_none;
}
////////////////////////////////////////////////////////////////////

View File

@ -28,7 +28,7 @@ public:
P3DNoneObject();
public:
virtual P3DObject *make_copy() const;
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual void make_string(string &value) const;

View File

@ -19,9 +19,11 @@
// Description:
////////////////////////////////////////////////////////////////////
inline P3DObject::
P3DObject(P3D_object_type type) {
P3DObject() {
_class = &_object_class;
_type = type;
// The reference count is initially 1.
_ref_count = 1;
}
////////////////////////////////////////////////////////////////////
@ -31,15 +33,43 @@ P3DObject(P3D_object_type type) {
////////////////////////////////////////////////////////////////////
inline P3DObject::
P3DObject(const P3DObject &copy) {
_type = copy._type;
assert(copy._class == &_object_class);
_class = copy._class;
_ref_count = 1;
}
////////////////////////////////////////////////////////////////////
// Function: P3DObject::get_type
// Function: P3DObject::ref
// Access: Public
// Description: Returns the fundamental type of this kind of object.
// Description: Increments the reference count.
////////////////////////////////////////////////////////////////////
inline P3D_object_type P3DObject::
get_type() const {
return _type;
inline void P3DObject::
ref() const {
++(((P3DObject *)this)->_ref_count);
}
////////////////////////////////////////////////////////////////////
// Function: P3DObject::unref
// Access: Public
// Description: Decrements the reference count, and returns the new
// count.
////////////////////////////////////////////////////////////////////
inline int P3DObject::
unref() const {
--(((P3DObject *)this)->_ref_count);
return _ref_count;
}
////////////////////////////////////////////////////////////////////
// Function: P3DObject::unref_delete
// Access: Public, Static
// Description: Decrements the reference count on the indicated
// object, and deletes it if the reference count reaches
// zero.
////////////////////////////////////////////////////////////////////
inline void P3DObject::
unref_delete(P3DObject *obj) {
if (obj->unref() <= 0) {
delete obj;
}
}

View File

@ -21,7 +21,7 @@
// P3D_object structure.
static void
object_finish(P3D_object *object) {
delete ((P3DObject *)object);
P3DObject::unref_delete(((P3DObject *)object));
}
static P3D_object *
@ -85,13 +85,12 @@ static int object_get_list_length(const P3D_object *object) {
}
static P3D_object *
object_call(const P3D_object *object, P3D_object *params) {
return ((const P3DObject *)object)->call(params);
}
static P3D_object *
object_evaluate(const P3D_object *object, const char *expression) {
return ((const P3DObject *)object)->evaluate(expression);
object_call(const P3D_object *object, const char *method_name,
P3D_object *params) {
if (method_name == NULL) {
method_name = "";
}
return ((const P3DObject *)object)->call(method_name, params);
}
P3D_class_definition P3DObject::_object_class = {
@ -109,7 +108,6 @@ P3D_class_definition P3DObject::_object_class = {
&object_set_element,
&object_get_list_length,
&object_call,
&object_evaluate,
};
////////////////////////////////////////////////////////////////////
@ -119,7 +117,20 @@ P3D_class_definition P3DObject::_object_class = {
////////////////////////////////////////////////////////////////////
P3DObject::
~P3DObject() {
_type = P3D_OT_none;
}
////////////////////////////////////////////////////////////////////
// Function: P3DObject::make_copy
// Access: Public, Virtual
// Description: Returns a new copy of the object, if necessary. If
// the object type is static and all instances are
// identical, this actually simply ups the reference
// count and returns the same object.
////////////////////////////////////////////////////////////////////
P3DObject *P3DObject::
make_copy() const {
ref();
return (P3DObject *)this;
}
////////////////////////////////////////////////////////////////////
@ -244,30 +255,19 @@ set_element(int n, P3D_object *value) {
////////////////////////////////////////////////////////////////////
// Function: P3DObject::call
// Access: Public, Virtual
// Description: Invokes the object as a method, passing the indicated
// parameters. Returns the return value on success,
// NULL on error.
// 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 *P3DObject::
call(P3D_object *params) const {
call(const string &method_name, P3D_object *params) const {
if (params != NULL) {
P3D_OBJECT_FINISH(params);
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: P3DObject::evaluate
// Access: Public, Virtual
// Description: Evaluates an arbitrary script expression within the
// context of this object. Returns the return value on
// success, NULL on error.
////////////////////////////////////////////////////////////////////
P3D_object *P3DObject::
evaluate(const string &expression) const {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: P3DObject::output
// Access: Public, Virtual

View File

@ -27,14 +27,14 @@
////////////////////////////////////////////////////////////////////
class P3DObject : public P3D_object {
protected:
inline P3DObject(P3D_object_type type);
inline P3DObject();
inline P3DObject(const P3DObject &copy);
public:
virtual ~P3DObject();
virtual P3DObject *make_copy() const=0;
inline P3D_object_type get_type() const;
virtual P3DObject *make_copy() const;
virtual P3D_object_type get_type() const=0;
virtual bool get_bool() const=0;
virtual int get_int() const;
virtual double get_float() const;
@ -50,15 +50,18 @@ public:
virtual P3D_object *get_element(int n) const;
virtual bool set_element(int n, P3D_object *value);
virtual P3D_object *call(P3D_object *params) const;
virtual P3D_object *evaluate(const string &expression) const;
virtual P3D_object *call(const string &method_name, P3D_object *params) const;
virtual TiXmlElement *make_xml() const=0;
virtual void output(ostream &out) const;
protected:
P3D_object_type _type;
inline void ref() const;
inline int unref() const;
static inline void unref_delete(P3DObject *obj);
private:
int _ref_count;
public:
static P3D_class_definition _object_class;

View File

@ -0,0 +1,302 @@
// Filename: p3dPythonObject.cxx
// Created by: drose (03Jul09)
//
////////////////////////////////////////////////////////////////////
//
// 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 "p3dPythonObject.h"
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
P3DPythonObject::
P3DPythonObject(P3DSession *session, int object_id) :
_session(session),
_object_id(object_id)
{
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
P3DPythonObject::
~P3DPythonObject() {
// TODO.
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::get_type
// Access: Public, Virtual
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DPythonObject::
get_type() const {
return P3D_OT_object;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::get_bool
// Access: Public, Virtual
// Description: Returns the object value coerced to a boolean, if
// possible.
////////////////////////////////////////////////////////////////////
bool P3DPythonObject::
get_bool() const {
bool bresult = 0;
P3D_object *result = call("__bool__", NULL);
if (result != NULL) {
bresult = P3D_OBJECT_GET_BOOL(result);
P3D_OBJECT_FINISH(result);
}
return bresult;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::get_int
// Access: Public, Virtual
// Description: Returns the object value coerced to an integer, if
// possible.
////////////////////////////////////////////////////////////////////
int P3DPythonObject::
get_int() const {
int iresult = 0;
P3D_object *result = call("__int__", NULL);
if (result != NULL) {
iresult = P3D_OBJECT_GET_INT(result);
P3D_OBJECT_FINISH(result);
}
return iresult;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::get_float
// Access: Public, Virtual
// Description: Returns the object value coerced to a floating-point
// value, if possible.
////////////////////////////////////////////////////////////////////
double P3DPythonObject::
get_float() const {
double fresult = 0.0;
P3D_object *result = call("__float__", NULL);
if (result != NULL) {
fresult = P3D_OBJECT_GET_FLOAT(result);
P3D_OBJECT_FINISH(result);
}
return fresult;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::make_string
// Access: Public, Virtual
// Description: Fills the indicated C++ string object with the value
// of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DPythonObject::
make_string(string &value) const {
P3D_object *result = call("__str__", NULL);
if (result != NULL) {
int size = P3D_OBJECT_GET_STRING(result, NULL, 0);
char *buffer = new char[size];
P3D_OBJECT_GET_STRING(result, buffer, size);
value = string(buffer, size);
delete[] buffer;
P3D_OBJECT_FINISH(result);
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::get_property
// Access: Public, Virtual
// Description: Returns the named property element in the object. The
// return value is a freshly-allocated P3DPythonObject object
// that must be deleted by the caller, or NULL on error.
////////////////////////////////////////////////////////////////////
P3D_object *P3DPythonObject::
get_property(const string &property) const {
P3DListObject *params = new P3DListObject;
params->append(new P3DStringObject(property));
P3D_object *result = call("__getattr__", params);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::set_property
// Access: Public, Virtual
// Description: Modifies (or deletes, if value is NULL) the named
// property element in the object. Returns true on
// success, false on failure.
////////////////////////////////////////////////////////////////////
bool P3DPythonObject::
set_property(const string &property, P3D_object *value) {
bool bresult = false;
P3DListObject *params = new P3DListObject;
params->append(new P3DStringObject(property));
P3D_object *result = NULL;
if (value == NULL) {
// Delete an attribute.
result = call("__delattr__", params);
} else {
// Set a new attribute.
params->append(value);
result = call("__setattr__", params);
}
if (result != NULL) {
bresult = P3D_OBJECT_GET_BOOL(result);
P3D_OBJECT_FINISH(result);
}
return bresult;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::get_list_length
// Access: Public, Virtual
// Description: Returns the length of the object as a list.
////////////////////////////////////////////////////////////////////
int P3DPythonObject::
get_list_length() const {
// TODO.
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::get_element
// Access: Public, Virtual
// Description: Returns the nth item in the value as a list. The
// return value is a freshly-allocated P3DPythonObject object
// that must be deleted by the caller, or NULL on error.
////////////////////////////////////////////////////////////////////
P3D_object *P3DPythonObject::
get_element(int n) const {
// TODO.
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::set_element
// Access: Public, Virtual
// Description: Modifies (or deletes, if value is NULL) the nth item
// in the value as a list. Returns true on success,
// false on failure.
////////////////////////////////////////////////////////////////////
bool P3DPythonObject::
set_element(int n, P3D_object *value) {
// TODO.
if (value != NULL) {
P3D_OBJECT_FINISH(value);
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::call
// 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.
////////////////////////////////////////////////////////////////////
P3D_object *P3DPythonObject::
call(const string &method_name, P3D_object *params) const {
TiXmlDocument *doc = new TiXmlDocument;
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
TiXmlElement *xcommand = new TiXmlElement("command");
xcommand->SetAttribute("cmd", "pyobj");
xcommand->SetAttribute("op", "call");
xcommand->SetAttribute("object_id", _object_id);
if (!method_name.empty()) {
xcommand->SetAttribute("method_name", method_name);
}
if (params != NULL) {
assert(params->_class == &P3DObject::_object_class);
TiXmlElement *xparams = ((P3DObject *)params)->make_xml();
xcommand->LinkEndChild(xparams);
// Now we're done with the params object passed in, we can delete
// it as promised.
P3D_OBJECT_FINISH(params);
}
doc->LinkEndChild(decl);
doc->LinkEndChild(xcommand);
TiXmlDocument *response = _session->command_and_response(doc);
nout << "call response pointer: " << response << "\n" << flush;
P3DObject *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);
}
}
delete response;
}
nout << "call result = " << result << "\n" << flush;
if (result != NULL) {
nout << " result = " << *result << "\n" << flush;
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::output
// Access: Public, Virtual
// Description: Writes a formatted representation of the value to the
// indicated string. This is intended for developer
// assistance.
////////////////////////////////////////////////////////////////////
void P3DPythonObject::
output(ostream &out) const {
P3D_object *result = call("__repr__", NULL);
out << "Python " << _object_id;
if (result != NULL) {
out << ": " << *result;
P3D_OBJECT_FINISH(result);
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonObject::make_xml
// Access: Public, Virtual
// Description: Allocates and returns a new XML structure
// corresponding to this value.
////////////////////////////////////////////////////////////////////
TiXmlElement *P3DPythonObject::
make_xml() const {
TiXmlElement *xvalue = new TiXmlElement("value");
xvalue->SetAttribute("type", "python");
xvalue->SetAttribute("object_id", _object_id);
return xvalue;
}

View File

@ -0,0 +1,63 @@
// Filename: p3dPythonObject.h
// Created by: drose (02Jul09)
//
////////////////////////////////////////////////////////////////////
//
// 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 P3DPYTHONOBJECT_H
#define P3DPYTHONOBJECT_H
#include "p3d_plugin_common.h"
#include "p3dObject.h"
class P3DSession;
////////////////////////////////////////////////////////////////////
// Class : P3DPythonObject
// Description : An object type that references a PyObject in the
// subordinate process. It allows querying and/or
// modifying the state of the referenced PyObject, via
// clever XML communication in
// P3DSession::command_and_response().
////////////////////////////////////////////////////////////////////
class P3DPythonObject : public P3DObject {
public:
P3DPythonObject(P3DSession *session, int object_id);
virtual ~P3DPythonObject();
public:
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual int get_int() const;
virtual double get_float() const;
virtual void make_string(string &value) const;
virtual P3D_object *get_property(const string &property) const;
virtual bool set_property(const string &property, P3D_object *value);
virtual int get_list_length() const;
virtual P3D_object *get_element(int n) const;
virtual bool set_element(int n, P3D_object *value);
virtual P3D_object *call(const string &method_name, P3D_object *params) const;
virtual TiXmlElement *make_xml() const;
virtual void output(ostream &out) const;
private:
P3DSession *_session;
int _object_id;
};
#endif

View File

@ -273,7 +273,104 @@ handle_pyobj_command(TiXmlElement *xcommand, int want_response_id) {
if (op != NULL) {
if (strcmp(op, "get_script_object") == 0) {
// Get the toplevel Python object.
xresponse->SetAttribute("object", "fooby");
PyObject *obj = PyObject_GetAttrString(_runner, "scriptRoot");
if (obj != NULL) {
xresponse->LinkEndChild(pyobj_to_xml(obj));
Py_DECREF(obj);
}
} else if (strcmp(op, "call") == 0) {
// Call the named method on the indicated object, or the object
// itself if method_name isn't given.
int object_id;
if (xcommand->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
PyObject *obj = (PyObject *)(void *)object_id;
const char *method_name = xcommand->Attribute("method_name");
PyObject *params = NULL;
TiXmlElement *xvalue = xcommand->FirstChildElement("value");
if (xvalue != NULL) {
params = xml_to_pyobj(xvalue);
if (!PySequence_Check(params)) {
// Wrap it in a tuple to pass it to the method.
PyObject *tuple = PyTuple_New(1);
PyTuple_SetItem(tuple, 0, params);
params = tuple;
}
}
if (params == NULL) {
params = PyTuple_New(0);
}
// Now call the method.
PyObject *result = NULL;
if (method_name == NULL) {
// No method name; call the object directly.
result = PyObject_CallObject(obj, params);
// Several special-case "method" names.
} else if (strcmp(method_name, "__bool__") == 0) {
result = PyBool_FromLong(PyObject_IsTrue(obj));
} else if (strcmp(method_name, "__int__") == 0) {
result = PyNumber_Int(obj);
} else if (strcmp(method_name, "__float__") == 0) {
result = PyNumber_Float(obj);
} else if (strcmp(method_name, "__repr__") == 0) {
result = PyObject_Repr(obj);
} else if (strcmp(method_name, "__str__") == 0) {
result = PyObject_Str(obj);
} else if (strcmp(method_name, "__setattr__") == 0) {
const char *property_name;
PyObject *value;
if (PyArg_ParseTuple(params, "sO", &property_name, &value)) {
PyObject_SetAttrString(obj, property_name, value);
result = Py_True;
Py_INCREF(result);
}
} else if (strcmp(method_name, "__delattr__") == 0) {
const char *property_name;
if (PyArg_ParseTuple(params, "s", &property_name)) {
if (PyObject_HasAttrString(obj, property_name)) {
PyObject_DelAttrString(obj, property_name);
result = Py_True;
} else {
result = Py_False;
}
Py_INCREF(result);
}
} else if (strcmp(method_name, "__getattr__") == 0) {
const char *property_name;
if (PyArg_ParseTuple(params, "s", &property_name)) {
if (PyObject_HasAttrString(obj, property_name)) {
result = PyObject_GetAttrString(obj, property_name);
} else {
result = NULL;
}
}
} else {
// Not a special-case name. Call the named method.
PyObject *method = PyObject_GetAttrString(obj, method_name);
if (method != NULL) {
result = PyObject_CallObject(method, params);
Py_DECREF(method);
}
}
Py_DECREF(params);
// Feed the return value back through the XML pipe to the
// caller.
if (result != NULL) {
xresponse->LinkEndChild(pyobj_to_xml(result));
Py_DECREF(result);
}
}
}
}
@ -622,14 +719,14 @@ terminate_session() {
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonRun::make_xml_value
// Function: P3DPythonRun::pyobj_to_xml
// Access: Private
// Description: Converts the indicated PyObject to the appropriate
// XML representation of a P3D_value type, and returns a
// freshly-allocated TiXmlElement.
////////////////////////////////////////////////////////////////////
TiXmlElement *P3DPythonRun::
make_xml_value(PyObject *value) {
pyobj_to_xml(PyObject *value) {
TiXmlElement *xvalue = new TiXmlElement("value");
if (value == Py_None) {
// None.
@ -690,42 +787,43 @@ make_xml_value(PyObject *value) {
xvalue->SetAttribute("value", str);
}
} else if (PySequence_Check(value)) {
// A sequence or list value.
} else if (PyTuple_CheckExact(value)) {
// A tuple. We check for this class type specifically; other
// objects that provide a sequence interface should be treated as
// generic Python objects, below, so we don't lose other useful
// functionality in these objects. Even a Python list, since we
// want to allow the caller to modify the list object on the
// Python side.
xvalue->SetAttribute("type", "list");
Py_ssize_t length = PySequence_Length(value);
for (Py_ssize_t i = 0; i < length; ++i) {
PyObject *obj = PySequence_GetItem(value, i);
xvalue->LinkEndChild(make_xml_value(obj));
xvalue->LinkEndChild(pyobj_to_xml(obj));
}
} else {
// Some other kind of object. Don't know what else to do with it;
// we'll make it a string.
xvalue->SetAttribute("type", "string");
PyObject *as_str = PyObject_Str(value);
if (as_str != NULL) {
char *buffer;
Py_ssize_t length;
if (PyString_AsStringAndSize(as_str, &buffer, &length) != -1) {
string str(buffer, length);
xvalue->SetAttribute("value", str);
}
Py_DECREF(as_str);
}
// 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.
xvalue->SetAttribute("type", "python");
xvalue->SetAttribute("object_id", (long)value);
// Temporary hack.
Py_INCREF(value);
}
return xvalue;
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonRun::from_xml_value
// Function: P3DPythonRun::xml_to_pyobj
// Access: Private
// Description: Converts the XML representation of a P3D_value type
// into the equivalent Python object and returns it.
////////////////////////////////////////////////////////////////////
PyObject *P3DPythonRun::
from_xml_value(TiXmlElement *xvalue) {
xml_to_pyobj(TiXmlElement *xvalue) {
const char *type = xvalue->Attribute("type");
if (strcmp(type, "none") == 0) {
return Py_BuildValue("");
@ -761,12 +859,20 @@ from_xml_value(TiXmlElement *xvalue) {
TiXmlElement *xchild = xvalue->FirstChildElement("value");
while (xchild != NULL) {
PyObject *child = from_xml_value(xchild);
PyObject *child = xml_to_pyobj(xchild);
PyList_Append(list, child);
Py_DECREF(child);
xchild = xchild->NextSiblingElement("value");
}
return list;
PyObject *tuple = PyList_AsTuple(list);
Py_DECREF(list);
return tuple;
} else if (strcmp(type, "python") == 0) {
int object_id;
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
return (PyObject *)(void *)object_id;
}
}
// Something went wrong in decoding.

View File

@ -90,8 +90,8 @@ private:
void terminate_session();
private:
TiXmlElement *make_xml_value(PyObject *value);
PyObject *from_xml_value(TiXmlElement *xvalue);
TiXmlElement *pyobj_to_xml(PyObject *value);
PyObject *xml_to_pyobj(TiXmlElement *xvalue);
private:
// This method runs only within the read thread.

View File

@ -16,6 +16,12 @@
#include "p3dInstance.h"
#include "p3dInstanceManager.h"
#include "p3d_plugin_config.h"
#include "p3dNoneObject.h"
#include "p3dBoolObject.h"
#include "p3dIntObject.h"
#include "p3dFloatObject.h"
#include "p3dListObject.h"
#include "p3dPythonObject.h"
#ifndef _WIN32
#include <fcntl.h>
@ -286,6 +292,66 @@ command_and_response(TiXmlDocument *command) {
return response;
}
////////////////////////////////////////////////////////////////////
// Function: P3DSession::xml_to_object
// Access: Public
// Description: Converts the XML representation of the particular
// object value into a corresponding P3DObject object.
// Returns the newly-allocated object.
////////////////////////////////////////////////////////////////////
P3DObject *P3DSession::
xml_to_object(TiXmlElement *xvalue) {
const char *type = xvalue->Attribute("type");
if (strcmp(type, "none") == 0) {
return new P3DNoneObject;
} else if (strcmp(type, "bool") == 0) {
int value;
if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) {
return new P3DBoolObject(value != 0);
}
} else if (strcmp(type, "int") == 0) {
int value;
if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) {
return new P3DIntObject(value);
}
} else if (strcmp(type, "float") == 0) {
double value;
if (xvalue->QueryDoubleAttribute("value", &value) == TIXML_SUCCESS) {
return new P3DFloatObject(value);
}
} else if (strcmp(type, "string") == 0) {
// Using the string form here instead of the char * form, so we
// don't get tripped up on embedded null characters.
const string *value = xvalue->Attribute(string("value"));
if (value != NULL) {
return new P3DStringObject(*value);
}
} else if (strcmp(type, "list") == 0) {
P3DListObject *list = new P3DListObject;
TiXmlElement *xchild = xvalue->FirstChildElement("value");
while (xchild != NULL) {
list->set_element(list->get_list_length(), xml_to_object(xchild));
xchild = xchild->NextSiblingElement("value");
}
return list;
} else if (strcmp(type, "python") == 0) {
int object_id;
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
return new P3DPythonObject(this, object_id);
}
}
// Something went wrong in decoding.
return new P3DNoneObject;
}
////////////////////////////////////////////////////////////////////
// Function: P3DSession::install_progress
// Access: Private
@ -392,22 +458,6 @@ start_p3dpython() {
}
_pipe_write << flush;
_commands.clear();
// Temp testing code.
{
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");
doc->LinkEndChild(decl);
doc->LinkEndChild(xcommand);
TiXmlDocument *response = command_and_response(doc);
nout << "response pointer: " << response << "\n";
if (response != NULL) {
delete response;
}
}
}
////////////////////////////////////////////////////////////////////
@ -573,60 +623,6 @@ rt_make_p3d_request(TiXmlElement *xrequest) {
return request;
}
////////////////////////////////////////////////////////////////////
// Function: P3DSession::rt_from_xml_value
// Access: Private
// Description: Converts the XML representation of the particular
// value value into a corresponding P3DObject object.
// Returns the newly-allocated object.
////////////////////////////////////////////////////////////////////
P3DObject *P3DSession::
rt_from_xml_value(TiXmlElement *xvalue) {
const char *type = xvalue->Attribute("type");
if (strcmp(type, "none") == 0) {
return new P3DNoneObject;
} else if (strcmp(type, "bool") == 0) {
int value;
if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) {
return new P3DBoolObject(value != 0);
}
} else if (strcmp(type, "int") == 0) {
int value;
if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) {
return new P3DIntObject(value);
}
} else if (strcmp(type, "float") == 0) {
double value;
if (xvalue->QueryDoubleAttribute("value", &value) == TIXML_SUCCESS) {
return new P3DFloatObject(value);
}
} else if (strcmp(type, "string") == 0) {
// Using the string form here instead of the char * form, so we
// don't get tripped up on embedded null characters.
const string *value = xvalue->Attribute(string("value"));
if (value != NULL) {
return new P3DStringObject(*value);
}
} else if (strcmp(type, "list") == 0) {
P3DListObject *list = new P3DListObject;
TiXmlElement *xchild = xvalue->FirstChildElement("value");
while (xchild != NULL) {
list->set_element(list->get_list_length(), rt_from_xml_value(xchild));
xchild = xchild->NextSiblingElement("value");
}
return list;
}
// Something went wrong in decoding.
return new P3DNoneObject;
}
////////////////////////////////////////////////////////////////////
// Function: P3DSession::rt_terminate
// Access: Private

View File

@ -49,6 +49,7 @@ public:
void send_command(TiXmlDocument *command);
TiXmlDocument *command_and_response(TiXmlDocument *command);
P3DObject *xml_to_object(TiXmlElement *xvalue);
private:
void install_progress(P3DPackage *package, double progress);
@ -63,7 +64,6 @@ private:
void rt_terminate();
void rt_handle_request(TiXmlDocument *doc);
P3D_request *rt_make_p3d_request(TiXmlElement *xrequest);
P3DObject *rt_from_xml_value(TiXmlElement *xvalue);
#ifdef _WIN32
static DWORD WINAPI win_rt_thread_run(LPVOID data);

View File

@ -20,10 +20,7 @@
// Description:
////////////////////////////////////////////////////////////////////
P3DStringObject::
P3DStringObject(const string &value) :
P3DObject(P3D_OT_string),
_value(value)
{
P3DStringObject(const string &value) : _value(value) {
}
////////////////////////////////////////////////////////////////////
@ -48,13 +45,13 @@ P3DStringObject::
}
////////////////////////////////////////////////////////////////////
// Function: P3DStringObject::make_copy
// Function: P3DStringObject::get_type
// Access: Public, Virtual
// Description:
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3DObject *P3DStringObject::
make_copy() const {
return new P3DStringObject(*this);
P3D_object_type P3DStringObject::
get_type() const {
return P3D_OT_string;
}
////////////////////////////////////////////////////////////////////

View File

@ -30,7 +30,7 @@ public:
public:
virtual ~P3DStringObject();
virtual P3DObject *make_copy() const;
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual void make_string(string &value) const;

View File

@ -203,8 +203,7 @@ P3D_instance_get_script_object(P3D_instance *instance) {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_lock);
// TODO.
P3D_object *result = NULL;
P3D_object *result = ((P3DInstance *)instance)->get_script_object();
RELEASE_LOCK(_lock);
return result;

View File

@ -388,21 +388,20 @@ P3D_object_set_element_method(P3D_object *object, int n, P3D_object *value);
typedef int
P3D_object_get_list_length_method(const P3D_object *object);
/* Invokes the object as a function. The params object should be a
list object containing the individual parameters; ownership of this
list object is transferred in this call, and it will automatically
be deleted. The return value is a newly-allocated P3D_object on
success, or NULL on failure. Ownership of the return value is
transferred to the caller. */
typedef P3D_object *
P3D_object_call_method(const P3D_object *object, P3D_object *params);
/* Invokes a named method on the object. If method_name is empty or
NULL, invokes the object itself as a function. The params object
should be a list object containing the individual parameters;
ownership of this list object is transferred in this call, and it
will automatically be deleted. It may also be NULL if no
parameters are required, or a single non-list parameter if only one
parameter is required.
/* Evaluates an arbitrary script expression, if possible, within the
context of the object. The return value is the return value of the
expression, or NULL on error. As above, ownership of the return
value is transferred to the caller. */
The return value is a newly-allocated P3D_object on success, or
NULL on failure. Ownership of the return value is transferred to
the caller. */
typedef P3D_object *
P3D_object_evaluate_method(const P3D_object *object, const char *expression);
P3D_object_call_method(const P3D_object *object, const char *method_name,
P3D_object *params);
/* This defines the class structure that implements all of the above
methods. */
@ -424,7 +423,6 @@ typedef struct _P3D_class_definition {
P3D_object_get_list_length_method *_get_list_length;
P3D_object_call_method *_call;
P3D_object_evaluate_method *_evaluate;
} P3D_class_definition;
@ -455,8 +453,7 @@ struct _P3D_object {
#define P3D_OBJECT_SET_ELEMENT(object, n, value) ((object)->_class->_set_element((object), (n), (value)))
#define P3D_OBJECT_GET_LIST_LENGTH(object, n, value) ((object)->_class->_get_list_length((object), (n), (value)))
#define P3D_OBJECT_CALL(object, params) ((object)->_class->_call((object), (params)))
#define P3D_OBJECT_EVALUATE(object, expression) ((object)->_class->_evaluate((object), (expression)))
#define P3D_OBJECT_CALL(object, method_name, params) ((object)->_class->_call((object), (method_name), (params)))
/* The following function types are once again meant to define

View File

@ -10,6 +10,7 @@
#include "p3dIntObject.cxx"
#include "p3dListObject.cxx"
#include "p3dMultifileReader.cxx"
#include "p3dPythonObject.cxx"
#include "p3dNoneObject.cxx"
#include "p3dObject.cxx"
#include "p3dPackage.cxx"

View File

@ -404,6 +404,28 @@ handle_request(P3D_request *request) {
cerr << "Got P3D_RT_notify: " << request->_request._notify._message
<< "\n";
// Ignore notifications.
// Temporary.
P3D_object *obj = P3D_instance_get_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))) {
cerr << "set_property succeeded\n";
P3D_object *prop = P3D_OBJECT_GET_PROPERTY(obj, "foo");
cerr << "get_property returned " << prop << "\n";
if (prop != NULL) {
int size = P3D_OBJECT_GET_STRING(prop, NULL, 0);
char *buffer = new char[size];
P3D_OBJECT_GET_STRING(prop, buffer, size);
cerr << " property is " << buffer << "\n";
delete buffer;
P3D_OBJECT_FINISH(prop);
}
} else {
cerr << "set_property failed\n";
}
P3D_OBJECT_FINISH(obj);
}
break;
default:

View File

@ -41,6 +41,12 @@ default-model-extension .bam
class ArgumentError(AttributeError):
pass
class ScriptRoot:
""" This dummy class serves as the root object for the scripting
interface. The Python code can store objects and functions here
for direct meddling by the browser's JavaScript code. """
pass
class AppRunner(DirectObject):
def __init__(self):
DirectObject.__init__(self)
@ -50,7 +56,10 @@ class AppRunner(DirectObject):
self.gotP3DFilename = False
self.started = False
self.windowPrc = None
# TODO: we need one of these per instance, not per session.
self.instanceId = None
self.scriptRoot = ScriptRoot()
# This is the default requestFunc that is installed if we
# never call setRequestFunc().