Director needs to call cancelTimer if an effect is already in progress (patch)

I’ve noticed a VERY serious problem with the current Director class code.

If you set up a scene with any transition that requires a delay (like moveFromRight) and then do something that causes a new transition while the previous is still working, then it crashes.

For example, set up two screens: tapping Screen1 calls:

director:changeScene(“Screen2”,“moveFromRight”)

and tapping Screen2 calls:

director:changeScene(“Screen1”,“moveFromLeft”)

Now, tap Screen1 and BEFORE IT IS FINISHED sliding, tap the screen again. This will hang/crash.

I have come up with my own fix for this which should be incorporated into the code in the Code Repository:

  1. Within the directory.lua file, whenever you call timer.performWithDelay, save the result in a variable called directorTimer. For example:

directorTimer = timer.performWithDelay( fxTime, fxEnded )

do this for every occurrence of timer.performWithDelay

  1. At the end of the fxEnded(event) function, reset this variable by adding this line:

directorTimer = nil

  1. In the director:changeScene method, add this code just after the “if lastScene…end” block at the beginning of the function:
    [lua] if (directorTimer) then
    – ensure that we don’t change again until previous transition is finished
    timer.cancel( directorTimer);
    fxEnded();
    end[/lua]
    This will check to see if a current transition timer is already active, and if so it will cancel the timer and complete the previous transition before starting the new one.

With these changes the Director class works a LOT more reliably for me, even though I’m still having other timer troubles in other modules.

Hope this helps others. [import]uid: 12529 topic_id: 6199 reply_id: 306199[/import]

@MPotter

Thanks for the help! Some people asked me about this some time ago, the solution I gave to them was a boolean variable to test if the transition is running. This is at version 1.2 but I have a lot to do in that version before release it. I’m thinking on deploy it only with some bug fixes and the new features will be on the next version. [import]uid: 8556 topic_id: 6199 reply_id: 21385[/import]

Thank you MPotter for this fix (and ricardorauber for the framework). The app is not crashing anymore when switching fast between the pages. Great!
[import]uid: 7519 topic_id: 6199 reply_id: 21497[/import]

woud you please, post the full code with all change ?

[import]uid: 13061 topic_id: 6199 reply_id: 29554[/import]

Sure here it is:

[code]

module(…, package.seeall)

–====================================================================–
– DIRECTOR CLASS
–====================================================================–

– Version: 1.1
– Made by Ricardo Rauber Pereira @ 2010
– Blog: http://rauberlabs.blogspot.com/
– Mail: ricardorauber@gmail.com

– This class is free to use, feel free to change but please send new versions
– or new features like new effects to me and help us to make it better!

–====================================================================–
– CHANGES
–====================================================================–

– 06-OCT-2010 - Ricardo Rauber - Created
– 07-OCT-2010 - Ricardo Rauber - Functions loadScene and fxEnded were
– taken off from the changeScene function;
– Added function cleanGroups for best
– memory clean up;
– Added directorView and effectView groups
– for better and easier control;
– Please see INFORMATION to know how to use it

–====================================================================–
– VARIABLES
–====================================================================–

– currentView: Main display group
– nextView: Display group for transitions
– currentScreen: Active module
– nextScreen: New module
– lastScene: Active module in string for control
– nextScene: New module in string for control
– effect: Transition type
– arg[N]: Arguments for each transition
– fxTime: Time for transition.to

–====================================================================–
– INFORMATION
–====================================================================–

– * For best practices, use fps=60, scale = “zoomStretch” on config.lua

– * In main.lua file, you have to import the class like this:

– director = require(“director”)
– local g = display.newGroup()
– g:insert(director.directorView)

– * To change scenes, use this command [use the effect of your choice]

– director:changeScene(“settings”,“moveFromLeft”)

– * Every scene is a lua module file and must have a new() function that
– must return a local display group, like this: [see template.lua]

– module(…, package.seeall)
– function new()
– local lg = display.newGroup()
– ------ Your code here ------
– return lg
– end

– * Every display object must be inserted on the local display group

– local background = display.newImage(“background.png”)
– lg:insert(background)

– * This class doesn’t clean timers! If you want to stop timers when
– change scenes, you’ll have to do it manually.

–====================================================================–

directorView = display.newGroup()
currentView = display.newGroup()
nextView = display.newGroup()
effectView = display.newGroup()

