Logo Search packages:      
Sourcecode: k3d version File versions

object_model.cpp

Go to the documentation of this file.
// K-3D
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
            \brief Implements a scripting object model in Python
            \author Anders Dahnielson (anders@dahnielson.com)
            \author Romain Behar (romainbehar@yahoo.com)
*/

#include "object_model.h"

#include <k3dsdk/algebra.h>
#include <k3dsdk/classes.h>
#include <k3dsdk/color.h>
#include <k3dsdk/command_node.h>
#include <k3dsdk/file_filter.h>
#include <k3dsdk/iapplication.h>
#include <k3dsdk/iapplication_plugin_factory.h>
#include <k3dsdk/ibezier_channel.h>
#include <k3dsdk/icommand_tree.h>
#include <k3dsdk/idocument.h>
#include <k3dsdk/idocument_plugin_factory.h>
#include <k3dsdk/igeometry_read_format.h>
#include <k3dsdk/igeometry_write_format.h>
#include <k3dsdk/imesh_sink.h>
#include <k3dsdk/imesh_source.h>
#include <k3dsdk/iobject.h>
#include <k3dsdk/iproperty.h>
#include <k3dsdk/iproperty_collection.h>
#include <k3dsdk/iuser_interface.h>
#include <k3dsdk/iwritable_property.h>
#include <k3dsdk/objects.h>
#include <k3dsdk/plugins.h>
#include <k3dsdk/property.h>
#include <k3dsdk/scripting.h>
#include <k3dsdk/serialization.h>
#include <k3dsdk/state_change_set.h>
#include <k3dsdk/utility.h>
#include <k3dsdk/viewport.h>

#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/path.hpp>

#include <fstream>
#include <iostream>

namespace
{

PyObject* ConvertTuple3(const k3d::vector3& Source)
{
      // Converts 3d vector to tuple
      return Py_BuildValue("(ddd)", Source[0], Source[1], Source[2]);
}

PyObject* ConvertTuple4(const k3d::angle_axis& Source)
{
      // Convert 1+3d vector to tuple
      return Py_BuildValue("(dddd)", k3d::degrees(Source.angle), Source.axis[0], Source.axis[1], Source.axis[2]);
}

k3d::vector3 ConvertVector3(PyObject* Value)
{
      // Converts tuple to 3d vector
      k3d::vector3 result;

      if(PyTuple_Check(Value))
      {
            result[0] = PyFloat_AsDouble(PyTuple_GetItem(Value, 0));
            result[1] = PyFloat_AsDouble(PyTuple_GetItem(Value, 1));
            result[2] = PyFloat_AsDouble(PyTuple_GetItem(Value, 2));
      }

      return result;
}

k3d::angle_axis ConvertAngleAxis(PyObject* Value)
{
      // Convert tuple to 1+3d vector
      k3d::angle_axis result;

      if(PyTuple_Check(Value))
      {
            result.angle = PyFloat_AsDouble(PyTuple_GetItem(Value, 0));
            result.axis[0] = PyFloat_AsDouble(PyTuple_GetItem(Value, 1));
            result.axis[1] = PyFloat_AsDouble(PyTuple_GetItem(Value, 2));
            result.axis[2] = PyFloat_AsDouble(PyTuple_GetItem(Value, 3));
            result.angle = k3d::radians(result.angle);
      }

      return result;
}

/// converts a boost::any object to a Python value
00111 PyObject* convert(const boost::any Value)
{
      // We put the likely types up front for efficiency ...
      if(Value.type() == typeid(bool))
            {
                  if(boost::any_cast<bool>(Value))
                        return PYVAL_TRUE;
                  else
                        return PYVAL_NONE;
            }

      if(Value.type() == typeid(double))
            return DoubleToPyVal(boost::any_cast<double>(Value));

      if(Value.type() == typeid(std::string))
            return StringToPyVal(boost::any_cast<std::string>(Value));

      if(Value.type() == typeid(k3d::vector2))
            {
                  const k3d::vector2 value = boost::any_cast<k3d::vector2>(Value);

                  return Py_BuildValue("(dd)", value[0], value[1]);
            }

      if(Value.type() == typeid(k3d::vector3))
            {
                  const k3d::vector3 value = boost::any_cast<k3d::vector3>(Value);

                  return Py_BuildValue("(ddd)", value[0], value[1], value[2]);
            }

      if(Value.type() == typeid(k3d::vector4))
            {
                  const k3d::vector4 value = boost::any_cast<k3d::vector4>(Value);

                  return Py_BuildValue("(dddd)", value[0], value[1], value[2], value[3]);
            }

      if(Value.type() == typeid(k3d::angle_axis))
            {
                  const k3d::angle_axis value = boost::any_cast<k3d::angle_axis>(Value);

                  return Py_BuildValue("(dddd)", value.angle, value.axis[0], value.axis[1], value.axis[2]);
            }

      if(Value.type() == typeid(k3d::euler_angles))
            {
                  const k3d::euler_angles value = boost::any_cast<k3d::euler_angles>(Value);

                  return Py_BuildValue("(dddi)", value[0], value[1], value[2], value.order);
            }

      // Less-likely stuff here ...
      if(Value.type() == typeid(unsigned long))
            return LongToPyVal(boost::any_cast<unsigned long>(Value));

      if(Value.type() == typeid(int))
            return IntToPyVal(boost::any_cast<int>(Value));

      if(Value.type() == typeid(long))
            return LongToPyVal(boost::any_cast<long>(Value));

      std::cerr << __PRETTY_FUNCTION__ << " : unrecognized type" << std::endl;
      return PYVAL_NONE;
}

/// converts a Python value to a boost::any object
00178 boost::any convert(PyObject* Value, const std::type_info& TargetType)
{
      if(TargetType == typeid(bool))
            {
                  return boost::any(PyObject_IsTrue(Value));
            }

      if(TargetType == typeid(double))
            {
                  if(!PyFloat_Check(Value))
                        return boost::any();

                  return boost::any(PyFloat_AsDouble(Value));
            }

      if(TargetType == typeid(std::string))
            {
                  if(!PyString_Check(Value))
                        return boost::any();

                  return boost::any(std::string(PyString_AsString(Value)));
            }

      if(TargetType == typeid(k3d::vector3))
            {
                  if(!PyTuple_Check(Value))
                        return boost::any();

                  k3d::vector3 result;

                  result[0] = PyFloat_AsDouble(PyTuple_GetItem(Value, 0));
                  result[1] = PyFloat_AsDouble(PyTuple_GetItem(Value, 1));
                  result[2] = PyFloat_AsDouble(PyTuple_GetItem(Value, 2));

                  return boost::any(result);
            }

      if(TargetType == typeid(k3d::angle_axis))
            {
                  if(!PyTuple_Check(Value))
                        return boost::any();

                  unsigned int length = PyTuple_Size(Value);
                  if(3 == length)
                        {
                              k3d::euler_angles euler(0, 0, 0, k3d::euler_angles::ZXYstatic);

                              euler.n[1] = PyFloat_AsDouble(PyTuple_GetItem(Value, 0));
                              euler.n[2] = PyFloat_AsDouble(PyTuple_GetItem(Value, 1));
                              euler.n[0] = PyFloat_AsDouble(PyTuple_GetItem(Value, 2));

                              euler.n[0] = k3d::radians(euler.n[0]);
                              euler.n[1] = k3d::radians(euler.n[1]);
                              euler.n[2] = k3d::radians(euler.n[2]);

                              return boost::any(k3d::angle_axis(euler));
                        }
                  else if(4 == length)
                        {
                              k3d::angle_axis result;

                              result.angle = PyFloat_AsDouble(PyTuple_GetItem(Value, 0));
                              result.axis[0] = PyFloat_AsDouble(PyTuple_GetItem(Value, 1));
                              result.axis[1] = PyFloat_AsDouble(PyTuple_GetItem(Value, 2));
                              result.axis[2] = PyFloat_AsDouble(PyTuple_GetItem(Value, 3));

                              result.angle = k3d::radians(result.angle);

                              return boost::any(result);
                        }
            }

      if(TargetType == typeid(unsigned long))
            {
                  if(!PyLong_Check(Value))
                        return boost::any();

                  return boost::any(PyLong_AsLong(Value));
            }

      if(TargetType == typeid(int))
            {
                  if(!PyInt_Check(Value))
                        return boost::any();

                  return boost::any(PyInt_AsLong(Value));
            }

      if(TargetType == typeid(long))
            {
                  if(!PyLong_Check(Value))
                        return boost::any();

                  return boost::any(PyLong_AsLong(Value));
            }

      std::cerr << __PRETTY_FUNCTION__ << " : unrecognized type" << std::endl;
      return boost::any();
}

} // namespace

