diff --git a/examples/example1/src/main.d b/examples/example1/src/main.d index 10ba9a3c..988a20f2 100644 --- a/examples/example1/src/main.d +++ b/examples/example1/src/main.d @@ -7,6 +7,51 @@ import std.conv; mixin APP_ENTRY_POINT; +class SampleAnimationWidget : Widget { + ulong animationProgress; + this(string ID) { + super(ID); + } + /// returns true is widget is being animated - need to call animate() and redraw + @property override bool animating() { return true; } + /// animates window; interval is time left from previous draw, in hnsecs (1/10000000 of second) + override void animate(long interval) { + animationProgress += interval; + invalidate(); + } + void drawAnimatedRect(DrawBuf buf, uint p, Rect rc, int speedx, int speedy, int sz) { + int x = (p * speedx % rc.width); + int y = (p * speedy % rc.height); + if (x < 0) + x += rc.width; + if (y < 0) + y += rc.height; + uint a = 64 + ((p / 2) & 0x7F); + uint r = 128 + ((p / 7) & 0x7F); + uint g = 128 + ((p / 5) & 0x7F); + uint b = 128 + ((p / 3) & 0x7F); + uint color = (a << 24) | (r << 16) | (g << 8) | b; + buf.fillRect(Rect(rc.left + x, rc.top + y, rc.left + x + sz, rc.top + y + sz), color); + } + /// Draw widget at its position to buffer + override void onDraw(DrawBuf buf) { + if (visibility != Visibility.Visible) + return; + super.onDraw(buf); + Rect rc = _pos; + applyMargins(rc); + auto saver = ClipRectSaver(buf, rc, alpha); + applyPadding(rc); + drawAnimatedRect(buf, cast(uint)(animationProgress / 295430), rc, 2, 3, 100); + drawAnimatedRect(buf, cast(uint)(animationProgress / 312400) + 100, rc, 3, 2, 130); + drawAnimatedRect(buf, cast(uint)(animationProgress / 212400) + 200, rc, -2, 1, 290); + drawAnimatedRect(buf, cast(uint)(animationProgress / 512400) + 300, rc, 2, -2, 200); + drawAnimatedRect(buf, cast(uint)(animationProgress / 214230) + 800, rc, 1, 2, 390); + drawAnimatedRect(buf, cast(uint)(animationProgress / 123320) + 900, rc, -1, -3, 150); + drawAnimatedRect(buf, cast(uint)(animationProgress / 100000) + 100, rc, -1, -1, 120); + } +} + Widget createEditorSettingsControl(EditWidgetBase editor) { HorizontalLayout res = new HorizontalLayout("editor_options"); res.addChild((new CheckBox("wantTabs", "wantTabs"d)).checked(editor.wantTabs).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.wantTabs = checked; return true;})); @@ -294,6 +339,8 @@ extern (C) int UIAppMain(string[] args) { tabs.addTab((new TextWidget()).id("tab5").textColor(0x00802000).text("Tab 5 contents"), "Tab 5"d); + tabs.addTab((new SampleAnimationWidget("tab6")).layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT), "Animation"d); + //========================================================================== // create Editors test tab VerticalLayout editors = new VerticalLayout("editors"); diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index 22810a8a..f6854bbe 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -171,7 +171,8 @@ class Window { // layout required flag could be changed during animate - check again checkUpdateNeeded(needDraw, needLayout, animationActive); } - if (needLayout) { + lastDrawTs = ts; + if (needLayout) { long measureStart = currentTimeMillis; measure(); long measureEnd = currentTimeMillis; @@ -192,7 +193,6 @@ class Window { long drawEnd = currentTimeMillis; if (drawEnd - drawStart > PERFORMANCE_LOGGING_THRESHOLD_MS) Log.d("draw took ", drawEnd - drawStart, " ms"); - lastDrawTs = ts; if (animationActive) scheduleAnimation(); } @@ -471,7 +471,7 @@ class Window { protected void checkUpdateNeeded(Widget root, ref bool needDraw, ref bool needLayout, ref bool animationActive) { if (root is null) return; - if (!root.visibility == Visibility.Visible) + if (root.visibility != Visibility.Visible) return; needDraw = root.needDraw || needDraw; if (!needLayout) { @@ -480,7 +480,8 @@ class Window { Log.d("need layout: ", root.id); } } - animationActive = root.animating || animationActive; + if (root.animating && root.visible) + animationActive = true; // check animation only for visible widgets for (int i = 0; i < root.childCount; i++) checkUpdateNeeded(root.child(i), needDraw, needLayout, animationActive); } diff --git a/src/dlangui/platforms/sdl/sdlapp.d b/src/dlangui/platforms/sdl/sdlapp.d index d8582012..5fbe7134 100644 --- a/src/dlangui/platforms/sdl/sdlapp.d +++ b/src/dlangui/platforms/sdl/sdlapp.d @@ -139,6 +139,11 @@ version(USE_SDL) { SDL_SetWindowTitle(_win, _caption.toStringz); } + /// after drawing, call to schedule redraw if animation is active + override void scheduleAnimation() { + invalidate(); + } + SDL_Texture * _texture; int _txw; int _txh; diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index d0dfeb39..d5f30080 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -411,7 +411,7 @@ class Widget { @property bool needDraw() { return _needDraw; } /// returns true is widget is being animated - need to call animate() and redraw @property bool animating() { return false; } - /// animates window; interval is time left from previous draw, in hnsecs (1/10000 of second) + /// animates window; interval is time left from previous draw, in hnsecs (1/10000000 of second) void animate(long interval) { } /// returns measured width (calculated during measure() call)