home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / include / k3d / k3dsdk / scripted_node.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-07-03  |  3.2 KB  |  120 lines

  1. #ifndef K3DSDK_SCRIPTED_NODE_H
  2. #define K3DSDK_SCRIPTED_NODE_H
  3.  
  4. // K-3D
  5. // Copyright (c) 1995-2006, Timothy M. Shead
  6. //
  7. // Contact: tshead@k-3d.com
  8. //
  9. // This program is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17. // General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public
  20. // License along with this program; if not, write to the Free Software
  21. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  22.  
  23. /** \file
  24.         \author Tim Shead (tshead@k-3d.com)
  25. */
  26.  
  27. #include "data.h"
  28. #include "k3d-i18n-config.h"
  29. #include "plugins.h"
  30. #include "scripting.h"
  31. #include "user_property_changed_signal.h"
  32.  
  33. #include <boost/scoped_ptr.hpp>
  34.  
  35. namespace k3d
  36. {
  37.  
  38. /// Uses parameterized inheritance to provide a boilerplate implementation for nodes that are controlled by scripts
  39. template<typename base_t>
  40. class scripted_node :
  41.     public base_t
  42. {
  43. public:
  44.     scripted_node(iplugin_factory& Factory, idocument& Document) :
  45.         base_t(Factory, Document),
  46.         m_script(init_owner(*this) + init_name("script") + init_label(_("Script")) + init_description(_("Script source code")) + init_value<string_t>("")),
  47.         m_user_property_changed_signal(*this),
  48.         m_executing(false)
  49.     {
  50.         m_script.changed_signal().connect(sigc::mem_fun(*this, &scripted_node::on_script_changed));
  51.     }
  52.  
  53. protected:
  54.     void set_script(const string_t& Script)
  55.     {
  56.         m_script.set_value(Script);
  57.     }
  58.  
  59.     void connect_script_changed_signal(const sigc::slot<void, ihint*>& Slot)
  60.     {
  61.         m_script.changed_signal().connect(Slot);
  62.         m_user_property_changed_signal.connect(Slot);
  63.     }
  64.  
  65.     bool execute_script(iscript_engine::context_t& Context)
  66.     {
  67.         if(m_executing) // prevent recursion when writing properties in the script (infinite loop!)
  68.             return true;
  69.  
  70.         execute_lock lock(m_executing);
  71.  
  72.         const script::code code(m_script.pipeline_value());
  73.         if(!m_script_engine)
  74.         {
  75.             const script::language language(code);
  76.             return_val_if_fail(language.factory(), false);
  77.  
  78.             m_script_engine.reset(plugin::create<iscript_engine>(language.factory()->factory_id()));
  79.             return_val_if_fail(m_script_engine, false);
  80.         }
  81.  
  82.         return m_script_engine->execute(base_t::name() + "Script", code.source(), Context);
  83.     }
  84.  
  85. private:
  86.     /// RAII helper class that keeps track of whether we're executing, so we can avoid recursive loops.
  87.     class execute_lock
  88.     {
  89.     public:
  90.         execute_lock(bool_t& Executing) :
  91.             executing(Executing)
  92.         {
  93.             executing = true;
  94.         }
  95.  
  96.         ~execute_lock()
  97.         {
  98.             executing = false;
  99.         }
  100.  
  101.     private:
  102.         bool_t& executing;
  103.     };
  104.  
  105.     void on_script_changed(ihint* hint)
  106.     {
  107.         m_script_engine.reset();
  108.     }
  109.  
  110.     k3d_data(string_t, immutable_name, change_signal, with_undo, local_storage, no_constraint, script_property, with_serialization) m_script;
  111.     boost::scoped_ptr<iscript_engine> m_script_engine;
  112.     user_property_changed_signal m_user_property_changed_signal;
  113.     bool m_executing;
  114. };
  115.  
  116. } // namespace k3d
  117.  
  118. #endif // !K3DSDK_SCRIPTED_NODE_H
  119.  
  120.