/////////////////////////////////////////////////////////////////////////////
// CPythonObject

PyMethodDef CPythonObject::Skeleton::Methods[] =
{
      {"get_document", Owner::GetDocument, METH_VARARGS, "Return document that own object"},
      {"get_factory", Owner::GetFactory, METH_VARARGS, "Return object factory."},
      {"get_name", Owner::get_name, METH_VARARGS, "Get object name"},
      {"set_name", Owner::set_name, METH_VARARGS, "Set object name"},
      {"get_mesh", Owner::get_mesh, METH_VARARGS, "Return k3d::mesh object from a FrozenMesh"},
      {"EditObject", Owner::EditObject, METH_VARARGS, "Called to request that the object open its user interface."},
      {NULL, NULL, 0, NULL}
};

PyObject* CPythonObject::GetDocument(PyObject* self, PyObject* args)
{
      PyObject *object1;
      if (!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      return CPythonDocument::Create(&Interface(object1)->document());
}

PyObject* CPythonObject::GetFactory(PyObject* self, PyObject* args)
{
      PyObject *object1;
      if (!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      return CPythonPluginFactory::Create(&Interface(object1)->factory());
}

PyObject* CPythonObject::get_name(PyObject* self, PyObject* args)
{
      PyObject* object;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &object), PYVAL_FALSE);

      return StringToPyVal(Interface(object)->name());
}

PyObject* CPythonObject::set_name(PyObject* self, PyObject* args)
{
      PyObject* object;
      char* name;
      return_val_if_fail(PyArg_ParseTuple(args, "Os", &object, &name), PYVAL_FALSE);

      Interface(object)->set_name(name);
      return PYVAL_TRUE;
}

PyObject* CPythonObject::get_mesh(PyObject* self, PyObject* args)
{
      PyObject* py_object;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_object), PYVAL_FALSE);

      k3d::iobject* object = Interface(py_object);
      return_val_if_fail(object, PYVAL_FALSE);
      k3d::imesh_source* const mesh_source = dynamic_cast<k3d::imesh_source*>(object);
      return_val_if_fail(mesh_source, PYVAL_FALSE);

      k3d::mesh* const mesh = boost::any_cast<k3d::mesh*>(k3d::get_property_value(object->document().dag(), mesh_source->mesh_source_output()));
      return_val_if_fail(mesh, PYVAL_FALSE);

      return python_mesh::Create(mesh);
}

