From ccd5d0ad1950ed63ccdf76081ae0cb056f372c9f Mon Sep 17 00:00:00 2001 From: johanengelen Date: Sun, 2 Sep 2007 16:37:15 +0000 Subject: [PATCH] LPE: add RandomParam type. --- src/live_effects/lpe-curvestitch.cpp | 11 +- src/live_effects/lpe-curvestitch.h | 5 +- src/live_effects/parameter/parameter.cpp | 2 +- src/live_effects/parameter/parameter.h | 19 +-- src/live_effects/parameter/random.cpp | 194 +++++++++++++++++++++++ src/live_effects/parameter/random.h | 76 +++++++++ src/live_effects/parameter/todo.txt | 2 +- src/ui/widget/random.cpp | 148 +++++++++++++++++ src/ui/widget/random.h | 72 +++++++++ src/ui/widget/registered-widget.cpp | 72 +++++++++ src/ui/widget/registered-widget.h | 27 ++++ 11 files changed, 611 insertions(+), 17 deletions(-) create mode 100644 src/live_effects/parameter/random.cpp create mode 100644 src/live_effects/parameter/random.h create mode 100644 src/ui/widget/random.cpp create mode 100644 src/ui/widget/random.h diff --git a/src/live_effects/lpe-curvestitch.cpp b/src/live_effects/lpe-curvestitch.cpp index f595a9553..a0a473fe7 100644 --- a/src/live_effects/lpe-curvestitch.cpp +++ b/src/live_effects/lpe-curvestitch.cpp @@ -65,6 +65,9 @@ std::vector LPECurveStitch::doEffect (std::vector & path_in) { if (path_in.size() >= 2) { + startpoint_variation.resetRandomizer(); + endpoint_variation.resetRandomizer(); + D2 > stroke = make_cuts_independant(strokepath); Interval bndsStroke = bounds_exact(stroke[0]); gdouble scaling = bndsStroke.max() - bndsStroke.min(); @@ -85,10 +88,10 @@ LPECurveStitch::doEffect (std::vector & path_in) for (int i = 0; i < nrofpaths; i++) { Point start = A(tA); Point end = B(tB); - if (startpoint_variation != 0) - start = start + g_random_double_range(0, startpoint_variation) * (end - start); - if (endpoint_variation != 0) - end = end + g_random_double_range(0, endpoint_variation) * (end - start); + if (startpoint_variation.get_value() != 0) + start = start + startpoint_variation * (end - start); + if (endpoint_variation.get_value() != 0) + end = end + endpoint_variation * (end - start); Matrix transform; transform.setXAxis( (end-start) / scaling ); diff --git a/src/live_effects/lpe-curvestitch.h b/src/live_effects/lpe-curvestitch.h index 571996a7c..2b3e4553e 100644 --- a/src/live_effects/lpe-curvestitch.h +++ b/src/live_effects/lpe-curvestitch.h @@ -18,6 +18,7 @@ #include "live_effects/parameter/path.h" #include "live_effects/parameter/parameter.h" #include "live_effects/parameter/bool.h" +#include "live_effects/parameter/random.h" namespace Inkscape { namespace LivePathEffect { @@ -32,8 +33,8 @@ public: private: PathParam strokepath; ScalarParam nrofpaths; - ScalarParam startpoint_variation; - ScalarParam endpoint_variation; + RandomParam startpoint_variation; + RandomParam endpoint_variation; BoolParam scale_y; LPECurveStitch(const LPECurveStitch&); diff --git a/src/live_effects/parameter/parameter.cpp b/src/live_effects/parameter/parameter.cpp index 42dd21995..94d5e3f8e 100644 --- a/src/live_effects/parameter/parameter.cpp +++ b/src/live_effects/parameter/parameter.cpp @@ -110,7 +110,7 @@ ScalarParam::param_set_range(gdouble min, gdouble max) if (rsu) rsu->getS()->setRange(min, max); - param_set_value(value); + param_set_value(value); // reset value to see whether it is in ranges } void diff --git a/src/live_effects/parameter/parameter.h b/src/live_effects/parameter/parameter.h index d8659600a..e6cabbdd9 100644 --- a/src/live_effects/parameter/parameter.h +++ b/src/live_effects/parameter/parameter.h @@ -68,31 +68,32 @@ public: Inkscape::UI::Widget::Registry* wr, Effect* effect, gdouble default_value = 1.0); - ~ScalarParam(); + virtual ~ScalarParam(); - bool param_readSVGValue(const gchar * strvalue); - gchar * param_writeSVGValue() const; + virtual bool param_readSVGValue(const gchar * strvalue); + virtual gchar * param_writeSVGValue() const; - void param_set_default(); + virtual void param_set_default(); void param_set_value(gdouble val); void param_make_integer(bool yes = true); void param_set_range(gdouble min, gdouble max); - Gtk::Widget * param_getWidget(); + virtual Gtk::Widget * param_getWidget(); inline operator gdouble() { return value; }; -private: - ScalarParam(const ScalarParam&); - ScalarParam& operator=(const ScalarParam&); - +protected: gdouble value; gdouble min; gdouble max; bool integer; gdouble defvalue; Inkscape::UI::Widget::RegisteredScalar * rsu; + +private: + ScalarParam(const ScalarParam&); + ScalarParam& operator=(const ScalarParam&); }; } //namespace LivePathEffect diff --git a/src/live_effects/parameter/random.cpp b/src/live_effects/parameter/random.cpp new file mode 100644 index 000000000..846c2f9e8 --- /dev/null +++ b/src/live_effects/parameter/random.cpp @@ -0,0 +1,194 @@ +#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_RANDOM_CPP + +/* + * Copyright (C) Johan Engelen 2007 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/parameter/random.h" +#include "live_effects/effect.h" +#include "svg/svg.h" +#include "libnr/nr-values.h" + +#include +#include "ui/widget/random.h" + +#include "svg/stringstream.h" + +#include "verbs.h" + +#define noLPERANDOMPARAM_DEBUG + +namespace Inkscape { + +namespace LivePathEffect { + + +RandomParam::RandomParam( const Glib::ustring& label, const Glib::ustring& tip, + const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, + Effect* effect, gdouble default_value, long default_seed) + : Parameter(label, tip, key, wr, effect) +{ + defvalue = default_value; + value = defvalue; + min = -NR_HUGE; + max = NR_HUGE; + integer = false; + regrandom = NULL; + + defseed = default_seed; + startseed = defseed; + seed = startseed; +} + +RandomParam::~RandomParam() +{ + if (regrandom) + delete regrandom; +} + +bool +RandomParam::param_readSVGValue(const gchar * strvalue) +{ + double newval, newstartseed; + gchar** stringarray = g_strsplit (strvalue, ";", 2); + unsigned int success = sp_svg_number_read_d(stringarray[0], &newval); + if (success == 1) { + success += sp_svg_number_read_d(stringarray[1], &newstartseed); + if (success == 2) { + param_set_value(newval, newstartseed); + } else { + param_set_value(newval, defseed); + } + g_strfreev(stringarray); + return true; + } + g_strfreev(stringarray); + return false; +} + +gchar * +RandomParam::param_writeSVGValue() const +{ + Inkscape::SVGOStringStream os; + os << value << ';' << startseed; + gchar * str = g_strdup(os.str().c_str()); + return str; +} + +void +RandomParam::param_set_default() +{ + param_set_value(defvalue, defseed); +} + +void +RandomParam::param_set_value(gdouble val, long newseed) +{ + value = val; + if (integer) + value = round(value); + if (value > max) + value = max; + if (value < min) + value = min; + + startseed = setup_seed(newseed); + seed = startseed; + + if (regrandom) + regrandom->setValue(value, startseed); +} + +void +RandomParam::param_set_range(gdouble min, gdouble max) +{ + this->min = min; + this->max = max; + if (regrandom) + regrandom->getR()->setRange(min, max); + + param_set_value(value, startseed); // reset value, to check whether it is in range +} + +void +RandomParam::param_make_integer(bool yes) +{ + integer = yes; + if (regrandom) { + regrandom->getR()->setDigits(0); + regrandom->getR()->setIncrements(1, 10); + } +} + +void +RandomParam::resetRandomizer() +{ + seed = startseed; +} + + +Gtk::Widget * +RandomParam::param_getWidget() +{ + // TODO: add a button to set a different startseed + if (!regrandom) { + regrandom = new Inkscape::UI::Widget::RegisteredRandom(); + regrandom->init(param_label, param_tooltip, param_key, *param_wr, param_effect->getRepr(), param_effect->getSPDoc()); + regrandom->setValue(value, startseed); + if (integer) + param_make_integer(); + + regrandom->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change random parameter")); + } + return dynamic_cast (regrandom->getR()); +} + +RandomParam::operator gdouble() +{ + return rand() * value; +}; + +/* RNG stolen from /display/nr-filter-turbulence.cpp */ +#define RAND_m 2147483647 /* 2**31 - 1 */ +#define RAND_a 16807 /* 7**5; primitive root of m */ +#define RAND_q 127773 /* m / a */ +#define RAND_r 2836 /* m % a */ +#define BSize 0x100 + +long +RandomParam::setup_seed(long lSeed) +{ + if (lSeed <= 0) lSeed = -(lSeed % (RAND_m - 1)) + 1; + if (lSeed > RAND_m - 1) lSeed = RAND_m - 1; + return lSeed; +} + +// generates random number between 0 and 1 +gdouble +RandomParam::rand() +{ + long result; + result = RAND_a * (seed % RAND_q) - RAND_r * (seed / RAND_q); + if (result <= 0) result += RAND_m; + seed = result; + + gdouble dresult = (gdouble)(result % BSize) / BSize; + return dresult; +} + + +} /* namespace LivePathEffect */ +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/random.h b/src/live_effects/parameter/random.h new file mode 100644 index 000000000..772f46ac6 --- /dev/null +++ b/src/live_effects/parameter/random.h @@ -0,0 +1,76 @@ +#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_RANDOM_H +#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_RANDOM_H + +/* + * Inkscape::LivePathEffectParameters + * +* Copyright (C) Johan Engelen 2007 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/parameter/parameter.h" +#include +#include <2geom/point.h> +#include <2geom/path.h> + +#include "ui/widget/registry.h" +#include "ui/widget/registered-widget.h" + +namespace Inkscape { + +namespace LivePathEffect { + +class RandomParam : public Parameter { +public: + RandomParam( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect, + gdouble default_value = 1.0, + long default_seed = 0); + virtual ~RandomParam(); + + virtual bool param_readSVGValue(const gchar * strvalue); + virtual gchar * param_writeSVGValue() const; + virtual void param_set_default(); + + virtual Gtk::Widget * param_getWidget(); + + void param_set_value(gdouble val, long newseed); + void param_make_integer(bool yes = true); + void param_set_range(gdouble min, gdouble max); + + void resetRandomizer(); + + operator gdouble(); + inline gdouble get_value() + { return value; } ; + +protected: + long startseed; + long seed; + long defseed; + + gdouble value; + gdouble min; + gdouble max; + bool integer; + gdouble defvalue; + + Inkscape::UI::Widget::RegisteredRandom * regrandom; + +private: + long setup_seed(long); + gdouble rand(); + + RandomParam(const RandomParam&); + RandomParam& operator=(const RandomParam&); +}; + +} //namespace LivePathEffect + +} //namespace Inkscape + +#endif diff --git a/src/live_effects/parameter/todo.txt b/src/live_effects/parameter/todo.txt index f1a1b4220..d82411db0 100644 --- a/src/live_effects/parameter/todo.txt +++ b/src/live_effects/parameter/todo.txt @@ -5,5 +5,5 @@ For example, the spinbuttons for scalarparam can "hang" which is very very very - add more types! straightlinepaths: for example for the gears effect. (curves are not important there) -random number: it must also store the random number generator seed!!! + diff --git a/src/ui/widget/random.cpp b/src/ui/widget/random.cpp new file mode 100644 index 000000000..1d99f406c --- /dev/null +++ b/src/ui/widget/random.cpp @@ -0,0 +1,148 @@ +/** + * \brief Scalar Widget - A labelled text box, with spin buttons and optional + * icon or suffix, for entering arbitrary number values. It adds an extra + * number called "startseed", that is not UI edittable, but should be put in SVG. + * This does NOT generate a random number, but provides merely the saving of + * the startseed value. + * + * Authors: + * Carl Hetherington + * Derek P. Moore + * Bryce Harrington + * + * Copyright (C) 2004 Carl Hetherington + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + + +#include "random.h" +#include "widgets/icon.h" + +#include + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * Construct a Random scalar Widget. + * + * \param label Label. + * \param suffix Suffix, placed after the widget (defaults to ""). + * \param icon Icon filename, placed before the label (defaults to ""). + * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label + * indicates the next character should be used for the + * mnemonic accelerator key (defaults to false). + */ +Random::Random(Glib::ustring const &label, Glib::ustring const &tooltip, + Glib::ustring const &suffix, + Glib::ustring const &icon, + bool mnemonic) + : Scalar(label, tooltip, suffix, icon, mnemonic) +{ + startseed = 0; + addReseedButton(); +} + +/** + * Construct a Random Scalar Widget. + * + * \param label Label. + * \param digits Number of decimal digits to display. + * \param suffix Suffix, placed after the widget (defaults to ""). + * \param icon Icon filename, placed before the label (defaults to ""). + * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label + * indicates the next character should be used for the + * mnemonic accelerator key (defaults to false). + */ +Random::Random(Glib::ustring const &label, Glib::ustring const &tooltip, + unsigned digits, + Glib::ustring const &suffix, + Glib::ustring const &icon, + bool mnemonic) + : Scalar(label, tooltip, digits, suffix, icon, mnemonic) +{ + startseed = 0; + addReseedButton(); +} + +/** + * Construct a Random Scalar Widget. + * + * \param label Label. + * \param adjust Adjustment to use for the SpinButton. + * \param digits Number of decimal digits to display (defaults to 0). + * \param suffix Suffix, placed after the widget (defaults to ""). + * \param icon Icon filename, placed before the label (defaults to ""). + * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label + * indicates the next character should be used for the + * mnemonic accelerator key (defaults to true). + */ +Random::Random(Glib::ustring const &label, Glib::ustring const &tooltip, + Gtk::Adjustment &adjust, + unsigned digits, + Glib::ustring const &suffix, + Glib::ustring const &icon, + bool mnemonic) + : Scalar(label, tooltip, adjust, digits, suffix, icon, mnemonic) +{ + startseed = 0; + addReseedButton(); +} + +/** Gets the startseed */ +long +Random::getStartSeed() const +{ + return startseed; +} + +/** Sets the startseed number */ +void +Random::setStartSeed(long newseed) +{ + startseed = newseed; +} + +/** Add reseed button to the widget */ +void +Random::addReseedButton() +{ + Gtk::Widget* pIcon = Gtk::manage( sp_icon_get_icon( "draw_spiral", Inkscape::ICON_SIZE_BUTTON) ); + Gtk::Button * pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &Random::onReseedButtonClick)); + _tooltips.set_tip(*pButton, _("Reseed the random number generator; this creates a different sequence of random numbers.")); + + pack_start(*pButton, Gtk::PACK_SHRINK, 0); +} + +void +Random::onReseedButtonClick() +{ + startseed = g_random_int(); + signal_reseeded.emit(); +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/random.h b/src/ui/widget/random.h new file mode 100644 index 000000000..56c39ccc1 --- /dev/null +++ b/src/ui/widget/random.h @@ -0,0 +1,72 @@ +/** + * \brief Random Scalar Widget - A labelled text box, with spin buttons and optional + * icon or suffix, for entering arbitrary number values and generating a random number from it. + * + * Authors: + * Johan Engelen + * + * Copyright (C) 2007 Author + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_RANDOM_H +#define INKSCAPE_UI_WIDGET_RANDOM_H + +#include "scalar.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Random : public Scalar +{ +public: + Random(Glib::ustring const &label, + Glib::ustring const &tooltip, + Glib::ustring const &suffix = "", + Glib::ustring const &icon = "", + bool mnemonic = true); + Random(Glib::ustring const &label, + Glib::ustring const &tooltip, + unsigned digits, + Glib::ustring const &suffix = "", + Glib::ustring const &icon = "", + bool mnemonic = true); + Random(Glib::ustring const &label, + Glib::ustring const &tooltip, + Gtk::Adjustment &adjust, + unsigned digits = 0, + Glib::ustring const &suffix = "", + Glib::ustring const &icon = "", + bool mnemonic = true); + + long getStartSeed() const; + void setStartSeed(long newseed); + + sigc::signal signal_reseeded; + +protected: + long startseed; + +private: + void addReseedButton(); + void onReseedButtonClick(); +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_RANDOM_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp index 8a569bc32..4db4363ca 100644 --- a/src/ui/widget/registered-widget.cpp +++ b/src/ui/widget/registered-widget.cpp @@ -23,6 +23,7 @@ #include "ui/widget/registry.h" #include "ui/widget/scalar-unit.h" #include "ui/widget/point.h" +#include "ui/widget/random.h" #include "widgets/spinbutton-events.h" #include "helper/units.h" @@ -542,6 +543,77 @@ RegisteredPoint::on_value_changed() _wr->setUpdating (false); } +/*######################################### + * Registered RANDOM + */ + +RegisteredRandom::RegisteredRandom() +{ + _widget = NULL; +} + +RegisteredRandom::~RegisteredRandom() +{ + if (_widget) + delete _widget; + + _value_changed_connection.disconnect(); + _reseeded_connection.disconnect(); +} + +void +RegisteredRandom::init ( const Glib::ustring& label, const Glib::ustring& tip, + const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, + SPDocument * doc_in ) +{ + init_parent(key, wr, repr_in, doc_in); + + _widget = new Random (label, tip); + _widget->setRange (-1e6, 1e6); + _widget->setDigits (2); + _widget->setIncrements(0.1, 1.0); + _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed)); + _reseeded_connection = _widget->signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed)); +} + +Random* +RegisteredRandom::getR() +{ + return _widget; +} + +void +RegisteredRandom::setValue (double val, long startseed) +{ + _widget->setValue (val); + _widget->setStartSeed(startseed); + on_value_changed(); +} + +void +RegisteredRandom::on_value_changed() +{ + if (_wr->isUpdating()) + return; + _wr->setUpdating (true); + + // FIXME: gtk bug? + // disable interruptibility: see http://inkscape.svn.sourceforge.net/viewvc/inkscape/inkscape/trunk/src/ui/widget/selected-style.cpp?r1=13149&r2=13257&sortby=date + SPDesktop* dt = SP_ACTIVE_DESKTOP; + sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(dt), 0); + + Inkscape::SVGOStringStream os; + os << _widget->getValue() << ';' << _widget->getStartSeed(); + + write_to_xml(os.str().c_str()); + + // resume interruptibility + sp_canvas_end_forced_full_redraws(sp_desktop_canvas(dt)); + + _wr->setUpdating (false); +} + + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/widget/registered-widget.h b/src/ui/widget/registered-widget.h index 008ca0077..7d71165da 100644 --- a/src/ui/widget/registered-widget.h +++ b/src/ui/widget/registered-widget.h @@ -38,6 +38,7 @@ class Scalar; class ScalarUnit; class UnitMenu; class Point; +class Random; class RegisteredWidget { public: @@ -298,6 +299,32 @@ protected: void on_value_changed(); }; +class RegisteredRandom : public RegisteredWidget { +public: + RegisteredRandom(); + ~RegisteredRandom(); + void init (const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Registry& wr, + Inkscape::XML::Node* repr_in, + SPDocument *doc_in); + inline void init ( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Registry& wr) + { init(label, tip, key, wr, NULL, NULL); }; + + Random* getR(); + void setValue (double val, long startseed); + +protected: + Random *_widget; + sigc::connection _value_changed_connection; + sigc::connection _reseeded_connection; + void on_value_changed(); +}; + } // namespace Widget } // namespace UI } // namespace Inkscape -- 2.30.2