487 lines
17 KiB
C++
487 lines
17 KiB
C++
// Filename: ppPandaObject.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 "ppPandaObject.h"
|
|
|
|
NPClass PPPandaObject::_object_class = {
|
|
NP_CLASS_STRUCT_VERSION,
|
|
&PPPandaObject::NPAllocate,
|
|
&PPPandaObject::NPDeallocate,
|
|
&PPPandaObject::NPInvalidate,
|
|
&PPPandaObject::NPHasMethod,
|
|
&PPPandaObject::NPInvoke,
|
|
&PPPandaObject::NPInvokeDefault,
|
|
&PPPandaObject::NPHasProperty,
|
|
&PPPandaObject::NPGetProperty,
|
|
&PPPandaObject::NPSetProperty,
|
|
&PPPandaObject::NPRemoveProperty,
|
|
#if defined(NP_CLASS_STRUCT_VERSION_ENUM) && NP_CLASS_STRUCT_VERSION >= NP_CLASS_STRUCT_VERSION_ENUM
|
|
&PPPandaObject::NPEnumerate,
|
|
#endif
|
|
#if defined(NP_CLASS_STRUCT_VERSION_CTOR) && NP_CLASS_STRUCT_VERSION >= NP_CLASS_STRUCT_VERSION_CTOR
|
|
&PPPandaObject::NPConstruct,
|
|
#endif
|
|
};
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::make_new
|
|
// Access: Public, Static
|
|
// Description: Use this call to construct a new PPPandaObject.
|
|
////////////////////////////////////////////////////////////////////
|
|
PPPandaObject *PPPandaObject::
|
|
make_new(PPInstance *inst, P3D_object *p3d_object) {
|
|
NPObject *npobj =
|
|
browser->createobject(inst->get_npp_instance(), &_object_class);
|
|
PPPandaObject *ppobj = (PPPandaObject *)npobj;
|
|
ppobj->construct(inst, p3d_object);
|
|
return ppobj;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::set_p3d_object
|
|
// Access: Public
|
|
// Description: Changes the p3d_object this PPPandaObject maps to. The
|
|
// new object's reference count is incremented, and the
|
|
// previous object's is decremented.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PPPandaObject::
|
|
set_p3d_object(P3D_object *p3d_object) {
|
|
if (p3d_object != NULL) {
|
|
P3D_OBJECT_INCREF(p3d_object);
|
|
}
|
|
P3D_OBJECT_XDECREF(_p3d_object);
|
|
_p3d_object = p3d_object;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::construct
|
|
// Access: Private
|
|
// Description: Stands in for the C++ constructor. We can't have a
|
|
// true constructor because of the C-style interface in
|
|
// NPN_CreateObject(). This must be called explicitly
|
|
// following NPN_CreateObject().
|
|
////////////////////////////////////////////////////////////////////
|
|
void PPPandaObject::
|
|
construct(PPInstance *inst, P3D_object *p3d_object) {
|
|
_instance = inst;
|
|
_p3d_object = NULL;
|
|
set_p3d_object(p3d_object);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::invalidate
|
|
// Access: Private
|
|
// Description: This "destructor" is called by NPInvalidate().
|
|
////////////////////////////////////////////////////////////////////
|
|
void PPPandaObject::
|
|
invalidate() {
|
|
_instance = NULL;
|
|
set_p3d_object(NULL);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::has_method
|
|
// Access: Private
|
|
// Description: Returns true if the object has the named method,
|
|
// false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
has_method(NPIdentifier name) {
|
|
string method_name = identifier_to_string(name);
|
|
//nout << this << ".has_method(" << method_name << ")\n";
|
|
if (_p3d_object == NULL) {
|
|
// Not powered up yet.
|
|
return false;
|
|
}
|
|
|
|
// Unlike has_property(), below, it turns out that we really do need
|
|
// to honestly answer whether there is a method by this name,
|
|
// because if there is, then Firefox won't query the property in a
|
|
// meaningful fashion.
|
|
|
|
// Of course, in Python the distinction between property and method
|
|
// is a little looser than Firefox seems to want to make it, and
|
|
// sometimes you have an object which is both. This could become
|
|
// problematic in obscure situations. Too bad, say I. Mozilla's
|
|
// bug, not mine.
|
|
|
|
bool result = P3D_OBJECT_HAS_METHOD(_p3d_object, method_name.c_str());
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::invoke
|
|
// Access: Private
|
|
// Description: Calls the named method on the object, storing the
|
|
// return value into result. Returns true on success,
|
|
// false on failure.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount,
|
|
NPVariant *result) {
|
|
string method_name = identifier_to_string(name);
|
|
//nout << this << ".invoke(" << method_name << ")\n";
|
|
if (_p3d_object == NULL) {
|
|
// Not powered up yet.
|
|
return false;
|
|
}
|
|
|
|
P3D_object **p3dargs = new P3D_object *[argCount];
|
|
unsigned int i;
|
|
for (i = 0; i < argCount; ++i) {
|
|
p3dargs[i] = _instance->variant_to_p3dobj(&args[i]);
|
|
}
|
|
|
|
P3D_object *value = P3D_OBJECT_CALL(_p3d_object, method_name.c_str(),
|
|
true, p3dargs, argCount);
|
|
for (i = 0; i < argCount; ++i) {
|
|
P3D_OBJECT_DECREF(p3dargs[i]);
|
|
}
|
|
delete[] p3dargs;
|
|
|
|
if (value == NULL) {
|
|
// No such method, or some problem with the parameters.
|
|
return false;
|
|
}
|
|
|
|
// We have the return value, and its value is stored in value.
|
|
_instance->p3dobj_to_variant(result, value);
|
|
P3D_OBJECT_DECREF(value);
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::invoke_default
|
|
// Access: Private
|
|
// Description: Calls the default method on the object, storing the
|
|
// return value into result. Returns true on success,
|
|
// false on failure.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
invoke_default(const NPVariant *args, uint32_t argCount,
|
|
NPVariant *result) {
|
|
//nout << this << ".invoke_default()\n";
|
|
if (_p3d_object == NULL) {
|
|
// Not powered up yet.
|
|
return false;
|
|
}
|
|
|
|
P3D_object **p3dargs = new P3D_object *[argCount];
|
|
unsigned int i;
|
|
for (i = 0; i < argCount; ++i) {
|
|
p3dargs[i] = _instance->variant_to_p3dobj(&args[i]);
|
|
}
|
|
|
|
P3D_object *value = P3D_OBJECT_CALL(_p3d_object, "", true,
|
|
p3dargs, argCount);
|
|
for (i = 0; i < argCount; ++i) {
|
|
P3D_OBJECT_DECREF(p3dargs[i]);
|
|
}
|
|
delete[] p3dargs;
|
|
|
|
if (value == NULL) {
|
|
// No such method, or some problem with the parameters.
|
|
return false;
|
|
}
|
|
|
|
// We have the return value, and its value is stored in value.
|
|
_instance->p3dobj_to_variant(result, value);
|
|
P3D_OBJECT_DECREF(value);
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::has_property
|
|
// Access: Private
|
|
// Description: Returns true if the object has the named property,
|
|
// false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
has_property(NPIdentifier name) {
|
|
string property_name = identifier_to_string(name);
|
|
//nout << this << ".has_property(" << property_name << ")\n";
|
|
if (_p3d_object == NULL) {
|
|
// Not powered up yet.
|
|
return false;
|
|
}
|
|
|
|
// If we say we don't have a given property, then set_property()
|
|
// will never be called. So we always say we *do* have any
|
|
// particular property, whether we currently have it right now or
|
|
// not (since we *could* have it if you call set_property()).
|
|
|
|
// On the other hand, Firefox gets confused about methods that are
|
|
// also properties. So you have to say there's *no* property if
|
|
// there is in fact a callable method by that name, or Firefox will
|
|
// never call the method.
|
|
bool result = P3D_OBJECT_HAS_METHOD(_p3d_object, property_name.c_str());
|
|
return !result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::get_property
|
|
// Access: Private
|
|
// Description: Retrieves the named property value from the object
|
|
// and stores it in result. Returns true on success,
|
|
// false on failure.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
get_property(NPIdentifier name, NPVariant *result) {
|
|
string property_name = identifier_to_string(name);
|
|
//nout << this << ".get_property(" << property_name << ")\n";
|
|
if (_p3d_object == NULL) {
|
|
// Not powered up yet.
|
|
return false;
|
|
}
|
|
|
|
P3D_object *value = P3D_OBJECT_GET_PROPERTY(_p3d_object, property_name.c_str());
|
|
if (value == NULL) {
|
|
// No such property.
|
|
return false;
|
|
}
|
|
|
|
// We have the property, and its value is stored in value.
|
|
_instance->p3dobj_to_variant(result, value);
|
|
P3D_OBJECT_DECREF(value);
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::set_property
|
|
// Access: Private
|
|
// Description: Replaces the named property value on the object.
|
|
// Returns true on success, false on failure.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
set_property(NPIdentifier name, const NPVariant *value) {
|
|
string property_name = identifier_to_string(name);
|
|
//nout << this << ".set_property(" << property_name << ")\n";
|
|
if (_p3d_object == NULL) {
|
|
// Not powered up yet.
|
|
return false;
|
|
}
|
|
|
|
P3D_object *object = _instance->variant_to_p3dobj(value);
|
|
bool result = P3D_OBJECT_SET_PROPERTY(_p3d_object, property_name.c_str(), object);
|
|
P3D_OBJECT_DECREF(object);
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::remove_property
|
|
// Access: Private
|
|
// Description: Deletes the named property value from the object.
|
|
// Returns true on success, false on failure.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
remove_property(NPIdentifier name) {
|
|
string property_name = identifier_to_string(name);
|
|
//nout << this << ".remove_property(" << property_name << ")\n";
|
|
if (_p3d_object == NULL) {
|
|
// Not powered up yet.
|
|
return false;
|
|
}
|
|
|
|
bool result = P3D_OBJECT_SET_PROPERTY(_p3d_object, property_name.c_str(), NULL);
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::enumerate
|
|
// Access: Private
|
|
// Description: Constructs a list of available properties on this
|
|
// object. Returns true on success, false on failure.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
enumerate(NPIdentifier **value, uint32_t *count) {
|
|
//nout << this << ".enumerate()\n";
|
|
// TODO: Not implemented yet.
|
|
|
|
// Note that the array of values must be allocated here with
|
|
// NPN_MemAlloc().
|
|
*value = NULL;
|
|
*count = 0;
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::identifier_to_string
|
|
// Access: Private, Static
|
|
// Description: Gets the string equivalent of the indicated
|
|
// identifier, whether it is an integer identifier or a
|
|
// string identifier.
|
|
////////////////////////////////////////////////////////////////////
|
|
string PPPandaObject::
|
|
identifier_to_string(NPIdentifier ident) {
|
|
if (browser->identifierisstring(ident)) {
|
|
NPUTF8 *result = browser->utf8fromidentifier(ident);
|
|
if (result != NULL) {
|
|
string strval(result);
|
|
browser->memfree(result);
|
|
return strval;
|
|
}
|
|
} else {
|
|
// An integer identifier. We could treat this as a special case,
|
|
// like Firefox does, but Safari doesn't appear to use integer
|
|
// identifiers and just sends everything as a string identifier.
|
|
// So to make things consistent internally, we also send
|
|
// everything as a string.
|
|
ostringstream strm;
|
|
strm << browser->intfromidentifier(ident);
|
|
return strm.str();
|
|
}
|
|
|
|
return string();
|
|
}
|
|
|
|
|
|
// The remaining function bodies are the C-style function wrappers
|
|
// that are called directly by NPAPI, and which redirect into the
|
|
// above C++-style methods.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::NPAllocate
|
|
// Access: Private, Static
|
|
// Description: Called by NPN_CreateObject() to allocate space for
|
|
// this object.
|
|
////////////////////////////////////////////////////////////////////
|
|
NPObject *PPPandaObject::
|
|
NPAllocate(NPP npp, NPClass *aClass) {
|
|
assert(aClass == &_object_class);
|
|
return (PPPandaObject *)malloc(sizeof(PPPandaObject));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::Deallocate
|
|
// Access: Private, Static
|
|
// Description: Called to delete the space allocated by NPAllocate,
|
|
// above.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PPPandaObject::
|
|
NPDeallocate(NPObject *npobj) {
|
|
((PPPandaObject *)npobj)->invalidate();
|
|
free(npobj);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::Deallocate
|
|
// Access: Private, Static
|
|
// Description: Called to destruct the object.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PPPandaObject::
|
|
NPInvalidate(NPObject *npobj) {
|
|
// It turns out that this method isn't actually called by Safari's
|
|
// implementation of NPAPI, so we'll move the actual destructor call
|
|
// into NPDeallocate, above.
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::NPHasMethod
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
NPHasMethod(NPObject *npobj, NPIdentifier name) {
|
|
return ((PPPandaObject *)npobj)->has_method(name);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::NPInvoke
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
NPInvoke(NPObject *npobj, NPIdentifier name,
|
|
const NPVariant *args, uint32_t argCount,
|
|
NPVariant *result) {
|
|
return ((PPPandaObject *)npobj)->invoke(name, args, argCount, result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::NPInvokeDefault
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
NPInvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount,
|
|
NPVariant *result) {
|
|
return ((PPPandaObject *)npobj)->invoke_default(args, argCount, result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::NPHasProperty
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
NPHasProperty(NPObject *npobj, NPIdentifier name) {
|
|
return ((PPPandaObject *)npobj)->has_property(name);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::NPGetProperty
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
NPGetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) {
|
|
return ((PPPandaObject *)npobj)->get_property(name, result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::NPSetProperty
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
NPSetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value) {
|
|
return ((PPPandaObject *)npobj)->set_property(name, value);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::NPRemoveProperty
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
NPRemoveProperty(NPObject *npobj, NPIdentifier name) {
|
|
return ((PPPandaObject *)npobj)->remove_property(name);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::NPEnumerate
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
NPEnumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count) {
|
|
return ((PPPandaObject *)npobj)->enumerate(value, count);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PPPandaObject::NPConstruct
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PPPandaObject::
|
|
NPConstruct(NPObject *npobj, const NPVariant *args,
|
|
uint32_t argCount, NPVariant *result) {
|
|
// Not implemented. We don't use this constructor mechanism because
|
|
// it wasn't supported on earlier versions of Gecko. Instead, we
|
|
// use make_new() to construct PPPandaObjects via an explicit call to
|
|
// construct().
|
|
return true;
|
|
}
|