PyObject* CPythonObject::EditObject(PyObject* self, PyObject* args)
{
      PyObject *object1;
      if (!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      if(k3d::application().user_interface())
            {
                  k3d::application().user_interface()->show(*Interface(object1));
                  return PYVAL_TRUE;
            }

      return PYVAL_FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// CPythonBezierChannel

PyMethodDef CPythonBezierChannel::Skeleton::Methods[] =
{
      {"GetCurve", Owner::GetCurve, METH_VARARGS, "Returns the channel's curve."},
      {NULL, NULL, 0, NULL}
};

PyObject* CPythonBezierChannel::GetCurve(PyObject* self, PyObject* args)
{
      PyObject *object1;
      if(!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

/*
      k3d::ibezier_channel* const bezier_channel = dynamic_cast<k3d::ibezier_channel*>(Interface(object1));
      return_val_if_fail(bezier_channel, PYVAL_FALSE);

      k3d::ibezier_channel::control_points_t control_points;
      k3d::ibezier_channel::values_t values;
      bezier_channel->get_curve(control_points, values);
*/
      return PYVAL_FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// CPythonDocument

PyMethodDef CPythonDocument::Skeleton::Methods[] =
{
      {"GetApplication", Owner::GetApplication, METH_VARARGS, "Return the application that owns document."},
      {"GetPath", Owner::GetPath, METH_VARARGS, "Return the filepath to the document."},
      {"Import", Owner::Import, METH_VARARGS, "Imports a geometry file into the document, using the given file format."},
      {"Export", Owner::Export, METH_VARARGS, "Exports the document to a geometry file, using the given file format."},
      {"Save", Owner::Save, METH_VARARGS, "Save document to a given file."},
      {"StartChangeSet", Owner::StartStateChangeSet, METH_VARARGS, "Records an original state that should be restored when undo."},
      {"FinishChangeSet", Owner::FinishStateChangeSet, METH_VARARGS, ""},
      {"RedrawAll", Owner::RedrawAll, METH_VARARGS, "Redraws all cameras."},

      {"CreateObject", Owner::CreateObject, METH_VARARGS, "Create a new K-3D object."},
      {"Objects", Owner::Objects, METH_VARARGS, "Return the set of K-3D objects within this document as a list."},
      {"GetObject", Owner::GetObject, METH_VARARGS, "Return named K-3D object."},
      {"DeleteObject", Owner::DeleteObject, METH_VARARGS, "Delete named K-3D object."},
      {"get_mesh_instances", Owner::get_mesh_instances, METH_VARARGS, "Returns mesh list"},
      {"get_frozen_meshes", Owner::get_frozen_meshes, METH_VARARGS, "Returns mesh list"},
      {"get_objects_by_name", Owner::get_objects_by_name, METH_VARARGS, "Returns mesh list"},
      {NULL, NULL, 0, NULL}
};

PyObject* CPythonDocument::GetApplication(PyObject* self, PyObject* args)
{
      //FIXME: Return Application instance
      return PYVAL_TRUE;
}

PyObject* CPythonDocument::GetPath(PyObject* self, PyObject* args)
{
      PyObject *object1;
      if (!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      return StringToPyVal(Interface(object1)->path().native_file_string());
}

PyObject* CPythonDocument::Import(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char *string1, *string2;
      if (!PyArg_ParseTuple(args, "Oss", &object1, &string1, &string2))
            return PYVAL_FALSE;

      const boost::filesystem::path filepath(string1, boost::filesystem::native);
      return_val_if_fail(!filepath.empty(), PYVAL_FALSE);

      const std::string formatname(string2);

      k3d::auto_ptr<k3d::igeometry_read_format> filter(
            formatname.size() ?
            k3d::file_filter<k3d::igeometry_read_format>(formatname) :
            k3d::auto_file_filter<k3d::igeometry_read_format>(filepath));
      return_val_if_fail(filter.get(), PYVAL_FALSE);

      return k3d::import_file(*Interface(object1), *filter, filepath) ? PYVAL_TRUE : PYVAL_FALSE;
}

PyObject* CPythonDocument::Export(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char *string1, *string2;
      if (!PyArg_ParseTuple(args, "Oss", &object1, &string1, &string2))
            return PYVAL_FALSE;

      const boost::filesystem::path filepath(string1, boost::filesystem::native);
      return_val_if_fail(!filepath.empty(), PYVAL_FALSE);

      const std::string formatname(string2);

      k3d::auto_ptr<k3d::igeometry_write_format> filter(
            formatname.size() ?
            k3d::file_filter<k3d::igeometry_write_format>(formatname) :
            k3d::auto_file_filter<k3d::igeometry_write_format>(filepath));
      return_val_if_fail(filter.get(), PYVAL_FALSE);

      return k3d::export_file(*Interface(object1), *filter, filepath) ? PYVAL_TRUE : PYVAL_FALSE;
}

PyObject* CPythonDocument::Save(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char *string1;
      if (!PyArg_ParseTuple(args, "Os", &object1, &string1))
            return PYVAL_FALSE;

      if (Interface(object1)->save(boost::filesystem::path(string1, boost::filesystem::native)))
            return PYVAL_TRUE;

      return PYVAL_FALSE;
}

PyObject* CPythonDocument::StartStateChangeSet(PyObject* self, PyObject* args)
{
      PyObject *object1;
      if (!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      k3d::start_state_change_set(*Interface(object1));
      return PYVAL_TRUE;
}

PyObject* CPythonDocument::FinishStateChangeSet(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char *string1;
      if (!PyArg_ParseTuple(args, "Os", &object1, &string1))
            return PYVAL_FALSE;

      k3d::finish_state_change_set(*Interface(object1), string1);
      return PYVAL_TRUE;
}

PyObject* CPythonDocument::RedrawAll(PyObject* self, PyObject* args)
{
      PyObject *object1;
      if (!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      k3d::viewport::redraw_all(*Interface(object1), k3d::iviewport::ASYNCHRONOUS);
      return PYVAL_TRUE;
}

PyObject* CPythonDocument::CreateObject(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char *string1;
      if (!PyArg_ParseTuple(args, "Os", &object1, &string1))
            return PYVAL_FALSE;

      // Look for object types by name ...
      k3d::iplugin_factory_collection::factories_t factories(k3d::plugins(string1));

      // If we got at exactly one object type, create an instance of it ...
      return_val_if_fail(1 == factories.size(), PYVAL_FALSE);

      // Create an object ...
      k3d::iobject* const object = k3d::create_document_plugin(**factories.begin(), *Interface(object1));
      return_val_if_fail(object, PYVAL_FALSE);

      // Return that baby...
      return CPythonObject::Create(object);
}

PyObject* CPythonDocument::Objects(PyObject* self, PyObject* args)
{
      PyObject *object1, *list1;
      if (!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      // Return the set of objects in this collection ...
      const k3d::objects_t objects(Interface(object1)->objects().collection());

      // Convert the set to a Python list ...
      list1 = PyList_New(0);
      for(k3d::objects_t::const_iterator object = objects.begin(); object != objects.end(); ++object)
            PyList_Append(list1, CPythonObject::Create(*object));

      // Return that baby ...
      return list1;
}

PyObject* CPythonDocument::GetObject(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char *string1;
      if (!PyArg_ParseTuple(args, "Os", &object1, &string1))
            return PYVAL_FALSE;

      // Look for objects by name ...
      const k3d::objects_t objects(k3d::find_objects(Interface(object1)->objects(), string1));

      // If we found something return it ...
      return_val_if_fail(1 == objects.size(), PYVAL_FALSE);

      return CPythonObject::Create(*objects.begin());
}

PyObject* CPythonDocument::DeleteObject(PyObject* self, PyObject* args)
{
      k3d::iobject* victim = 0;

      PyObject *object1, *object2;
      if (!PyArg_ParseTuple(args, "OO", &object1, &object2))
            return PYVAL_FALSE;

      if(PyString_Check(object2))
      {
            // Look for our victim by name ...
            const k3d::objects_t objects(k3d::find_objects(Interface(object1)->objects(), PyString_AsString(object2)));

            if(1 == objects.size());
            victim = *objects.begin();
      }
      else if(PyCObject_Check(object2))
      {
            // We got a direct reference to the object ...
            victim = CPythonObject::Interface(object2);
      }

      k3d::delete_objects(*Interface(object1), k3d::make_collection<k3d::objects_t>(victim));
      return PYVAL_TRUE;
}

PyObject* get_document_objects(k3d::idocument* Document, const k3d::uuid ClassID)
{
      // Get object collection ...
      const k3d::objects_t objects(k3d::find_objects(Document->objects(), ClassID));

      // Return it as a Python list ...
      PyObject* list = PyList_New(0);
      for(k3d::objects_t::const_iterator object = objects.begin(); object != objects.end(); ++object)
            PyList_Append(list, CPythonObject::Create(*object));

      return list;
}

PyObject* CPythonDocument::get_frozen_meshes(PyObject* self, PyObject* args)
{
      PyObject* py_document;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_document), PYVAL_FALSE);

      k3d::idocument* document = dynamic_cast<k3d::idocument*>(Interface(py_document));
      return get_document_objects(document, k3d::classes::FrozenMesh());
}

PyObject* CPythonDocument::get_mesh_instances(PyObject* self, PyObject* args)
{
      PyObject* py_document;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_document), PYVAL_FALSE);

      k3d::idocument* document = dynamic_cast<k3d::idocument*>(Interface(py_document));
      return get_document_objects(document, k3d::classes::MeshInstance());
}

PyObject* CPythonDocument::get_objects_by_name(PyObject* self, PyObject* args)
{
      PyObject* py_document;
      char* name;
      return_val_if_fail(PyArg_ParseTuple(args, "Os", &py_document, &name), PYVAL_FALSE);

      k3d::idocument* document = dynamic_cast<k3d::idocument*>(Interface(py_document));

      // Get object collection ...
      const k3d::objects_t objects(k3d::find_objects(document->objects(), name));

      // Return it as a Python list ...
      PyObject* list = PyList_New(0);
      for(k3d::objects_t::const_iterator object = objects.begin(); object != objects.end(); ++object)
            PyList_Append(list, CPythonObject::Create(*object));

      return list;
}

/////////////////////////////////////////////////////////////////////////////
// CPythonProperty

PyMethodDef CPythonProperty::Skeleton::Methods[] =
{
      {"get_property_name", Owner::GetName, METH_VARARGS, "Returns property name."},
      {"get_property_description", Owner::GetDescription, METH_VARARGS, "Returns property description."},
      {NULL, NULL, 0, NULL}
};

PyObject* CPythonProperty::GetName(PyObject* self, PyObject* args)
{
      PyObject *object1;

      if(!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      k3d::iproperty* const property = dynamic_cast<k3d::iproperty*>(Interface(object1));
      return StringToPyVal(property->name());
}

PyObject* CPythonProperty::GetDescription(PyObject* self, PyObject* args)
{
      PyObject *object1;

      if(!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      k3d::iproperty* const property = dynamic_cast<k3d::iproperty*>(Interface(object1));
      return StringToPyVal(property->description());
}

/////////////////////////////////////////////////////////////////////////////
// CPythonCommandNode

PyMethodDef CPythonCommandNode::Skeleton::Methods[] =
{
      {"Command", Owner::Command, METH_VARARGS, "Execute a command on the command-node."},
      {"get_child", Owner::GetChild, METH_VARARGS, "Return command-node child."},
      {"get_property", Owner::GetProperty, METH_VARARGS, "Return property value."},
      {"set_property", Owner::SetProperty, METH_VARARGS, "Set property value."},
      {"get_children", Owner::GetChildren, METH_VARARGS, "Return command-node children."},
      {"get_properties", Owner::GetProperties, METH_VARARGS, "Return command-node properties."},
      {NULL, NULL, 0, NULL}
};

PyObject* CPythonCommandNode::Command(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char* string1;
      char* string2;
      if(!PyArg_ParseTuple(args, "Oss", &object1, &string1, &string2))
            return PYVAL_FALSE;

      const std::string command(string1);
      return_val_if_fail(command.size(), PYVAL_FALSE);

      const std::string arguments(string2);

      if(Interface(object1)->execute_command(command, arguments))
            return PYVAL_TRUE;

      return PYVAL_FALSE;
}

PyObject* CPythonCommandNode::GetChild(PyObject* self, PyObject* args)
{
      PyObject *object1, *object2;

      if(!PyArg_ParseTuple(args, "OO", &object1, &object2))
            return PYVAL_FALSE;

      if(!PyString_Check(object2))
            return PYVAL_FALSE;

      std::string child_name = PyString_AsString(object2);

      // Test to see if it's a command-node ...
      k3d::icommand_node* const command_node = dynamic_cast<k3d::icommand_node*>(Interface(object1));
      if(!command_node)
            return PYVAL_FALSE;

      // Check against children ...
      k3d::icommand_tree::children_t children = k3d::application().command_tree().children(*command_node);
      for(k3d::icommand_tree::children_t::iterator child = children.begin(); child != children.end(); ++child)
            if(child_name == (*child)->command_node_name())
                  return CPythonCommandNode::Create(*child);

      return PYVAL_NONE;
}

/// k3d::iproperty::value wrapper
PyObject* CPythonCommandNode::GetProperty(PyObject* self, PyObject* args)
{
      PyObject *object1, *object2;

      if(!PyArg_ParseTuple(args, "OO", &object1, &object2))
            return PYVAL_FALSE;

      if(!PyString_Check(object2))
            return PYVAL_FALSE;

      std::string property_name = PyString_AsString(object2);

      // Test to see if it's a property collection ...
      k3d::iproperty_collection* const property_collection = dynamic_cast<k3d::iproperty_collection*>(Interface(object1));
      if(!property_collection)
            return PYVAL_FALSE;

      // Check against properties ...
      const k3d::iproperty_collection::properties_t properties(property_collection->properties());
      for(k3d::iproperty_collection::properties_t::const_iterator property = properties.begin(); property != properties.end(); ++property)
            if((*property)->name() == property_name)
                  return convert((*property)->value());

      return PYVAL_NONE;
}

/// k3d::iproperty::set_value wrapper
PyObject* CPythonCommandNode::SetProperty(PyObject* self, PyObject* args)
{
      PyObject *object1, *object2, *object3;
      if (!PyArg_ParseTuple(args, "OOO", &object1, &object2, &object3))
            return PYVAL_FALSE;

      if(!PyString_Check(object2))
            return PYVAL_FALSE;

      std::string property_name = PyString_AsString(object2);

      // Test to see if it's a property collection ...
      k3d::iproperty_collection* const property_collection = dynamic_cast<k3d::iproperty_collection*>(Interface(object1));
      if(!property_collection)
            return PYVAL_FALSE;

      // Check against properties ...
      const k3d::iproperty_collection::properties_t properties(property_collection->properties());
      for(k3d::iproperty_collection::properties_t::const_iterator property = properties.begin(); property != properties.end(); ++property)
            {
                  if((*property)->name() == property_name)
                        {
                              k3d::iwritable_property* const writable_property = dynamic_cast<k3d::iwritable_property*>(*property);
                              if(writable_property)
                                    writable_property->set_value(convert(object3, (*property)->type()));

                              break;
                        }
            }

      return PYVAL_TRUE;
}

PyObject* CPythonCommandNode::GetChildren(PyObject* self, PyObject* args)
{
      PyObject *object1, *list1;

      if(!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      // Test to see if it's a command-node ...
      k3d::icommand_node* const command_node = dynamic_cast<k3d::icommand_node*>(Interface(object1));
      if(!command_node)
            return PYVAL_FALSE;

      // List children names ...
      list1 = PyList_New(0);
      k3d::icommand_tree::children_t children = k3d::application().command_tree().children(*command_node);
      for(k3d::icommand_tree::children_t::iterator child = children.begin(); child != children.end(); ++child)
            PyList_Append(list1, StringToPyVal((*child)->command_node_name()));

      return list1;
}

PyObject* CPythonCommandNode::GetProperties(PyObject* self, PyObject* args)
{
      PyObject *object1, *list1;

      if(!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      // Test to see if it's a property collection ...
      k3d::iproperty_collection* const property_collection = dynamic_cast<k3d::iproperty_collection*>(Interface(object1));
      if(!property_collection)
            return PYVAL_FALSE;

      // List node properties ...
      list1 = PyList_New(0);
      const k3d::iproperty_collection::properties_t properties(property_collection->properties());
      for(k3d::iproperty_collection::properties_t::const_iterator property = properties.begin(); property != properties.end(); ++property)
            PyList_Append(list1, CPythonProperty::Create(*property));
            //PyList_Append(list1, StringToPyVal((*property)->name()));

      return list1;
}

/////////////////////////////////////////////////////////////////////////////
// CPythonUserInterface

PyMethodDef CPythonUserInterface::Skeleton::Methods[] =
{
      {"BrowserNavigate", Owner::BrowserNavigate, METH_VARARGS, "Displays a URL in the user's preffered web browser."},
      {"Message", Owner::Message, METH_VARARGS, "Displays an informational message in a modal dialog box."},
      {"ErrorMessage", Owner::ErrorMessage, METH_VARARGS, "Displays an error in a modal dialog box."},
      {"QueryMessage", Owner::QueryMessage, METH_VARARGS, "Prompts the user to choose one of selections in a modal dialog box."},
      {"GetFilePath", Owner::GetFilePath, METH_VARARGS, "Prompt user for filepath."},
      {NULL, NULL, 0, NULL}
};

PyObject* CPythonUserInterface::BrowserNavigate(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char *string1;
      if (!PyArg_ParseTuple(args, "Os", &object1, &string1))
            return PYVAL_FALSE;

      Interface(object1)->browser_navigate(string1);
      return PYVAL_TRUE;
}

PyObject* CPythonUserInterface::Message(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char *string1, *string2;
      if (!PyArg_ParseTuple(args, "Oss", &object1, &string1, &string2))
            return PYVAL_FALSE;

      Interface(object1)->message(string1, string2);
      return PYVAL_TRUE;
}

PyObject* CPythonUserInterface::ErrorMessage(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char *string1, *string2;
      if (!PyArg_ParseTuple(args, "Oss", &object1, &string1, &string2))
            return PYVAL_FALSE;

      Interface(object1)->error_message(string1, string2);
      return PYVAL_TRUE;
}

PyObject* CPythonUserInterface::QueryMessage(PyObject* self, PyObject* args)
{
      PyObject *object1, *list1;
      char *string1, *string2;
      if (!PyArg_ParseTuple(args, "OssO", &object1, &string1, &string2, &list1))
            return PYVAL_FALSE;

      std::vector<std::string> buttons;
      for(int i = 0; i < PyList_Size(list1); i++)
      {
            buttons.push_back(std::string(PyString_AsString(PyList_GetItem(list1, i))));
      }

      return IntToPyVal(Interface(object1)->query_message(string1, string2, 0, buttons));
}

PyObject* CPythonUserInterface::GetFilePath(PyObject* self, PyObject* args)
{
      PyObject *object1;
      char *string1, *string2, *string3;
      int bool1 = 1;
      if(!PyArg_ParseTuple(args, "Ossis", &object1, &string1, &string2, bool1, &string3))
            return PYVAL_FALSE;

      const boost::filesystem::path old_path(string3, boost::filesystem::native);
      boost::filesystem::path FilePath;
      Interface(object1)->get_file_path(string1, string2, bool1 == 1, old_path, FilePath);

      return StringToPyVal(FilePath.native_file_string());
}

/////////////////////////////////////////////////////////////////////////////
// CPythonScriptEngines

PyObject* CPythonScriptEngines::Create()
{
      return PYVAL_TRUE;
}

PyMethodDef CPythonScriptEngines::Methods[] =
{
      {"PlayFile", PlayFile, METH_VARARGS, "Play script."},
      {NULL, NULL, 0, NULL}
};

PyObject* CPythonScriptEngines::PlayFile(PyObject* self, PyObject* args)
{
      char *string1;
      if (!PyArg_ParseTuple(args, "s", &string1))
            return PYVAL_FALSE;

      const boost::filesystem::path filepath(string1, boost::filesystem::native);

      bool recognized = false;
      bool executed = false;
      boost::filesystem::ifstream file(filepath);
      k3d::execute_script(file, filepath.native_file_string(), k3d::iscript_engine::context_t(), recognized, executed);

      if (recognized && executed)
            return PYVAL_TRUE;

      return PYVAL_FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// CPythonPluginFactory

PyMethodDef CPythonPluginFactory::Methods[] =
{
      {"get_attribute", GetAttribute, METH_VARARGS, "Returns names and types."},
      {NULL, NULL, 0, NULL}
};

PyObject* CPythonPluginFactory::GetAttribute(PyObject* self, PyObject* args)
{
      PyObject *object1, *object2;

      if(!PyArg_ParseTuple(args, "OO", &object1, &object2))
            return PYVAL_FALSE;

      if(!PyString_Check(object2))
            return PYVAL_FALSE;

      std::string attribute = PyString_AsString(object2);

      k3d::iplugin_factory* const plugin_factory = dynamic_cast<k3d::iplugin_factory*>(Interface(object1));
      if(attribute == "Name")
            return StringToPyVal(plugin_factory->name());
      if(attribute == "ShortDescription")
            return StringToPyVal(plugin_factory->short_description());
      if(attribute == "DefaultCategory")
            return StringToPyVal(plugin_factory->default_category());

      if(attribute == "ApplicationPlugin")
            {
                  k3d::iapplication_plugin_factory* const application_plugin_factory = dynamic_cast<k3d::iapplication_plugin_factory*>(Interface(object1));
                  if(application_plugin_factory)
                        return PYVAL_TRUE;

                  return PYVAL_NONE;
            }
      if(attribute == "DocumentPlugin")
            {
                  k3d::idocument_plugin_factory* const document_plugin_factory = dynamic_cast<k3d::idocument_plugin_factory*>(Interface(object1));
                  if(document_plugin_factory)
                        return PYVAL_TRUE;

                  return PYVAL_NONE;
            }

      return PYVAL_FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// CPythonApplication

PyMethodDef CPythonApplication::Methods[] =
{
      {"get_attribute", GetAttribute, METH_VARARGS, "Return objects and paths."},
      {"Close", Close, METH_VARARGS, "Closes K-3D."},
      {"NewDocument", NewDocument, METH_VARARGS, "Creates a new K-3D document."},
      {"OpenDocument", OpenDocument, METH_VARARGS, "Opens a  K-3D document."},
      {"CloseDocument", CloseDocument, METH_VARARGS, "Closes an open K-3D document."},
      {"get_command_node", CommandNode, METH_VARARGS, "Return a command-node."},
      {"get_plugin_factories", Plugins, METH_VARARGS, "Returns plugin factories."},
      {NULL, NULL, 0, NULL}
};

PyObject* CPythonApplication::GetAttribute(PyObject* self, PyObject* args)
{
      PyObject *object1;

      if(!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      if(!PyString_Check(object1))
            return PYVAL_FALSE;

      std::string attribute = PyString_AsString(object1);

      if(attribute == "UI")
            // Return User Interface
            if(k3d::application().user_interface())
                  return CPythonUserInterface::Create(k3d::application().user_interface());
            else
                  return PYVAL_NONE;
      if(attribute == "ScriptEngine")
            return CPythonScriptEngines::Create();
      if(attribute == "Documents")
            {
                  PyObject* list1;

                  // Convert the set of open documents to a Python list ...
                  list1 = PyList_New(0);

                  const k3d::iapplication::document_collection_t documents(k3d::application().documents());
                  for(k3d::iapplication::document_collection_t::const_iterator document = documents.begin(); document != documents.end(); ++document)
                        PyList_Append(list1, CPythonDocument::Create(*document));

                  return list1;
            }
      if(attribute == "ShaderCachePath")
            return StringToPyVal(k3d::application().shader_cache_path().native_file_string());
      if(attribute == "SharePath")
            return StringToPyVal(k3d::application().share_path().native_file_string());

      return PYVAL_FALSE;
}

PyObject* CPythonApplication::Close(PyObject* self, PyObject* args)
{
      return PYVAL_NONE;
}

PyObject* CPythonApplication::NewDocument(PyObject* self, PyObject* args)
{
      k3d::idocument* const document = k3d::application().create_document();
      if(document)
            return CPythonDocument::Create(document);

      return PYVAL_NONE;
}

PyObject* CPythonApplication::OpenDocument(PyObject* self, PyObject* args)
{
      const char *string1;
      if (!PyArg_ParseTuple(args, "s", &string1))
            return PYVAL_FALSE;

      k3d::idocument* const document = k3d::application().open_document(boost::filesystem::path(string1, boost::filesystem::native));
      if(document)
            return CPythonDocument::Create(document);

      return PYVAL_NONE;
}

PyObject* CPythonApplication::CloseDocument(PyObject* self, PyObject* args)
{
      PyObject *object1;
      if (!PyArg_ParseTuple(args, "O", &object1))
            return PYVAL_FALSE;

      k3d::application().close_document(*CPythonDocument::Interface(object1));

      return PYVAL_TRUE;
}

PyObject* CPythonApplication::CommandNode(PyObject* self, PyObject* args)
{
      //k3d::icommand_node* const application_node = dynamic_cast<k3d::icommand_node*>(k3dApplication());
      //return CPythonCommandNode::Create(application_node);

      char *string1;
      if(!PyArg_ParseTuple(args, "s", &string1))
            return PYVAL_FALSE;

      std::string nodepath(string1);
      if(0 == nodepath.size())
      {
            std::cerr << "Empty command node path";
            return PYVAL_FALSE;
      }

      k3d::icommand_node* node = k3d::get_command_node(nodepath);
      if(0 == node)
      {
            std::cerr << "Could not find command node [" << nodepath << "]" << std::endl;
            return PYVAL_FALSE;
      }

      return CPythonCommandNode::Create(node);
}

PyObject* CPythonApplication::Plugins(PyObject* self, PyObject* args)
{
      const k3d::iplugin_factory_collection::factories_t& factories(k3d::application().plugins());

      PyObject* list1 = PyList_New(0);

      for(k3d::iplugin_factory_collection::factories_t::const_iterator factory = factories.begin(); factory != factories.end(); ++factory)
            PyList_Append(list1, CPythonPluginFactory::Create(*factory));

      return list1;
}

/////////////////////////////////////////////////////////////////////////////
// python_mesh

PyMethodDef python_mesh::methods[] =
{
      {"create_mesh", create_mesh, METH_VARARGS, "Create a new mesh"},
      {"create_mesh_object", create_mesh_object, METH_VARARGS, "Create an object for a mesh"},
      {"create_mesh_instance", create_mesh_instance, METH_VARARGS, "Create an instance for a mesh object"},
      {"create_point", create_point, METH_VARARGS, "Create a new point, add it to the point list"},
      {"get_points", get_points, METH_VARARGS, "Get mesh points as a list"},
      {"create_polyhedron", create_polyhedron, METH_VARARGS, "Create a new polyhedron, add it to the polyhedra list"},
      {"get_polyhedra", get_polyhedra, METH_VARARGS, "Get mesh polyhedra as a list"},
      {"add_blobby", add_blobby, METH_VARARGS, "Adds a blobby object"},
      {0, 0, 0, 0}
};

PyObject* python_mesh::create_mesh(PyObject* self, PyObject* args)
{
      k3d::mesh* const mesh = new k3d::mesh();
      return_val_if_fail(mesh, PYVAL_NONE);

      return Create(mesh);
}

PyObject* python_mesh::create_mesh_object(PyObject* self, PyObject* args)
{
      PyObject* py_mesh;
      PyObject* py_document;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_mesh, &py_document), PYVAL_FALSE);

      k3d::idocument* document = dynamic_cast<k3d::idocument*>(CPythonDocument::Interface(py_document));
      return_val_if_fail(document, PYVAL_FALSE);

      // Create a FrozenMesh
      k3d::iobject* const frozen_mesh = k3d::create_document_plugin(k3d::classes::FrozenMesh(), *document);
      return_val_if_fail(frozen_mesh, PYVAL_FALSE);

      frozen_mesh->set_name("Mesh");

      k3d::imesh_sink* const frozen_mesh_sink = dynamic_cast<k3d::imesh_sink*>(frozen_mesh);
      return_val_if_fail(frozen_mesh_sink, PYVAL_FALSE);
      assert_warning(k3d::set_property_value(frozen_mesh_sink->mesh_sink_input(), dynamic_cast<k3d::mesh*>(Interface(py_mesh))));

      return CPythonObject::Create(frozen_mesh);
}
PyObject* python_mesh::create_mesh_instance(PyObject* self, PyObject* args)
{
      PyObject* py_frozen_mesh;
      PyObject* py_document;
      if(!PyArg_ParseTuple(args, "OO", &py_frozen_mesh, &py_document))
            return PYVAL_FALSE;

      k3d::idocument* document = dynamic_cast<k3d::idocument*>(CPythonDocument::Interface(py_document));
      return_val_if_fail(document, PYVAL_FALSE);

      // Create mesh object instance ...
      k3d::iobject* instance = k3d::create_document_plugin(k3d::classes::MeshInstance(), *document);
      return_val_if_fail(instance, PYVAL_FALSE);

      instance->set_name("Mesh instance");

      // Set dependencies ...
      k3d::imesh_sink* const instance_sink = dynamic_cast<k3d::imesh_sink*>(instance);
      return_val_if_fail(instance_sink, false);
      k3d::imesh_source* const frozen_mesh_source = dynamic_cast<k3d::imesh_source*>(CPythonObject::Interface(py_frozen_mesh));
      return_val_if_fail(frozen_mesh_source, PYVAL_FALSE);

      k3d::idag::dependencies_t dependencies;
      dependencies[&instance_sink->mesh_sink_input()] = &frozen_mesh_source->mesh_source_output();
      document->dag().set_dependencies(dependencies);

      return CPythonObject::Create(instance);
}

PyObject* python_mesh::create_point(PyObject* self, PyObject* args)
{
      PyObject* py_mesh;
      PyObject* py_vector;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_mesh, &py_vector), PYVAL_FALSE);

      k3d::mesh* const mesh = dynamic_cast<k3d::mesh*>(Interface(py_mesh));
      return_val_if_fail(mesh, PYVAL_FALSE);

      k3d::vector3 position = k3d::vector3(0, 0, 0);
      if(py_vector != Py_None)
            position = ConvertVector3(py_vector);

      k3d::point* const point = new k3d::point(position);
      return_val_if_fail(point, PYVAL_FALSE);

      mesh->points.push_back(point);
      return python_point::Create(point);
}

PyObject* python_mesh::get_points(PyObject* self, PyObject* args)
{
      PyObject* py_mesh;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_mesh), PYVAL_FALSE);

      k3d::mesh* const mesh = dynamic_cast<k3d::mesh*>(Interface(py_mesh));
      return_val_if_fail(mesh, PYVAL_FALSE);

      PyObject* list = PyList_New(0);
      for(k3d::mesh::points_t::const_iterator point = mesh->points.begin(); point != mesh->points.end(); ++point)
            PyList_Append(list, python_point::Create(*point));

      return list;
}

PyObject* python_mesh::create_polyhedron(PyObject* self, PyObject* args)
{
      PyObject* py_mesh;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_mesh), PYVAL_FALSE);

      k3d::mesh* const mesh = dynamic_cast<k3d::mesh*>(Interface(py_mesh));
      return_val_if_fail(mesh, PYVAL_FALSE);

      k3d::polyhedron* const polyhedron = new k3d::polyhedron();
      return_val_if_fail(polyhedron, PYVAL_FALSE);

      mesh->polyhedra.push_back(polyhedron);
      return python_polyhedron::Create(polyhedron);
}

PyObject* python_mesh::get_polyhedra(PyObject* self, PyObject* args)
{
      PyObject* py_mesh;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_mesh), PYVAL_FALSE);

      k3d::mesh* const mesh = dynamic_cast<k3d::mesh*>(Interface(py_mesh));
      return_val_if_fail(mesh, PYVAL_FALSE);

      PyObject* list = PyList_New(0);
      for(k3d::mesh::polyhedra_t::const_iterator polyhedron = mesh->polyhedra.begin(); polyhedron != mesh->polyhedra.end(); ++polyhedron)
            PyList_Append(list, python_polyhedron::Create(*polyhedron));

      return list;
}

/// Collects blobby points
01269 class get_blobby_points :
      public k3d::blobby::visitor
{
public:
      get_blobby_points(k3d::blobby& Blobby, k3d::mesh& Mesh) :
            mesh(Mesh)
      {
            Blobby.accept(*this);
      }

      void visit_constant(k3d::blobby::constant&)
      {
      }

      void visit_ellipsoid(k3d::blobby::ellipsoid& Ellipsoid)
      {
            mesh.points.push_back(Ellipsoid.origin);
      }

      void visit_segment(k3d::blobby::segment& Segment)
      {
            mesh.points.push_back(Segment.start);
            mesh.points.push_back(Segment.end);
      }

      void visit_subtract(k3d::blobby::subtract& Subtract)
      {
            Subtract.subtrahend->accept(*this);
            Subtract.minuend->accept(*this);
      }

      void visit_divide(k3d::blobby::divide& Divide)
      {
            Divide.dividend->accept(*this);
            Divide.divisor->accept(*this);
      }

      void visit_add(k3d::blobby::add& Add)
      {
            Add.operands_accept(*this);
      }

      void visit_multiply(k3d::blobby::multiply& Multiply)
      {
            Multiply.operands_accept(*this);
      }

      void visit_min(k3d::blobby::min& Min)
      {
            Min.operands_accept(*this);
      }

      void visit_max(k3d::blobby::max& Max)
      {
            Max.operands_accept(*this);
      }

private:
      k3d::mesh& mesh;
};

PyObject* python_mesh::add_blobby(PyObject* self, PyObject* args)
{
      PyObject* py_mesh;
      PyObject* py_opcode;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_mesh, &py_opcode), PYVAL_FALSE);

      k3d::mesh* const mesh = dynamic_cast<k3d::mesh*>(Interface(py_mesh));
      return_val_if_fail(mesh, PYVAL_FALSE);

      k3d::blobby::opcode* const opcode = dynamic_cast<k3d::blobby::opcode*>(python_blobby_opcode::Interface(py_opcode));
      return_val_if_fail(opcode, PYVAL_FALSE);

      k3d::blobby* new_blobby = new k3d::blobby(opcode);
      return_val_if_fail(new_blobby, PYVAL_FALSE);

      get_blobby_points(*new_blobby, *mesh);

      mesh->blobbies.push_back(new k3d::blobby(opcode));

      return PYVAL_TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// python_point