local currentScreen, nextScreen
local lastScene = “main”
local fxTime = 200

directorView:insert(currentView)
directorView:insert(nextView)
directorView:insert(effectView)


– CLEAN GROUP

local function cleanGroups ( curGroup, level )
if curGroup.numChildren then
while curGroup.numChildren > 0 do
cleanGroups ( curGroup[curGroup.numChildren], level+1 )
end
if level > 0 then
curGroup:removeSelf()
end
else
curGroup:removeSelf()
curGroup = nil
return
end
end


– LOAD SCENE

local function loadScene ( nextScene )

nextScreen = require(nextScene).new()
nextView:insert(nextScreen)

end


– EFFECT ENDED

local function fxEnded ( event )

currentView.x = 0
currentView.y = 0
currentView.xScale = 1
currentView.yScale = 1

cleanGroups(currentView,0)

currentScreen = nextScreen
currentView:insert(currentScreen)
nextView.x = display.contentWidth
nextView.y = 0
nextView.xScale = 1
nextView.yScale = 1

directorTimer = nil

end


– CHANGE SCENE

function director:changeScene(nextScene,
effect,
arg1,
arg2,
arg3)


– If is the same, don’t change

if lastScene then
if string.lower(lastScene) == string.lower(nextScene) then
return true
end
end

if (directorTimer) then
– ensure that we don’t change again until previous transition is finished
timer.cancel( directorTimer);
fxEnded();
end

local showFx


– EFFECT: Move From Right

if effect == “moveFromRight” then

nextView.x = display.contentWidth
nextView.y = 0

loadScene (nextScene)

showFx = transition.to ( nextView, { x=0, time=fxTime } )
showFx = transition.to ( currentView, { x=display.contentWidth*-1, time=fxTime } )

directorTimer = timer.performWithDelay( fxTime, fxEnded )


– EFFECT: Over From Right

elseif effect == “overFromRight” then

nextView.x = display.contentWidth
nextView.y = 0

loadScene (nextScene)

showFx = transition.to ( nextView, { x=0, time=fxTime } )

directorTimer = timer.performWithDelay( fxTime, fxEnded )


– EFFECT: Move From Left

elseif effect == “moveFromLeft” then

nextView.x = display.contentWidth*-1
nextView.y = 0

loadScene (nextScene)

showFx = transition.to ( nextView, { x=0, time=fxTime } )
showFx = transition.to ( currentView, { x=display.contentWidth, time=fxTime } )

directorTimer = timer.performWithDelay( fxTime, fxEnded )


– EFFECT: Over From Left

elseif effect == “overFromLeft” then

nextView.x = display.contentWidth*-1
nextView.y = 0

loadScene (nextScene)

showFx = transition.to ( nextView, { x=0, time=fxTime } )

directorTimer = timer.performWithDelay( fxTime, fxEnded )


– EFFECT: Over From Top

elseif effect == “overFromTop” then

nextView.x = 0
nextView.y = display.contentHeight*-1

loadScene (nextScene)

showFx = transition.to ( nextView, { y=0, time=fxTime } )

directorTimer = timer.performWithDelay( fxTime, fxEnded )


– EFFECT: Over From Bottom

elseif effect == “overFromBottom” then

nextView.x = 0
nextView.y = display.contentHeight

loadScene (nextScene)

showFx = transition.to ( nextView, { y=0, time=fxTime } )

directorTimer = timer.performWithDelay( fxTime, fxEnded )


– EFFECT: Fade

– ARG1 = color [string]

– ARG1 = red [number]
– ARG2 = green [number]
– ARG3 = blue [number]

elseif effect == “fade” then

local r, g, b

if type(arg1) == “nil” then
arg1 = “black”
end

if string.lower(arg1) == “red” then
r=255
g=0
b=0
elseif string.lower(arg1) == “green” then
r=0
g=255
b=0
elseif string.lower(arg1) == “blue” then
r=0
g=0
b=255
elseif string.lower(arg1) == “yellow” then
r=255
g=255
b=0
elseif string.lower(arg1) == “pink” then
r=255
g=0
b=255
elseif string.lower(arg1) == “white” then
r=255
g=255
b=255
elseif type (arg1) == “number”
and type (arg2) == “number”
and type (arg3) == “number” then
r=arg1
g=arg2
b=arg3
else
r=0
g=0
b=0
end

