Guest User

git diff master

a guest
Nov 4th, 2018
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 29.23 KB | None | 0 0
  1. diff --git a/share/ui/menus.xml b/share/ui/menus.xml
  2. index 03cd74d74..27c5a5523 100644
  3. --- a/share/ui/menus.xml
  4. +++ b/share/ui/menus.xml
  5. @@ -224,6 +224,7 @@
  6.         <verb verb-id="DialogAlignDistribute" />
  7.         <verb verb-id="DialogArrange" />
  8.         <verb verb-id="DialogPrototype" />
  9. +       <verb verb-id="DialogAnimation" />
  10.     </submenu>
  11.     <submenu _name="_Path">
  12.         <verb verb-id="ObjectToPath" />
  13. diff --git a/src/desktop.cpp b/src/desktop.cpp
  14. index 335afa17d..a99b99ebb 100644
  15. --- a/src/desktop.cpp
  16. +++ b/src/desktop.cpp
  17. @@ -1,3 +1,4 @@
  18. +
  19.  /*
  20.   * Editable view implementation
  21.   *
  22. @@ -1945,6 +1946,7 @@ SPDesktop::show_dialogs()
  23.      mapVerbPreference.insert(std::make_pair ("ObjectsPanel", "/dialogs/objects") );
  24.      mapVerbPreference.insert(std::make_pair ("TagsPanel", "/dialogs/tags") );
  25.      mapVerbPreference.insert(std::make_pair ("Prototype", "/dialogs/prototype") );
  26. +    mapVerbPreference.insert(std::make_pair ("Animation", "/dialogs/animation") );
  27.  
  28.  
  29.      for (std::map<Glib::ustring, Glib::ustring>::const_iterator iter = mapVerbPreference.begin(); iter != mapVerbPreference.end(); ++iter) {
  30. diff --git a/src/document.cpp b/src/document.cpp
  31. index 5b8fe305c..124ee7ca0 100644
  32. --- a/src/document.cpp
  33. +++ b/src/document.cpp
  34. @@ -1673,7 +1673,7 @@ bool SPDocument::addResource(gchar const *key, SPObject *object)
  35.  
  36.      bool result = false;
  37.  
  38. -    if ( !object->cloned ) {
  39. +    if ( !object->cloned || !strcmp(key, "animate") ) {
  40.          std::vector<SPObject *> rlist = priv->resources[key];
  41.          g_return_val_if_fail(std::find(rlist.begin(),rlist.end(),object) == rlist.end(), false);
  42.          priv->resources[key].insert(priv->resources[key].begin(),object);
  43. @@ -1704,7 +1704,7 @@ bool SPDocument::removeResource(gchar const *key, SPObject *object)
  44.  
  45.      bool result = false;
  46.  
  47. -    if ( !object->cloned ) {
  48. +    if ( !object->cloned || !strcmp(key, "animate") ) {
  49.          std::vector<SPObject *> rlist = priv->resources[key];
  50.          g_return_val_if_fail(!rlist.empty(), false);
  51.          std::vector<SPObject*>::iterator it = std::find(priv->resources[key].begin(),priv->resources[key].end(),object);
  52. diff --git a/src/object/CMakeLists.txt b/src/object/CMakeLists.txt
  53. index 3c347ce03..e45152b79 100644
  54. --- a/src/object/CMakeLists.txt
  55. +++ b/src/object/CMakeLists.txt
  56. @@ -8,6 +8,7 @@ set(object_SRC
  57.    persp3d-reference.cpp
  58.    persp3d.cpp
  59.    sp-anchor.cpp
  60. +  sp-animate.cpp
  61.    sp-clippath.cpp
  62.    sp-conn-end-pair.cpp
  63.    sp-conn-end.cpp
  64. diff --git a/src/object/sp-animate.cpp b/src/object/sp-animate.cpp
  65. new file mode 100644
  66. index 000000000..c5902c13b
  67. --- /dev/null
  68. +++ b/src/object/sp-animate.cpp
  69. @@ -0,0 +1,399 @@
  70. +/*
  71. + * SVG <animate> implementation
  72. + *
  73. + * Authors:
  74. + *
  75. + * Copyright (C) 2018 authors
  76. + *
  77. + * Released under GNU GPL, read the file 'COPYING' for more information
  78. + */
  79. +#include <cmath>
  80. +
  81. +#include "attributes.h"
  82. +#include "desktop-style.h"
  83. +#include "sp-animate.h"
  84. +#include "xml/repr.h"
  85. +#include "document.h"
  86. +
  87. +#include "svg/stringstream.h"
  88. +
  89. +SPAnimate::SPAnimate() : SPObject() {
  90. +    this->begin = 0;
  91. +    this->end = std::numeric_limits<float>::infinity();
  92. +    this->dur = std::numeric_limits<float>::infinity();
  93. +
  94. +    this->calcMode = g_strdup("linear");
  95. +    this->attributeName = SP_ATTR_INVALID;
  96. +
  97. +    this->_originalValue = nullptr;
  98. +}
  99. +
  100. +SPAnimate::~SPAnimate() = default;
  101. +
  102. +void SPAnimate::release() {
  103. +    if (this->calcMode) {
  104. +        g_free(this->calcMode);
  105. +    }
  106. +
  107. +    if (this->document) {
  108. +        // Unregister ourselves
  109. +        this->document->removeResource("animate", this);
  110. +    }
  111. +
  112. +    SPObject::release();
  113. +}
  114. +
  115. +void SPAnimate::update(SPCtx *ctx, guint flags) {
  116. +    if (flags & SP_OBJECT_MODIFIED_FLAG) {
  117. +        flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
  118. +    }
  119. +
  120. +    flags &= SP_OBJECT_MODIFIED_CASCADE;
  121. +    std::vector<SPObject*> l(this->childList(true));
  122. +    for(std::vector<SPObject*>::const_iterator i=l.begin();i!=l.end();++i){
  123. +        SPObject *child = *i;
  124. +        if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
  125. +            child->updateDisplay(ctx, flags);
  126. +        }
  127. +        sp_object_unref(child);
  128. +    }
  129. +}
  130. +
  131. +std::vector<float> SPAnimate::_read_semicolon_list(gchar const *value) {
  132. +    std::vector<float> v;
  133. +
  134. +    gchar const* beg = value;
  135. +    while(isspace(*beg) || (*beg == ';')) beg++;
  136. +    while(*beg)
  137. +    {
  138. +        char *end;
  139. +        double ret = g_ascii_strtod(beg, &end);
  140. +        if (end==beg){
  141. +            g_warning("SPAnimate::_read_semicolon_list() Unable to convert \"%s\" to number", beg);
  142. +            // We could leave this out, too. If strtod can't convert
  143. +            // anything, it will return zero.
  144. +            // ret = 0;
  145. +            break;
  146. +        }
  147. +        v.push_back(ret);
  148. +
  149. +        beg = end;
  150. +        while(isspace(*beg) || (*beg == ';')) beg++;
  151. +    }
  152. +    return v;
  153. +}
  154. +
  155. +void SPAnimate::build(SPDocument *doc, Inkscape::XML::Node* repr) {
  156. +    SPObject::build(doc, repr);
  157. +
  158. +    this->readAttr("begin");
  159. +    this->readAttr("dur");
  160. +    this->readAttr("repeatCount");
  161. +    this->readAttr("repeatDur");
  162. +    this->readAttr("end");
  163. +
  164. +    this->readAttr("calcMode");
  165. +    this->readAttr("values");
  166. +    this->readAttr("keyTimes");
  167. +
  168. +    this->readAttr("attributeName");
  169. +
  170. +    if (this->values.size() == 0) {
  171. +        this->readAttr("from");
  172. +        this->readAttr("by");
  173. +        this->readAttr("to");
  174. +    }
  175. +    if (this->keyTimes.size() == 0) {
  176. +        int size = this->values.size();
  177. +        if (!strcmp(this->calcMode, "discrete")) {
  178. +            for (int i = 0; i < size; i++) {
  179. +                this->keyTimes.push_back(1.0 * i / size);
  180. +            }
  181. +        } else {
  182. +            g_assert(size != 1);
  183. +            for (int i = 0; i < size; i++) {
  184. +                this->keyTimes.push_back(1.0 * i / (size - 1));
  185. +            }
  186. +        }
  187. +    } else {
  188. +        if (this->keyTimes.size() != this->values.size()) {
  189. +            g_warning("SPAnimate::build() keyTimes and values have different number of values");
  190. +            while (this->keyTimes.size() > this->values.size()) {
  191. +                this->values.push_back(this->values.back());
  192. +            }
  193. +            while (this->keyTimes.size() < this->values.size()) {
  194. +                this->values.pop_back();
  195. +            }
  196. +        }
  197. +        if (this->keyTimes.front() != 0.0) {
  198. +            g_warning("SPAnimate::build() first keyTimes is not 0");
  199. +            this->keyTimes.front() = 0.0;
  200. +        }
  201. +        if (strcmp(this->calcMode, "discrete") && this->keyTimes.back() != 1.0) {
  202. +            g_warning("SPAnimate::build() last keyTimes is not 1");
  203. +            this->keyTimes.back() = 0.0;
  204. +        }
  205. +    }
  206. +
  207. +    // Register ourselves
  208. +    doc->addResource("animate", this);
  209. +}
  210. +
  211. +void SPAnimate::set(SPAttributeEnum key, const gchar *value) {
  212. +    switch (key) {
  213. +    case SP_ATTR_BEGIN:
  214. +        if (value) {
  215. +            if (!strcmp (value, "indefinite")) {
  216. +                this->begin = std::numeric_limits<float>::infinity();
  217. +            } else {
  218. +                this->begin = g_ascii_strtod (value, nullptr);
  219. +            }
  220. +        }
  221. +        break;
  222. +    case SP_ATTR_DUR:
  223. +        if (value) {
  224. +            if (!strcmp (value, "indefinite")) {
  225. +                this->dur = std::numeric_limits<float>::infinity();
  226. +            } else {
  227. +                this->dur = g_ascii_strtod (value, nullptr);
  228. +            }
  229. +            this->end = this->begin + this->dur;
  230. +        }
  231. +        break;
  232. +
  233. +    case SP_ATTR_REPEATCOUNT:
  234. +        if (value) {
  235. +            float end_;
  236. +            if (!strcmp (value, "indefinite")) {
  237. +                this->end = std::numeric_limits<float>::infinity();
  238. +            } else {
  239. +                this->end = this->begin + this->dur * g_ascii_strtod (value, nullptr);
  240. +            }
  241. +        }
  242. +        break;
  243. +    case SP_ATTR_REPEATDUR:
  244. +        if (value) {
  245. +            float end_;
  246. +            if (!strcmp (value, "indefinite")) {
  247. +                end_ = std::numeric_limits<float>::infinity();
  248. +            } else {
  249. +                end_ = this->begin + g_ascii_strtod (value, nullptr);
  250. +            }
  251. +            this->end = MIN(end_, this->end);
  252. +        }
  253. +        break;
  254. +    case SP_ATTR_END:
  255. +        if (value) {
  256. +            float end_;
  257. +            if (!strcmp (value, "indefinite")) {
  258. +                end_ = std::numeric_limits<float>::infinity();
  259. +            } else {
  260. +                end_ = g_ascii_strtod (value, nullptr);
  261. +            }
  262. +            this->end = MIN(end_, this->end);
  263. +        }
  264. +        break;
  265. +
  266. +    case SP_ATTR_CALCMODE:
  267. +        if (value) {
  268. +            if (this->calcMode) {
  269. +                if (strcmp(value, this->calcMode) == 0) break;
  270. +
  271. +                g_free(this->calcMode);
  272. +                this->calcMode = nullptr;
  273. +            }
  274. +            this->calcMode = g_strdup(value);
  275. +        }
  276. +        break;
  277. +    case SP_ATTR_VALUES:
  278. +        if (value) {
  279. +            this->values = _read_semicolon_list(value);
  280. +        }
  281. +        break;
  282. +    case SP_ATTR_FROM:
  283. +        this->values.clear();
  284. +        if (value) {
  285. +            this->values.push_back(g_ascii_strtod(value, nullptr));
  286. +        } else {
  287. +            const char *attrKey = sp_attribute_name(this->attributeName);
  288. +            this->values.push_back(g_ascii_strtod(this->parent->getAttribute(attrKey), nullptr));
  289. +        }
  290. +        break;
  291. +    case SP_ATTR_TO:
  292. +        if (value) {
  293. +            this->values.push_back(g_ascii_strtod(value, nullptr));
  294. +        }
  295. +        break;
  296. +    case SP_ATTR_BY:
  297. +        if (value) {
  298. +            g_assert(this->values.size() > 0);
  299. +            this->values.push_back(this->values[0] + g_ascii_strtod(value, nullptr));
  300. +        }
  301. +        break;
  302. +    case SP_ATTR_KEYTIMES:
  303. +        if (value) {
  304. +            this->keyTimes = _read_semicolon_list(value);
  305. +        }
  306. +        break;
  307. +
  308. +    case SP_ATTR_ATTRIBUTENAME:
  309. +        if (value) {
  310. +            this->attributeName = sp_attribute_lookup(value);
  311. +        }
  312. +
  313. +    default:
  314. +        SPObject::set(key, value);
  315. +        break;
  316. +    }
  317. +}
  318. +
  319. +void SPAnimate::modified(unsigned int flags) {
  320. +    if (flags & SP_OBJECT_MODIFIED_FLAG) {
  321. +        flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
  322. +    }
  323. +
  324. +    flags &= SP_OBJECT_MODIFIED_CASCADE;
  325. +    std::vector<SPObject *> l;
  326. +    for (auto& child: children) {
  327. +        sp_object_ref(&child);
  328. +        l.push_back(&child);
  329. +    }
  330. +
  331. +    for (auto child:l) {
  332. +        if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
  333. +            child->emitModified(flags);
  334. +        }
  335. +        sp_object_unref(child);
  336. +    }
  337. +}
  338. +
  339. +Inkscape::XML::Node* SPAnimate::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
  340. +    if (flags & SP_OBJECT_WRITE_BUILD) {
  341. +
  342. +        if (!repr) {
  343. +            repr = xml_doc->createElement("svg:animate");
  344. +        }
  345. +
  346. +        std::vector<Inkscape::XML::Node *> l;
  347. +        for (auto& child: children) {
  348. +            Inkscape::XML::Node *crepr = child.updateRepr(xml_doc, nullptr, flags);
  349. +            if (crepr) {
  350. +                l.push_back(crepr);
  351. +            }
  352. +        }
  353. +        for (auto i=l.rbegin();i!=l.rend();++i) {
  354. +            repr->addChild(*i, nullptr);
  355. +            Inkscape::GC::release(*i);
  356. +        }
  357. +    } else {
  358. +        for (auto& child: children) {
  359. +            child.updateRepr(flags);
  360. +        }
  361. +    }
  362. +
  363. +    SPObject::write(xml_doc, repr, flags);
  364. +
  365. +    return repr;
  366. +}
  367. +
  368. +void SPAnimate::setAnimateTime(float time) {
  369. +    if (!this->parent) {
  370. +        g_warning("SPAnimate::setAnimateTime no parent!");
  371. +        return;
  372. +    }
  373. +
  374. +    if (!_isAnimating(time)) {
  375. +        restoreOriginalValue();
  376. +        return;
  377. +    }
  378. +
  379. +    if (!_originalValue) {
  380. +        const char *key = sp_attribute_name(this->attributeName);
  381. +        _originalValue = g_strdup(this->parent->getAttribute(key));
  382. +    }
  383. +
  384. +    float val = _calcAnimateValue(time);
  385. +    if (val != val) {  // test for nan
  386. +        g_warning("SPAnimate::setAnimateTime calculated value was nan");
  387. +        return;
  388. +    }
  389. +    // g_message("SPAnimate::setAnimateTime val=%f", val);
  390. +
  391. +    Inkscape::SVGOStringStream os;
  392. +    os << val;
  393. +    _setParentAttr(os.str().c_str());
  394. +}
  395. +
  396. +void SPAnimate::restoreOriginalValue() {
  397. +    if (!this->parent) {
  398. +        return;
  399. +    }
  400. +    if (_originalValue) {
  401. +        _setParentAttr(_originalValue);
  402. +        g_free(_originalValue);
  403. +        _originalValue = nullptr;
  404. +    }
  405. +}
  406. +
  407. +void SPAnimate::_setParentAttr(gchar const *val) {
  408. +    if (SP_ATTRIBUTE_IS_CSS(this->attributeName)) {
  409. +
  410. +        SPCSSAttr *css = sp_repr_css_attr_new ();
  411. +
  412. +        const char *key = sp_attribute_name(this->attributeName);
  413. +        sp_repr_css_set_property (css, key, val);
  414. +
  415. +        sp_desktop_apply_css_recursive(this->parent, css, true);
  416. +
  417. +        sp_repr_css_attr_unref (css);
  418. +
  419. +    } else {
  420. +        this->parent->setKeyValue(this->attributeName, val);
  421. +    }
  422. +}
  423. +
  424. +bool SPAnimate::_isAnimating(float time) {
  425. +    return this->begin <= time && time < this->end;
  426. +}
  427. +
  428. +float SPAnimate::_calcAnimateValue(float time) {
  429. +    g_assert(_isAnimating(time));
  430. +
  431. +    float dtime = std::fmod(time - this->begin, this->dur);
  432. +
  433. +    if (!strcmp(this->calcMode, "discrete")) {
  434. +        size_t i = 0;
  435. +        for (; i < this->keyTimes.size() - 1; i++) {
  436. +            if (dtime < this->dur * this->keyTimes[i + 1]) {
  437. +                break;
  438. +            }
  439. +        }
  440. +        return this->values[i];
  441. +
  442. +    } else {
  443. +        size_t i = 0;
  444. +        for (; i < this->keyTimes.size() - 2; i++) {
  445. +            if (dtime < this->dur * this->keyTimes[i + 1]) {
  446. +                break;
  447. +            }
  448. +        }
  449. +        float v1 = this->values[i], v2 = this->values[i + 1];
  450. +        float t1 = this->dur * this->keyTimes[i], t2 = this->dur * this->keyTimes[i + 1];
  451. +        if (t1 == t2) {
  452. +            return v1;
  453. +        }
  454. +        // linear interpolation
  455. +        return v1 + (v2 - v1) * (dtime - t1) / (t2 - t1);
  456. +    }
  457. +}
  458. +
  459. +/*
  460. +  Local Variables:
  461. +  mode:c++
  462. +  c-file-style:"stroustrup"
  463. +  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  464. +  indent-tabs-mode:nil
  465. +  fill-column:99
  466. +  End:
  467. +*/
  468. +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
  469. diff --git a/src/object/sp-animate.h b/src/object/sp-animate.h
  470. new file mode 100644
  471. index 000000000..bf047fdf5
  472. --- /dev/null
  473. +++ b/src/object/sp-animate.h
  474. @@ -0,0 +1,65 @@
  475. +#ifndef SEEN_SP_ANIMATE_H
  476. +#define SEEN_SP_ANIMATE_H
  477. +
  478. +/*
  479. + * SVG <animate> implementation
  480. + *
  481. + * Authors:
  482. + *
  483. + * Copyright (C) 2018 authors
  484. + *
  485. + * Released under GNU GPL, read the file 'COPYING' for more information
  486. + */
  487. +
  488. +#include "sp-object.h"
  489. +
  490. +#define SP_ANIMATE(obj) (dynamic_cast<SPAnimate*>((SPObject*)obj))
  491. +#define SP_IS_ANIMATE(obj) (dynamic_cast<const SPAnimate*>((SPObject*)obj) != NULL)
  492. +
  493. +class SPAnimate : public SPObject {
  494. +public:
  495. +   SPAnimate();
  496. +   ~SPAnimate() override;
  497. +
  498. +   float begin;
  499. +   float end;
  500. +   float dur;
  501. +
  502. +   char *calcMode;
  503. +   std::vector<float> values;
  504. +   std::vector<float> keyTimes;
  505. +
  506. +   SPAttributeEnum attributeName;
  507. +
  508. +   void setAnimateTime(float time);
  509. +   void restoreOriginalValue();
  510. +
  511. +protected:
  512. +   void release() override;
  513. +   void update(SPCtx* ctx, unsigned int flags) override;
  514. +   void build(SPDocument *doc, Inkscape::XML::Node *repr) override;
  515. +   void set(SPAttributeEnum key, const gchar *value) override;
  516. +   void modified(unsigned int flags) override;
  517. +   Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags) override;
  518. +
  519. +private:
  520. +   std::vector<float> _read_semicolon_list(gchar const *value);
  521. +   bool _isAnimating(float time);
  522. +   float _calcAnimateValue(float time);
  523. +   void _setParentAttr(gchar const *value);
  524. +
  525. +   char *_originalValue;
  526. +};
  527. +
  528. +#endif // SEEN_SP_ANIMATE_H
  529. +
  530. +/*
  531. +  Local Variables:
  532. +  mode:c++
  533. +  c-file-style:"stroustrup"
  534. +  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  535. +  indent-tabs-mode:nil
  536. +  fill-column:99
  537. +  End:
  538. +*/
  539. +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
  540. diff --git a/src/object/sp-factory.cpp b/src/object/sp-factory.cpp
  541. index 09ef89138..20fbb1c36 100644
  542. --- a/src/object/sp-factory.cpp
  543. +++ b/src/object/sp-factory.cpp
  544. @@ -16,6 +16,7 @@
  545.  #include "color-profile.h"
  546.  #include "persp3d.h"
  547.  #include "sp-anchor.h"
  548. +#include "sp-animate.h"
  549.  #include "sp-clippath.h"
  550.  #include "sp-defs.h"
  551.  #include "sp-desc.h"
  552. @@ -308,6 +309,11 @@ SPObject *SPFactory::createObject(std::string const& id)
  553.          ret = new SPFeTile;
  554.      else if (id == "svg:feTurbulence")
  555.          ret = new SPFeTurbulence;
  556. +
  557. +    // animation
  558. +    else if (id == "svg:animate")
  559. +        ret = new SPAnimate;
  560. +
  561.      else if (id == "inkscape:grid")
  562.          ret = new SPObject; // TODO wtf
  563.      else if (id == "rdf:RDF") // no SP node yet
  564. diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
  565. index 3411eeaba..975c794a8 100644
  566. --- a/src/ui/CMakeLists.txt
  567. +++ b/src/ui/CMakeLists.txt
  568. @@ -79,6 +79,7 @@ set(ui_SRC
  569.  
  570.     dialog/aboutbox.cpp
  571.     dialog/align-and-distribute.cpp
  572. +   dialog/animation.cpp
  573.     dialog/calligraphic-profile-rename.cpp
  574.     dialog/clonetiler.cpp
  575.     dialog/color-item.cpp
  576. diff --git a/src/ui/dialog/animation.cpp b/src/ui/dialog/animation.cpp
  577. new file mode 100644
  578. index 000000000..064d2c818
  579. --- /dev/null
  580. +++ b/src/ui/dialog/animation.cpp
  581. @@ -0,0 +1,241 @@
  582. +/*
  583. + * A simple panel for layers
  584. + *
  585. + * Authors:
  586. + *   Jon A. Cruz
  587. + *   Abhishek Sharma
  588. + *
  589. + * Copyright (C) 2006,2010 Jon A. Cruz
  590. + *
  591. + * Released under GNU GPL, read the file 'COPYING' for more information
  592. + */
  593. +
  594. +#include "animation.h"
  595. +
  596. +#include <gtkmm/icontheme.h>
  597. +#include <gtkmm/separatormenuitem.h>
  598. +#include <glibmm/main.h>
  599. +#include <glibmm/i18n.h>
  600. +#include <glibmm/timer.h>
  601. +
  602. +#include "desktop-style.h"
  603. +#include "desktop.h"
  604. +#include "document-undo.h"
  605. +#include "document.h"
  606. +#include "inkscape.h"
  607. +#include "selection-chemistry.h"
  608. +#include "verbs.h"
  609. +
  610. +#include "helper/action.h"
  611. +#include "helper/icon-loader.h"
  612. +
  613. +#include "include/gtkmm_version.h"
  614. +
  615. +#include "object/sp-root.h"
  616. +#include "object/sp-animate.h"
  617. +
  618. +#include "helper/icon-loader.h"
  619. +#include "ui/icon-names.h"
  620. +#include "ui/tools/tool-base.h"
  621. +#include "ui/widget/spin-scale.h"
  622. +
  623. +//#define DUMP_ANIMATION 1
  624. +
  625. +namespace Inkscape {
  626. +namespace UI {
  627. +namespace Dialog {
  628. +
  629. +Animation& Animation::getInstance()
  630. +{
  631. +    return *new Animation();
  632. +}
  633. +
  634. +enum {
  635. +    BUTTON_PLAY = 0,
  636. +};
  637. +
  638. +
  639. +
  640. +class Animation::InternalUIBounce
  641. +{
  642. +public:
  643. +    int _actionCode;
  644. +    // SPObject* _target;
  645. +};
  646. +
  647. +void Animation::_takeAction( int val )
  648. +{
  649. +    if ( !_pending ) {
  650. +        _pending = new InternalUIBounce();
  651. +        _pending->_actionCode = val;
  652. +        Glib::signal_timeout().connect( sigc::mem_fun(*this, &Animation::_executeAction), 0 );
  653. +    }
  654. +}
  655. +
  656. +bool Animation::_executeAction()
  657. +{
  658. +
  659. +    if ( _pending
  660. +         && (
  661. +             (_pending->_actionCode == BUTTON_PLAY)
  662. +            )
  663. +        ) {
  664. +
  665. +        int val = _pending->_actionCode;
  666. +//        SPObject* target = _pending->_target;
  667. +
  668. +        switch ( val ) {
  669. +            case BUTTON_PLAY:
  670. +            {
  671. +                bool active = _playButton.get_active();
  672. +                if (_isPlaying && !active) {
  673. +                    _animationStop();
  674. +                } else if (!_isPlaying && active) {
  675. +                    _animationStart();
  676. +                }
  677. +            }
  678. +            break;
  679. +        }
  680. +
  681. +
  682. +        delete _pending;
  683. +        _pending = nullptr;
  684. +    }
  685. +
  686. +    return false;
  687. +}
  688. +
  689. +
  690. +/**
  691. + * Constructor
  692. + */
  693. +Animation::Animation() :
  694. +    UI::Widget::Panel("/dialogs/animation", SP_VERB_DIALOG_ANIMATION),
  695. +    deskTrack(),
  696. +    _maxNestDepth(20),
  697. +    _desktop(nullptr),
  698. +    _pending(nullptr),
  699. +    _scrollBar(_("Scroll Bar (s)"), 0, 0, 30, 0.1, 1, 1),
  700. +    desktopChangeConn()
  701. +{
  702. +    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
  703. +    _maxNestDepth = prefs->getIntLimited("/dialogs/animation/maxDepth", 20, 1, 1000);
  704. +
  705. +    _scrollBar.signal_value_changed().connect(sigc::mem_fun(*this, &Animation::_scrollBarValueChanged));
  706. +
  707. +    Gtk::Box *contents = _getContents();
  708. +    contents->pack_start(_buttonsRow);
  709. +    contents->pack_start(_scrollBar);
  710. +
  711. +    SPDesktop* targetDesktop = getDesktop();
  712. +
  713. +    GtkWidget *child = GTK_WIDGET(sp_get_icon_image(INKSCAPE_ICON("media-playback-start"), GTK_ICON_SIZE_SMALL_TOOLBAR)->gobj());
  714. +    gtk_widget_show( child );
  715. +    _playButton.add( *Gtk::manage(Glib::wrap(child)) );
  716. +    _playButton.set_relief(Gtk::RELIEF_NONE);
  717. +    _playButton.signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &Animation::_takeAction), (int)BUTTON_PLAY) );
  718. +    _buttonsSecondary.pack_start(_playButton, Gtk::PACK_SHRINK);
  719. +
  720. +    _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET);
  721. +
  722. +    setDesktop( targetDesktop );
  723. +
  724. +    show_all_children();
  725. +
  726. +    // restorePanelPrefs();
  727. +
  728. +    // Connect this up last
  729. +    desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &Animation::setDesktop) );
  730. +    deskTrack.connect(GTK_WIDGET(gobj()));
  731. +}
  732. +
  733. +Animation::~Animation()
  734. +{
  735. +    setDesktop(nullptr);
  736. +
  737. +    if (_pending) {
  738. +        delete _pending;
  739. +        _pending = nullptr;
  740. +    }
  741. +
  742. +    desktopChangeConn.disconnect();
  743. +    deskTrack.disconnect();
  744. +}
  745. +
  746. +
  747. +void Animation::setDesktop( SPDesktop* desktop )
  748. +{
  749. +    Panel::setDesktop(desktop);
  750. +
  751. +    if ( desktop != _desktop ) {
  752. +        if ( _desktop ) {
  753. +            _desktop = nullptr;
  754. +        }
  755. +
  756. +        _desktop = Panel::getDesktop();
  757. +        if ( _desktop ) {
  758. +            //setLabel( _desktop->doc()->name );
  759. +
  760. +            _animationStop();
  761. +        }
  762. +    }
  763. +    deskTrack.setBase(desktop);
  764. +}
  765. +
  766. +void Animation::_scrollBarValueChanged() {
  767. +    double val = _scrollBar.get_value();
  768. +    _animationDraw(val);
  769. +}
  770. +
  771. +void Animation::_animationDraw(float time) {
  772. +    std::vector<SPObject *> animates = SP_ACTIVE_DOCUMENT->getResourceList("animate");
  773. +    for (std::vector<SPObject *>::const_iterator item = animates.begin(); item != animates.end(); ++item) {
  774. +        SPAnimate *anim = SP_ANIMATE(*item);
  775. +        anim->setAnimateTime(time);
  776. +    }
  777. +}
  778. +
  779. +void Animation::_animationStart() {
  780. +    _isPlaying = true;
  781. +    _timer.reset();
  782. +    _timeDiff = _scrollBar.get_value();
  783. +    _timer.start();
  784. +
  785. +    Glib::signal_timeout().connect( sigc::mem_fun(*this, &Animation::_animationNext), 1, Glib::PRIORITY_DEFAULT_IDLE );
  786. +}
  787. +
  788. +void Animation::_animationStop() {
  789. +    _isPlaying = false;
  790. +    _timer.stop();
  791. +
  792. +    std::vector<SPObject *> animates = SP_ACTIVE_DOCUMENT->getResourceList("animate");
  793. +    for (std::vector<SPObject *>::const_iterator item = animates.begin(); item != animates.end(); ++item) {
  794. +        SPAnimate *anim = SP_ANIMATE(*item);
  795. +        anim->restoreOriginalValue();
  796. +    }
  797. +}
  798. +
  799. +bool Animation::_animationNext() {
  800. +    if (!_isPlaying) {
  801. +        return false;
  802. +    }
  803. +    _scrollBar.set_value(_timeDiff + _timer.elapsed());
  804. +    return true;
  805. +}
  806. +
  807. +
  808. +} //namespace Dialogs
  809. +} //namespace UI
  810. +} //namespace Inkscape
  811. +
  812. +
  813. +/*
  814. +  Local Variables:
  815. +  mode:c++
  816. +  c-file-style:"stroustrup"
  817. +  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  818. +  indent-tabs-mode:nil
  819. +  fill-column:99
  820. +  End:
  821. +*/
  822. +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
  823. diff --git a/src/ui/dialog/animation.h b/src/ui/dialog/animation.h
  824. new file mode 100644
  825. index 000000000..e2dab3724
  826. --- /dev/null
  827. +++ b/src/ui/dialog/animation.h
  828. @@ -0,0 +1,103 @@
  829. +/*
  830. + * A simple dialog for layer UI.
  831. + *
  832. + * Authors:
  833. + *   Jon A. Cruz
  834. + *
  835. + * Copyright (C) 2006,2010 Jon A. Cruz
  836. + *
  837. + * Released under GNU GPL, read the file 'COPYING' for more information
  838. + */
  839. +
  840. +#ifndef SEEN_ANIMATION_PANEL_H
  841. +#define SEEN_ANIMATION_PANEL_H
  842. +
  843. +#include <glibmm/timer.h>
  844. +
  845. +#include <gtkmm/box.h>
  846. +#include "ui/widget/panel.h"
  847. +#include "desktop-tracker.h"
  848. +#include "ui/widget/style-subject.h"
  849. +#include "ui/widget/spin-scale.h"
  850. +
  851. +namespace Inkscape {
  852. +
  853. +namespace UI {
  854. +namespace Dialog {
  855. +
  856. +
  857. +/**
  858. + * A panel that displays layers.
  859. + */
  860. +class Animation : public UI::Widget::Panel
  861. +{
  862. +public:
  863. +    Animation();
  864. +    ~Animation() override;
  865. +
  866. +    static Animation& getInstance();
  867. +
  868. +    void setDesktop( SPDesktop* desktop ) override;
  869. +
  870. +private:
  871. +    class InternalUIBounce;
  872. +
  873. +    Animation(Animation const &) = delete; // no copy
  874. +    Animation &operator=(Animation const &) = delete; // no assign
  875. +
  876. +    void _fireAction( unsigned int code );
  877. +
  878. +    bool _handleButtonEvent(GdkEventButton *event);
  879. +
  880. +    void _takeAction( int val );
  881. +    bool _executeAction();
  882. +
  883. +    void _scrollBarValueChanged();
  884. +
  885. +    void _animationDraw(float time);
  886. +    void _animationStart();
  887. +    void _animationStop();
  888. +
  889. +    bool _animationNext();
  890. +
  891. +    // Internal
  892. +    sigc::connection _selectedConnection;
  893. +
  894. +    bool _isPlaying;
  895. +    Glib::Timer _timer;
  896. +    double _timeDiff;
  897. +
  898. +    DesktopTracker deskTrack;
  899. +    int _maxNestDepth;
  900. +    SPDesktop* _desktop;
  901. +    InternalUIBounce* _pending;
  902. +
  903. +    Gtk::Box _buttonsRow;
  904. +    Gtk::Box _buttonsSecondary;
  905. +    Gtk::ToggleButton _playButton;
  906. +    Inkscape::UI::Widget::SpinScale _scrollBar;
  907. +
  908. +    UI::Widget::StyleSubject::CurrentLayer _subject;
  909. +    sigc::connection desktopChangeConn;
  910. +};
  911. +
  912. +
  913. +
  914. +} //namespace Dialogs
  915. +} //namespace UI
  916. +} //namespace Inkscape
  917. +
  918. +
  919. +
  920. +#endif // SEEN_ANIMATION_PANEL_H
  921. +
  922. +/*
  923. +  Local Variables:
  924. +  mode:c++
  925. +  c-file-style:"stroustrup"
  926. +  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  927. +  indent-tabs-mode:nil
  928. +  fill-column:99
  929. +  End:
  930. +*/
  931. +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
  932. diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp
  933. index 28e45d50a..143eac3a5 100644
  934. --- a/src/ui/dialog/dialog-manager.cpp
  935. +++ b/src/ui/dialog/dialog-manager.cpp
  936. @@ -57,6 +57,7 @@
  937.  #include "ui/dialog/tags.h"
  938.  #include "ui/dialog/styledialog.h"
  939.  #include "ui/dialog/cssdialog.h"
  940. +#include "ui/dialog/animation.h"
  941.  
  942.  namespace Inkscape {
  943.  namespace UI {
  944. @@ -143,6 +144,7 @@ DialogManager::DialogManager() {
  945.          registerFactory("Export",              &create<Export,               FloatingBehavior>);
  946.          registerFactory("CloneTiler",          &create<CloneTiler,           FloatingBehavior>);
  947.          registerFactory("XmlTree",             &create<XmlTree,              FloatingBehavior>);
  948. +        registerFactory("Animation",           &create<Animation,            FloatingBehavior>);
  949.  
  950.      } else {
  951.  
  952. @@ -186,6 +188,7 @@ DialogManager::DialogManager() {
  953.          registerFactory("Export",              &create<Export,               DockBehavior>);
  954.          registerFactory("CloneTiler",          &create<CloneTiler,           DockBehavior>);
  955.          registerFactory("XmlTree",             &create<XmlTree,              DockBehavior>);
  956. +        registerFactory("Animation",           &create<Animation,            DockBehavior>);
  957.  
  958.      }
  959.  }
  960. diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp
  961. index 216b2688b..ecf83d5db 100644
  962. --- a/src/ui/widget/selected-style.cpp
  963. +++ b/src/ui/widget/selected-style.cpp
  964. @@ -45,6 +45,7 @@
  965.  #include "ui/dialog/panel-dialog.h"
  966.  #include "ui/tools/tool-base.h"
  967.  #include "ui/widget/color-preview.h"
  968. +#include "ui/dialog/animation.h"
  969.  
  970.  #include "widgets/gradient-image.h"
  971.  #include "widgets/spinbutton-events.h"
  972. diff --git a/src/verbs.cpp b/src/verbs.cpp
  973. index fe617148a..2a6a133fd 100644
  974. --- a/src/verbs.cpp
  975. +++ b/src/verbs.cpp
  976. @@ -2289,7 +2289,9 @@ void DialogVerb::perform(SPAction *action, void *data)
  977.          case SP_VERB_DIALOG_CSS:
  978.              dt->_dlg_mgr->showDialog("CssDialog");
  979.              break;
  980. -
  981. +        case SP_VERB_DIALOG_ANIMATION:
  982. +            dt->_dlg_mgr->showDialog("Animation");
  983. +            break;
  984.          default:
  985.              break;
  986.      }
  987. @@ -3209,6 +3211,9 @@ Verb *Verb::_base_verbs[] = {
  988.                     N_("Select which color separations to render in Print Colors Preview rendermode"), nullptr),
  989.      new DialogVerb(SP_VERB_DIALOG_EXPORT, "DialogExport", N_("_Export PNG Image..."),
  990.                     N_("Export this document or a selection as a PNG image"), INKSCAPE_ICON("document-export")),
  991. +    new DialogVerb(SP_VERB_DIALOG_ANIMATION, "DialogAnimation", N_("_Play SVG files..."),
  992. +                   N_("Play and stop svg animations..."),
  993. +                   INKSCAPE_ICON("media-playback-start")),
  994.      // Help
  995.      new HelpVerb(SP_VERB_HELP_ABOUT_EXTENSIONS, "HelpAboutExtensions", N_("About E_xtensions"),
  996.                   N_("Information on Inkscape extensions"), nullptr),
  997. diff --git a/src/verbs.h b/src/verbs.h
  998. index fec42cca2..ce341fc9c 100644
  999. --- a/src/verbs.h
  1000. +++ b/src/verbs.h
  1001. @@ -342,6 +342,7 @@ enum {
  1002.      SP_VERB_DIALOG_SVG_FONTS,
  1003.      SP_VERB_DIALOG_PRINT_COLORS_PREVIEW,
  1004.      SP_VERB_DIALOG_EXPORT,
  1005. +    SP_VERB_DIALOG_ANIMATION,
  1006.      /* Help */
  1007.      SP_VERB_HELP_ABOUT_EXTENSIONS,
  1008.      SP_VERB_HELP_MEMORY,
Add Comment
Please, Sign In to add comment