PyMethodDef python_point::methods[] =
{
      {"get_position", get_position, METH_VARARGS, "Return point position"},
      {"set_position", set_position, METH_VARARGS, "Set point position"},
      {"get_reference", get_reference, METH_VARARGS, "Return point reference (C++ pointer)"},
      {0, 0, 0, 0}
};

PyObject* python_point::get_position(PyObject* self, PyObject* args)
{
      PyObject* py_point;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_point), PYVAL_FALSE);

      k3d::point* const point = dynamic_cast<k3d::point*>(Interface(py_point));
      return_val_if_fail(point, PYVAL_FALSE);

      return ConvertTuple3(point->position);
}

PyObject* python_point::set_position(PyObject* self, PyObject* args)
{
      PyObject* py_point;
      PyObject* py_vector;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_point, &py_vector), PYVAL_FALSE);

      k3d::point* const point = dynamic_cast<k3d::point*>(Interface(py_point));
      return_val_if_fail(point, PYVAL_FALSE);

      point->position = ConvertVector3(py_vector);

      return PYVAL_TRUE;
}

PyObject* python_point::get_reference(PyObject* self, PyObject* args)
{
      PyObject* py_point;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_point), PYVAL_FALSE);

      k3d::point* const point = dynamic_cast<k3d::point*>(Interface(py_point));
      return_val_if_fail(point, PYVAL_FALSE);

      return Py_BuildValue("i", reinterpret_cast<unsigned long>(point));
}