nextView.x = display.contentWidth
nextView.y = 0

loadScene (nextScene)

local fade = display.newRect( 0 - display.contentWidth, 0 - display.contentHeight, display.contentWidth * 3, display.contentHeight * 3 )
fade.alpha = 0
fade:setFillColor( r,g,b )
effectView:insert(fade)

showFx = transition.to ( fade, { alpha=1.0, time=fxTime } )

directorTimer = timer.performWithDelay( fxTime, fxEnded )

local function returnFade ( event )

showFx = transition.to ( fade, { alpha=0, time=fxTime } )

local function removeFade ( event )
fade:removeSelf()
end

directorTimer = timer.performWithDelay( fxTime, removeFade )

end

directorTimer = timer.performWithDelay( fxTime+1, returnFade )


– EFFECT: Flip

elseif effect == “flip” then

showFx = transition.to ( currentView, { xScale=0.001, time=fxTime } )
showFx = transition.to ( currentView, { x=display.contentWidth*0.5, time=fxTime } )

loadScene (nextScene)

nextView.xScale=0.001
nextView.x=display.contentWidth*0.5

showFx = transition.to ( nextView, { xScale=1, delay=fxTime, time=fxTime } )
showFx = transition.to ( nextView, { x=0, delay=fxTime, time=fxTime } )

directorTimer = timer.performWithDelay( fxTime*2, fxEnded )


– EFFECT: Down Flip

elseif effect == “downFlip” then

showFx = transition.to ( currentView, { xScale=0.7, time=fxTime } )
showFx = transition.to ( currentView, { yScale=0.7, time=fxTime } )
showFx = transition.to ( currentView, { x=display.contentWidth*0.15, time=fxTime } )
showFx = transition.to ( currentView, { y=display.contentHeight*0.15, time=fxTime } )
showFx = transition.to ( currentView, { xScale=0.001, delay=fxTime, time=fxTime } )
showFx = transition.to ( currentView, { x=display.contentWidth*0.5, delay=fxTime, time=fxTime } )

loadScene (nextScene)

nextView.x = display.contentWidth*0.5
nextView.xScale=0.001
nextView.yScale=0.7
nextView.y=display.contentHeight*0.15

showFx = transition.to ( nextView, { x=display.contentWidth*0.15, delay=fxTime*2, time=fxTime } )
showFx = transition.to ( nextView, { xScale=0.7, delay=fxTime*2, time=fxTime } )
showFx = transition.to ( nextView, { xScale=1, delay=fxTime*3, time=fxTime } )
showFx = transition.to ( nextView, { yScale=1, delay=fxTime*3, time=fxTime } )
showFx = transition.to ( nextView, { x=0, delay=fxTime*3, time=fxTime } )
showFx = transition.to ( nextView, { y=0, delay=fxTime*3, time=fxTime } )

directorTimer = timer.performWithDelay( fxTime*4, fxEnded )


– EFFECT: None

else
directorTimer = timer.performWithDelay( 0, fxEnded )
loadScene (nextScene)
end


– Clean up memory

if lastScene then
package.loaded[lastScene] = nil
end
lastScene = nextScene
collectgarbage(“collect”)

return true
end
[import]uid: 7519 topic_id: 6199 reply_id: 29596[/import]

I tried this code in my Director.lua file but did not work, because main is :
my code is work with my project, but urs it is work in the beginning but because my background
is moving from right to left, its move then everything disappear , may be something with
time of movement or speed of movement ?

my code has Delay time, but urs doesnt have,

what do I have to change ?

[code]
module(…, package.seeall)

–====================================================================–
– DIRECTOR CLASS
–====================================================================–

– Version: 1.2
– Made by Ricardo Rauber Pereira @ 2010
– Blog: http://rauberlabs.blogspot.com/
– Mail: ricardorauber@gmail.com

– This class is free to use, feel free to change but please send new versions
– or new features like new effects to me and help us to make it better!

–====================================================================–
– CHANGES
–====================================================================–

– 06-OCT-2010 - Ricardo Rauber - Created
– 07-OCT-2010 - Ricardo Rauber - Functions loadScene and fxEnded were
– taken off from the changeScene function;
– Added function cleanGroups for best
– memory clean up;
– Added directorView and effectView groups
– for better and easier control;
– Please see INFORMATION to know how to use it
– 14-NOV-2010 - Ricardo Rauber - Bux fixes and new getScene function to get
– the name of the active scene (lua file)
– 14-FEB-2011 - Ricardo Rauber - General Bug Fixes

