пятница, сентября 28, 2012

Delphi XE3.FireMonkey: Фиксим рваную анимацию

О проблемах с анимацией в FireMonkey я уже неоднократно писал. Причина кроется в недостаточной точности используемого типа - Single. С переработкой FireMonkey на архитектуру сервисов, произошедшую в Delphi XE3, появилась возможность очень просто этот косяк пофиксить. В общем, фикс можно скачать отсюда.

 

p.s. Достаточно подключить модуль к проекту. Работает начиная с Delphi XE3. Будем надеяться, что с первым апдейтом этот фикс станет ненужен.

9 комментариев:

Анонимный комментирует...

Где найти файл? по ссылке его нет.

Evil_Demon комментирует...

Где скачать сам файл? Ссылка нерабочая.

Kazantsev Alexey комментирует...

Если не качается пробуйте скопировать ссылку в адресную строку браузера (т.е. не кликайте по ней, а копируйте и переходите, Хрому это помогло). Если и так не получилось, добавьте www (раньше это работало). Я проверил своей Оперой, файл на месте и качается.

Evil_Demon комментирует...

пробовал фикс с Tfloatanomation - как дергалось - так и дергается
добавлял в uses формы

Kazantsev Alexey комментирует...

Если анимируется что-то тяжелое этот фикс не поможет, он лишь избавляет от ошибки вычисления момента следующего шага анимации при большом аптайме системы.

Анонимный комментирует...

Алексей, ссылка не работает вообще никак, хотелось бы про фикс по подробнее. У самого проблемы с рваной анимацией.

Kazantsev Alexey комментирует...

Странно. У меня качается без проблем. ОК, вот исходник:

Unit FMX.AnimationFixer;

//
// Animation fixer
// Copyright (c) 2012 Kazantsev Alexey (kazantsev.alexey@mail.ru)
//
// Published under the MIT license
//

Interface

Implementation

Uses

System.Diagnostics, FMX.Types, FMX.Platform;

Type

//
TAnimationFixer = Class(TInterfacedObject, IFMXTimerService)

Strict Private

FOldService : IFMXTimerService;
FStopwatch : TStopwatch;

Public

Class Procedure Install; Static;

Constructor Create(Const AOldService : IFMXTimerService);

Function CreateTimer(AInterval : Integer; ATimerFunc : TTimerProc) : TFmxHandle;
Function DestroyTimer(ATimer : TFmxHandle) : Boolean;
Function GetTick : Extended;

End;
//

{ TAnimationFixer }

//
Class Procedure TAnimationFixer.Install;
Var

OldService : IFMXTimerService;

Begin

OldService := IFMXTimerService(TPlatformServices.Current.GetPlatformService(IFMXTimerService));

Assert(Assigned(OldService));

TPlatformServices.Current.RemovePlatformService(IFMXTimerService);
TPlatformServices.Current.AddPlatformService(IFMXTimerService, TAnimationFixer.Create(OldService) As IFMXTimerService);

End;
//

//
Constructor TAnimationFixer.Create(Const AOldService : IFMXTimerService);
Begin

Inherited Create;

FOldService := AOldService;
FStopwatch := TStopwatch.StartNew;

End;
//

//
Function TAnimationFixer.CreateTimer(AInterval : Integer; ATimerFunc : TTimerProc) : TFmxHandle;
Begin

Result := FOldService.CreateTimer(AInterval, ATimerFunc);

End;
//

//
Function TAnimationFixer.DestroyTimer(ATimer : TFmxHandle) : Boolean;
Begin

Result := FOldService.DestroyTimer(ATimer);

End;
//

//
Function TAnimationFixer.GetTick : Extended;
Begin

If FStopwatch.ElapsedTicks > TStopwatch.Frequency * 2 Then
FStopwatch := TStopwatch.StartNew;

Result := FStopwatch.ElapsedTicks / TStopwatch.Frequency;

End;
//

Initialization

TAnimationFixer.Install;

End.

Анонимный комментирует...

Спасибо, я попробую. Кстати просмотрев код TAnithread понял что плавность можно поднять повысив значение глобальной переменной FMX.Types.AniFrameRate, по умолчанию там 30 кадров.

Kazantsev Alexey комментирует...

Там алгоритм такой, что он совсем не гарантирует установленное количество кадров. Все зависит от того насколько быстро будет выполняться каждый шаг анимации.