/////////////////////////////////////////////////////////////////////////////
// python_polyhedron

PyMethodDef python_polyhedron::methods[] =
{
      {"create_face", create_face, METH_VARARGS, "Create a new face"},
      {"add_point_to_face", add_point_to_face, METH_VARARGS, "Add a new edge to an existing face"},
      {"get_faces", get_faces, METH_VARARGS, "Return face list"},
      {0, 0, 0, 0}
};

PyObject* python_polyhedron::create_face(PyObject* self, PyObject* args)
{
      PyObject* py_polyhedron;
      PyObject* py_mesh;
      PyObject* py_point;
      return_val_if_fail(PyArg_ParseTuple(args, "OOO", &py_polyhedron, &py_mesh, &py_point), PYVAL_FALSE);

      k3d::polyhedron* const polyhedron = dynamic_cast<k3d::polyhedron*>(Interface(py_polyhedron));
      return_val_if_fail(polyhedron, PYVAL_FALSE);
      // TODO: check that point and polyhedron belong to the same mesh
      k3d::point* const point = dynamic_cast<k3d::point*>(python_point::Interface(py_point));
      return_val_if_fail(point, PYVAL_FALSE);

      k3d::split_edge* const edge = new k3d::split_edge(point);
      return_val_if_fail(edge, PYVAL_FALSE);
      k3d::face* const face = new k3d::face(edge);
      return_val_if_fail(face, PYVAL_FALSE);

      polyhedron->edges.push_back(edge);
      polyhedron->faces.push_back(face);

      return python_face::Create(face);
}