–====================================================================–
– INFORMATION
–====================================================================–

– * For best practices, use fps=60, scale = “zoomStretch” on config.lua

– * In main.lua file, you have to import the class like this:

– director = require( “director” )
– local mainGroup = display.newGroup()
– mainGroup:insert( director.directorView )

– * To change scenes, use this command [use the effect of your choice]

– director:changeScene(“settings”,“moveFromLeft”)

– * Every scene is a lua module file and must have a new() function that
– must return a local display group, like this: [see template.lua]

– module(…, package.seeall)
– local localGroup = display.newGroup()
– function new()
– ------ Your code here ------
– return localGroup
– end

– * Every display object must be inserted on the local display group

– local background = display.newImage( “background.png” )
– localGroup:insert( background )

– * This class doesn’t clean timers! If you want to stop timers when
– change scenes, you’ll have to do it manually creating a clean() function.

–====================================================================–

directorView = display.newGroup()
currView = display.newGroup()
nextView = display.newGroup()
effectView = display.newGroup()

local currScreen, nextScreen
local currScene, nextScene = “main”, “main”
local newScene
local fxTime = 200
local safeDelay = 50
local isChangingScene = false

directorView:insert(currView)
directorView:insert(nextView)
directorView:insert(effectView)

currView.x = 0
currView.y = 0
nextView.x = display.contentWidth
nextView.y = 0


– GET COLOR

local function getColor ( arg1, arg2, arg3 )

local r, g, b

if type(arg1) == “nil” then
arg1 = “black”
end

if string.lower(arg1) == “red” then
r=255
g=0
b=0
elseif string.lower(arg1) == “green” then
r=0
g=255
b=0
elseif string.lower(arg1) == “blue” then
r=0
g=0
b=255
elseif string.lower(arg1) == “yellow” then
r=255
g=255
b=0
elseif string.lower(arg1) == “pink” then
r=255
g=0
b=255
elseif string.lower(arg1) == “white” then
r=255
g=255
b=255
elseif type (arg1) == “number”
and type (arg2) == “number”
and type (arg3) == “number” then
r=arg1
g=arg2
b=arg3
else
r=0
g=0
b=0
end

return r, g, b

end


– CHANGE CONTROLS

– fxTime
function director:changeFxTime ( newFxTime )
if type(newFxTime) == “number” then
fxTime = newFxTime
end
end

– safeDelay
function director:changeSafeDelay ( newSafeDelay )
if type(newSafeDelay) == “number” then
safeDelay = newSafeDelay
end
end


– GET SCENES

function director:getCurrScene ()
return currScene
end

function director:getNextScene ()
return nextScene
end


– CLEAN GROUP

local function cleanGroups ( curGroup, level )
if curGroup.numChildren then
while curGroup.numChildren > 0 do
cleanGroups ( curGroup[curGroup.numChildren], level+1 )
end
if level > 0 then
curGroup:removeSelf()
end
else
curGroup:removeSelf()
curGroup = nil
return true
end
end


– CALL CLEAN FUNCTION

local function callClean ( moduleName )
if type(package.loaded[moduleName]) == “table” then
if string.lower(moduleName) ~= “main” then
for k,v in pairs(package.loaded[moduleName]) do
if k == “clean” and type(v) == “function” then
package.loaded[moduleName].clean()
end
end
end
end
end


– UNLOAD SCENE

local function unloadScene ( moduleName )
if moduleName ~= “main” and type(package.loaded[moduleName]) == “table” then
package.loaded[moduleName] = nil
local function garbage ( event )
collectgarbage(“collect”)
end
garbage()
timer.performWithDelay(fxTime,garbage)
end
end


– LOAD SCENE

local function loadScene ( moduleName, target )

– Test parameters
if type(moduleName) == “nil” then
return true
end
if type(target) == “nil” then
target = “next”
end


– Load choosed scene

– Prev
if string.lower(target) == “curr” then

callClean ( moduleName )

cleanGroups(currView,0)

if nextScene == moduleName then
cleanGroups(nextView,0)
end

unloadScene( moduleName )

currScreen = require(moduleName).new()
currView:remove(currScreen)
currScene = moduleName

– Next
else

callClean ( moduleName )

cleanGroups(nextView,0)

if currScene == moduleName then
cleanGroups(currView,0)
end

unloadScene( moduleName )

nextScreen = require(moduleName).new()
nextView:insert(nextScreen)
nextScene = moduleName

end

end

– Load curr screen
function director:loadCurrScene ( moduleName )
loadScene ( moduleName, “curr” )
end

– Load next screen
function director:loadNextScene ( moduleName )
loadScene ( moduleName, “next” )
end


– EFFECT ENDED

local function fxEnded ( event )

currView.x = 0
currView.y = 0
currView.xScale = 1
currView.yScale = 1

callClean ( currScene )
cleanGroups( currView ,0)
unloadScene( currScene )

currScreen = nextScreen
currScene = newScene
currView:insert(currScreen)

nextView.x = display.contentWidth
nextView.y = 0
nextView.xScale = 1
nextView.yScale = 1

isChangingScene = false

end


– CHANGE SCENE


– Clean up memory

if lastScene then

– If you want to use a custom function to clean, use this
– if string.lower(lastScene) ~= “main” then
– package.loaded[lastScene].clean()
– end

package.loaded[lastScene] = nil
end
lastScene = nextScene
collectgarbage(“collect”)
function director:changeScene(nextLoadScene,
effect,
arg1,
arg2,
arg3)


– If is changing scene, return without do anything

if isChangingScene then
return true
else
isChangingScene = true
end


– If is the same, don’t change

if currScene then
if string.lower(currScene) == string.lower(nextLoadScene) then
return true
end
end

newScene = nextLoadScene
local showFx


– EFFECT: Move From Right

if effect == “moveFromRight” then

nextView.x = display.contentWidth
nextView.y = 0

loadScene (newScene)

showFx = transition.to ( nextView, { x=0, time=fxTime } )
showFx = transition.to ( currView, { x=display.contentWidth*-1, time=fxTime } )

timer.performWithDelay( fxTime+safeDelay, fxEnded )


– EFFECT: Over From Right

elseif effect == “overFromRight” then

nextView.x = display.contentWidth
nextView.y = 0

loadScene (newScene)

showFx = transition.to ( nextView, { x=0, time=fxTime } )

timer.performWithDelay( fxTime+safeDelay, fxEnded )


– EFFECT: Move From Left

elseif effect == “moveFromLeft” then

nextView.x = display.contentWidth*-1
nextView.y = 0

loadScene (newScene)

showFx = transition.to ( nextView, { x=0, time=fxTime } )
showFx = transition.to ( currView, { x=display.contentWidth, time=fxTime } )

timer.performWithDelay( fxTime+safeDelay, fxEnded )


– EFFECT: Over From Left

elseif effect == “overFromLeft” then

nextView.x = display.contentWidth*-1
nextView.y = 0

loadScene (newScene)

showFx = transition.to ( nextView, { x=0, time=fxTime } )

timer.performWithDelay( fxTime+safeDelay, fxEnded )


– EFFECT: Move From Top

elseif effect == “moveFromTop” then

nextView.x = 0
nextView.y = display.contentHeight*-1

loadScene (newScene)

showFx = transition.to ( nextView, { y=0, time=fxTime } )
showFx = transition.to ( currView, { y=display.contentHeight, time=fxTime } )

timer.performWithDelay( fxTime+safeDelay, fxEnded )


– EFFECT: Over From Top

elseif effect == “overFromTop” then

nextView.x = 0
nextView.y = display.contentHeight*-1

loadScene (newScene)

showFx = transition.to ( nextView, { y=0, time=fxTime } )

timer.performWithDelay( fxTime+safeDelay, fxEnded )


– EFFECT: Move From Bottom

elseif effect == “moveFromBottom” then

nextView.x = 0
nextView.y = display.contentHeight

loadScene (newScene)

showFx = transition.to ( nextView, { y=0, time=fxTime } )
showFx = transition.to ( currView, { y=display.contentHeight*-1, time=fxTime } )

timer.performWithDelay( fxTime+safeDelay, fxEnded )


– EFFECT: Over From Bottom

elseif effect == “overFromBottom” then

nextView.x = 0
nextView.y = display.contentHeight

loadScene (newScene)

showFx = transition.to ( nextView, { y=0, time=fxTime } )