PyObject* python_polyhedron::add_point_to_face(PyObject* self, PyObject* args)
{
      PyObject* py_polyhedron;
      PyObject* py_mesh;
      PyObject* py_face;
      PyObject* py_point;
      return_val_if_fail(PyArg_ParseTuple(args, "OOOO", &py_polyhedron, &py_mesh, &py_face, &py_point), PYVAL_FALSE);

      k3d::polyhedron* const polyhedron = dynamic_cast<k3d::polyhedron*>(Interface(py_polyhedron));
      return_val_if_fail(polyhedron, PYVAL_FALSE);
      // TODO: check that point and polyhedron belong to the same mesh
      k3d::face* const face = dynamic_cast<k3d::face*>(python_face::Interface(py_face));
      return_val_if_fail(face, PYVAL_FALSE);
      k3d::point* const point = dynamic_cast<k3d::point*>(python_point::Interface(py_point));
      return_val_if_fail(point, PYVAL_FALSE);

      k3d::split_edge* const new_edge = new k3d::split_edge(point);
      return_val_if_fail(new_edge, PYVAL_FALSE);

      polyhedron->edges.push_back(new_edge);
      k3d::split_edge* edge = face->first_edge;
      while(edge->face_clockwise && edge->face_clockwise != face->first_edge)
            {
                  edge = edge->face_clockwise;
            }
      edge->face_clockwise = new_edge;
      new_edge->face_clockwise = face->first_edge;

      return python_face::Create(face);
}