timer.performWithDelay( fxTime+safeDelay, fxEnded )


– EFFECT: Crossfade

elseif effect == “crossfade” then

nextView.x = display.contentWidth
nextView.y = 0

loadScene (newScene)

nextView.alpha = 0
nextView.x = 0

showFx = transition.to ( nextView, { alpha=1, time=fxTime*2 } )

timer.performWithDelay( fxTime*2+safeDelay, fxEnded )


– EFFECT: Fade

– ARG1 = color [string]

– ARG1 = red [number]
– ARG2 = green [number]
– ARG3 = blue [number]

elseif effect == “fade” then

local r, g, b = getColor ( arg1, arg2, arg3 )

nextView.x = display.contentWidth
nextView.y = 0

loadScene (newScene)

local fade = display.newRect( 0 - display.contentWidth, 0 - display.contentHeight, display.contentWidth * 3, display.contentHeight * 3 )
fade.alpha = 0
fade:setFillColor( r,g,b )
effectView:insert(fade)

showFx = transition.to ( fade, { alpha=1.0, time=fxTime } )

timer.performWithDelay( fxTime+safeDelay, fxEnded )

local function returnFade ( event )

showFx = transition.to ( fade, { alpha=0, time=fxTime } )

local function removeFade ( event )
fade:removeSelf()
end

timer.performWithDelay( fxTime+safeDelay, removeFade )

end

timer.performWithDelay( fxTime+safeDelay+1, returnFade )


– EFFECT: Flip

elseif effect == “flip” then

showFx = transition.to ( currView, { xScale=0.001, time=fxTime } )
showFx = transition.to ( currView, { x=display.contentWidth*0.5, time=fxTime } )

loadScene (newScene)

nextView.xScale=0.001
nextView.x=display.contentWidth*0.5

showFx = transition.to ( nextView, { xScale=1, delay=fxTime, time=fxTime } )
showFx = transition.to ( nextView, { x=0, delay=fxTime, time=fxTime } )

timer.performWithDelay( fxTime*2+safeDelay, fxEnded )


– EFFECT: Down Flip

elseif effect == “downFlip” then

showFx = transition.to ( currView, { xScale=0.7, time=fxTime } )
showFx = transition.to ( currView, { yScale=0.7, time=fxTime } )
showFx = transition.to ( currView, { x=display.contentWidth*0.15, time=fxTime } )
showFx = transition.to ( currView, { y=display.contentHeight*0.15, time=fxTime } )
showFx = transition.to ( currView, { xScale=0.001, delay=fxTime, time=fxTime } )
showFx = transition.to ( currView, { x=display.contentWidth*0.5, delay=fxTime, time=fxTime } )

loadScene (newScene)

nextView.x = display.contentWidth*0.5
nextView.xScale=0.001
nextView.yScale=0.7
nextView.y=display.contentHeight*0.15

showFx = transition.to ( nextView, { x=display.contentWidth*0.15, delay=fxTime*2, time=fxTime } )
showFx = transition.to ( nextView, { xScale=0.7, delay=fxTime*2, time=fxTime } )
showFx = transition.to ( nextView, { xScale=1, delay=fxTime*3, time=fxTime } )
showFx = transition.to ( nextView, { yScale=1, delay=fxTime*3, time=fxTime } )
showFx = transition.to ( nextView, { x=0, delay=fxTime*3, time=fxTime } )
showFx = transition.to ( nextView, { y=0, delay=fxTime*3, time=fxTime } )

timer.performWithDelay( fxTime*4+safeDelay, fxEnded )


– EFFECT: None

else
timer.performWithDelay( 0, fxEnded )
loadScene (newScene)
end

return true

end

[/code] [import]uid: 13061 topic_id: 6199 reply_id: 29773[/import]

@eng.tareqali

The modification above is for director 1.1, the version you have is 1.2 - you shouldn’t need to use it there [import]uid: 8366 topic_id: 6199 reply_id: 29788[/import]

I got confused ,

my version is 1.2 ? so I should not use the Code that other member posted it ??

is this true ??

if yes,

how can I solve my problem ? hahahha
[import]uid: 13061 topic_id: 6199 reply_id: 29791[/import]

Use Version 1.2 as the original problem is fixed in there [import]uid: 8366 topic_id: 6199 reply_id: 29830[/import]