PyObject* python_polyhedron::get_faces(PyObject* self, PyObject* args)
{
      PyObject* py_polyhedron;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_polyhedron), PYVAL_FALSE);

      k3d::polyhedron* const polyhedron = dynamic_cast<k3d::polyhedron*>(Interface(py_polyhedron));
      return_val_if_fail(polyhedron, PYVAL_FALSE);

      PyObject* list = PyList_New(0);
      for(k3d::polyhedron::faces_t::const_iterator face = polyhedron->faces.begin(); face != polyhedron->faces.end(); ++face)
            PyList_Append(list, python_face::Create(*face));

      return list;
}

/////////////////////////////////////////////////////////////////////////////
// python_face

PyMethodDef python_face::methods[] =
{
      {"get_edge_points", get_edge_points, METH_VARARGS, "Return point list"},
      {0, 0, 0, 0}
};

PyObject* python_face::get_edge_points(PyObject* self, PyObject* args)
{
      PyObject* py_face;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_face), PYVAL_FALSE);

      k3d::face* const face = dynamic_cast<k3d::face*>(Interface(py_face));
      return_val_if_fail(face, PYVAL_FALSE);

      PyObject* list = PyList_New(0);
      k3d::split_edge* edge = face->first_edge;
      while(edge)
            {
                  PyList_Append(list, python_point::Create(edge->vertex));

                  edge = edge->face_clockwise;
                  if(edge && edge == face->first_edge)
                        edge = 0;
            }

      return list;
}

/////////////////////////////////////////////////////////////////////////////
// python_blobby_opcode

PyMethodDef python_blobby_opcode::methods[] =
{
      {"ellipsoid", create_ellipsoid, METH_VARARGS, "Creates a new blobby ellispoid"},
      {"segment", create_segment, METH_VARARGS, "Creates a new blobby segment"},
      {"set_color", set_color, METH_VARARGS, "Set ellipsoid or segment color"},
      {"add", add_operation, METH_VARARGS, "Add operation"},
      {"multiply", mult_operation, METH_VARARGS, "Mult operation"},
      {"max", max_operation, METH_VARARGS, "Max operation"},
      {"min", min_operation, METH_VARARGS, "Min operation"},
      {"subtract", sub_operation, METH_VARARGS, "Sub operation"},
      {"divide", div_operation, METH_VARARGS, "Div operation"},
      {0, 0, 0, 0}
};

PyObject* python_blobby_opcode::create_ellipsoid(PyObject* self, PyObject* args)
{
      PyObject* py_position;
      //PyObject* py_matrix;
      return_val_if_fail(PyArg_ParseTuple(args, "O", &py_position), PYVAL_FALSE);

      k3d::vector3 position = ConvertVector3(py_position);
      k3d::matrix4 transformation = k3d::identity3D();
      k3d::blobby::opcode* const ellipsoid = new k3d::blobby::ellipsoid(new k3d::point(position), transformation);
      return_val_if_fail(ellipsoid, PYVAL_NONE);

      return Create(ellipsoid);
}

PyObject* python_blobby_opcode::create_segment(PyObject* self, PyObject* args)
{
      PyObject* py_start;
      PyObject* py_end;
      PyObject* py_radius;
      //PyObject* py_matrix;
      return_val_if_fail(PyArg_ParseTuple(args, "OOO", &py_start, &py_end, &py_radius), PYVAL_FALSE);

      k3d::vector3 start = ConvertVector3(py_start);
      k3d::vector3 end = ConvertVector3(py_end);
      double radius = PyFloat_AsDouble(py_radius);
      k3d::matrix4 transformation = k3d::identity3D();
      k3d::blobby::opcode* const segment = new k3d::blobby::segment(new k3d::point(start), new k3d::point(end), radius, transformation);
      return_val_if_fail(segment, PYVAL_NONE);

      return Create(segment);
}

PyObject* python_blobby_opcode::set_color(PyObject* self, PyObject* args)
{
      PyObject* py_opcode;
      PyObject* py_color;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_opcode, &py_color), PYVAL_FALSE);

      k3d::vector3 color = ConvertVector3(py_color);
      k3d::blobby::ellipsoid* ellipsoid = dynamic_cast<k3d::blobby::ellipsoid*>(Interface(py_opcode));
      if(ellipsoid)
            {
                  ellipsoid->vertex_data["Cs"] = k3d::color(color[0], color[1], color[2]);
                  return PYVAL_TRUE;
            }

      k3d::blobby::segment* segment = dynamic_cast<k3d::blobby::segment*>(Interface(py_opcode));
      if(segment)
            {
                  segment->vertex_data["Cs"] = k3d::color(color[0], color[1], color[2]);
                  return PYVAL_TRUE;
            }

      return PYVAL_FALSE;
}

PyObject* python_blobby_opcode::add_operation(PyObject* self, PyObject* args)
{
      PyObject* py_opcode1;
      PyObject* py_opcode2;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_opcode1, &py_opcode2), PYVAL_FALSE);

      k3d::blobby::add* blob1 = dynamic_cast<k3d::blobby::add*>(Interface(py_opcode1));
      if(blob1)
            {
                  // First operand is an Add operator
                  k3d::blobby::add* blob2 = dynamic_cast<k3d::blobby::add*>(Interface(py_opcode2));
                  if(blob2)
                        {
                              // Both blobbies are Add operators
                              for(k3d::blobby::variable_operands::operands_t::const_iterator operand = blob2->operands.begin(); operand != blob2->operands.end(); operand++)
                                    blob1->add_operand(*operand);

                              // TODO DELETE blob2
                        }
                  else
                        {
                              k3d::blobby::opcode* second = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode2));
                              blob1->add_operand(second);
                        }

                  return py_opcode1;
            }
      else
            {
                  k3d::blobby::add* blob2 = dynamic_cast<k3d::blobby::add*>(Interface(py_opcode2));
                  if(blob2)
                        {
                              // Second operand is an Add operator
                              k3d::blobby::opcode* first = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode1));
                              blob2->add_operand(first);
                              return py_opcode2;
                        }
                  else
                        {
                              // None is an Add operator
                              k3d::blobby::add* addition = new k3d::blobby::add();
                              k3d::blobby::opcode* first = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode1));
                              k3d::blobby::opcode* second = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode2));
                              addition->add_operand(first);
                              addition->add_operand(second);
                              return Create(addition);
                        }
            }
}

PyObject* python_blobby_opcode::mult_operation(PyObject* self, PyObject* args)
{
      PyObject* py_opcode1;
      PyObject* py_opcode2;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_opcode1, &py_opcode2), PYVAL_FALSE);

      k3d::blobby::multiply* blob1 = dynamic_cast<k3d::blobby::multiply*>(Interface(py_opcode1));
      if(blob1)
            {
                  // First operand is an Add operator
                  k3d::blobby::multiply* blob2 = dynamic_cast<k3d::blobby::multiply*>(Interface(py_opcode2));
                  if(blob2)
                        {
                              // Both blobbies are Add operators
                              for(k3d::blobby::variable_operands::operands_t::const_iterator operand = blob2->operands.begin(); operand != blob2->operands.end(); operand++)
                                    blob1->add_operand(*operand);

                              // TODO DELETE blob2
                        }
                  else
                        {
                              k3d::blobby::opcode* second = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode2));
                              blob1->add_operand(second);
                        }

                  return py_opcode1;
            }
      else
            {
                  k3d::blobby::multiply* blob2 = dynamic_cast<k3d::blobby::multiply*>(Interface(py_opcode2));
                  if(blob2)
                        {
                              // Second operand is an Add operator
                              k3d::blobby::opcode* first = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode1));
                              blob2->add_operand(first);
                              return py_opcode2;
                        }
                  else
                        {
                              // None is an Add operator
                              k3d::blobby::multiply* addition = new k3d::blobby::multiply();
                              k3d::blobby::opcode* first = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode1));
                              k3d::blobby::opcode* second = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode2));
                              addition->add_operand(first);
                              addition->add_operand(second);
                              return Create(addition);
                        }
            }
}

PyObject* python_blobby_opcode::max_operation(PyObject* self, PyObject* args)
{
      PyObject* py_opcode1;
      PyObject* py_opcode2;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_opcode1, &py_opcode2), PYVAL_FALSE);

      k3d::blobby::max* blob1 = dynamic_cast<k3d::blobby::max*>(Interface(py_opcode1));
      if(blob1)
            {
                  // First operand is an Add operator
                  k3d::blobby::max* blob2 = dynamic_cast<k3d::blobby::max*>(Interface(py_opcode2));
                  if(blob2)
                        {
                              // Both blobbies are Add operators
                              for(k3d::blobby::variable_operands::operands_t::const_iterator operand = blob2->operands.begin(); operand != blob2->operands.end(); operand++)
                                    blob1->add_operand(*operand);

                              // TODO DELETE blob2
                        }
                  else
                        {
                              k3d::blobby::opcode* second = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode2));
                              blob1->add_operand(second);
                        }

                  return py_opcode1;
            }
      else
            {
                  k3d::blobby::max* blob2 = dynamic_cast<k3d::blobby::max*>(Interface(py_opcode2));
                  if(blob2)
                        {
                              // Second operand is an Add operator
                              k3d::blobby::opcode* first = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode1));
                              blob2->add_operand(first);
                              return py_opcode2;
                        }
                  else
                        {
                              // None is an Add operator
                              k3d::blobby::max* addition = new k3d::blobby::max();
                              k3d::blobby::opcode* first = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode1));
                              k3d::blobby::opcode* second = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode2));
                              addition->add_operand(first);
                              addition->add_operand(second);
                              return Create(addition);
                        }
            }
}

PyObject* python_blobby_opcode::min_operation(PyObject* self, PyObject* args)
{
      PyObject* py_opcode1;
      PyObject* py_opcode2;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_opcode1, &py_opcode2), PYVAL_FALSE);

      k3d::blobby::min* blob1 = dynamic_cast<k3d::blobby::min*>(Interface(py_opcode1));
      if(blob1)
            {
                  // First operand is an Add operator
                  k3d::blobby::min* blob2 = dynamic_cast<k3d::blobby::min*>(Interface(py_opcode2));
                  if(blob2)
                        {
                              // Both blobbies are Add operators
                              for(k3d::blobby::variable_operands::operands_t::const_iterator operand = blob2->operands.begin(); operand != blob2->operands.end(); operand++)
                                    blob1->add_operand(*operand);

                              // TODO DELETE blob2
                        }
                  else
                        {
                              k3d::blobby::opcode* second = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode2));
                              blob1->add_operand(second);
                        }

                  return py_opcode1;
            }
      else
            {
                  k3d::blobby::min* blob2 = dynamic_cast<k3d::blobby::min*>(Interface(py_opcode2));
                  if(blob2)
                        {
                              // Second operand is an Add operator
                              k3d::blobby::opcode* first = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode1));
                              blob2->add_operand(first);
                              return py_opcode2;
                        }
                  else
                        {
                              // None is an Add operator
                              k3d::blobby::min* addition = new k3d::blobby::min();
                              k3d::blobby::opcode* first = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode1));
                              k3d::blobby::opcode* second = dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode2));
                              addition->add_operand(first);
                              addition->add_operand(second);
                              return Create(addition);
                        }
            }
}

PyObject* python_blobby_opcode::sub_operation(PyObject* self, PyObject* args)
{
      PyObject* py_opcode1;
      PyObject* py_opcode2;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_opcode1, &py_opcode2), PYVAL_FALSE);

      k3d::blobby::subtract* sub = new k3d::blobby::subtract(dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode1)), dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode2)));
      return Create(sub);
}

PyObject* python_blobby_opcode::div_operation(PyObject* self, PyObject* args)
{
      PyObject* py_opcode1;
      PyObject* py_opcode2;
      return_val_if_fail(PyArg_ParseTuple(args, "OO", &py_opcode1, &py_opcode2), PYVAL_FALSE);

      k3d::blobby::divide* div = new k3d::blobby::divide(dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode1)), dynamic_cast<k3d::blobby::opcode*>(Interface(py_opcode2)));
      return Create(div);
}



Generated by  Doxygen 1.6.0   Back to index