This content has been marked as final. Show 14 replies
Which version of Director are you using, on which platform?
When you say "text object", do you mean #text member, #field member,
#flashComponent, or something else?
> Which version of Director are you using, on which platform?
> When you say "text object", do you mean #text member, #field member,
> #flashComponent, or something else?
#text. No anti-aliasing or other fanciness, boring old Arial font. I tried
with #field, but the lack of tabs and adjustable line-spacing made them
basically useless in this case. I've also tried separating it into either
11 separate columns or 16 separate rows. Rows performed better than
columns, but still not great.
Single text object, .line.word: 36-40 ticks per draw
Single text object, .line: 24-30 ticks per draw
Single text object, .text: 8-10 ticks per draw
11 Separate columns, .line = 13-16 ticks per draw
16 Separate rows, .word: 4-5 ticks per draw (This is what I'm settling
with right now)
No text changes at all: 0-1 ticks per draw
So I know it's still the text that's slowing this thing down. I haven't yet
tried it with 176 separate text objects for every single field (I'd have to
make a bunch more room on the score just to be able to fit that, and it'd be
really tedious to set up.
I suppose another option might be to fill a single text object with all 500+
lines at the beginning, and then just use the ScrollTop to do the scrolling
instead of scripting the text changes based on the scroll bar. Of course,
you'd still end up with a long wait the first time it populated (even
longer, since we're talking about 500+ lines instead of just the 16 that
show), but maybe if it were hidden behind a load-screen - still not ideal.
And the single-text object only performed at an even remotely acceptable
speed when I set the entire text in one shot - which took a monstrous amount
of code, and that was just 16 lines. Multiply that to the full 500+ and any
speed advantage is quickly lost. Seriously, there's got to be a better way
to do this...
As for #flashComponents, I'm not touching that. Every time I've used any of
the #flashComponent objects, it's always a pain - first you have to learn a
whole new scripting language to interact with them, second, they take over
your input control (even a flash button object for some reason interrupts
all keyboard input just by being on the screen), and third they have redraw
problems up the wazoo. (Half the time when I go to a new frame where the
flash object doesn't exist, it leaves pieces of itself on the screen for
some inexplicable reason.) As far as I'm concerned, flashComponents are a
broken feature which I will never use again unless there's some major
changes to how they work.
I wasn't suggesting you go near #flashComponents - particularly if
you're looking for performance. I just wanted clarification about "text
object" before progressing.
Where is the text you're using coming from? It sounds like you're
populating a #text member with the results of a database query. The
reason I ask is to try to find a way to optimise alterations. Updating
it, or creating it, at run-time seems to be a requirement, which
suggests something dynamic going on.
Can you provide a cut-down version somewhere for download that focuses
solely on text and performance?
> Where is the text you're using coming from? It sounds like you're
> populating a #text member with the results of a database query. The reason
> I ask is to try to find a way to optimise alterations. Updating it, or
> creating it, at run-time seems to be a requirement, which suggests
> something dynamic going on.
> Can you provide a cut-down version somewhere for download that focuses
> solely on text and performance?
Not easily. At any rate, it is *sort of* a database query, but not really.
I'm creating the database in Director as a property list, and it's already
created before any of the text stuff happens. I'm sure that it's not the
database query part of the equation that's causing the slow down, however,
as I've placed my tick-counters in such a way that it's only surrounding the
text-changing parts of the code. Much-simplified pseudo-code example:
--(All of this is generated before-hand, long before any of the code in
question takes place.)
pos = sprite("Slider").pos
--(changes based on the position of the slider sprite)
repeat with i = 1 to 16
record = database[i + pos]
n = the ticks
member("Text Member").line .word = record.name
member("Text Member").line.word = record.date
put the ticks - n
Since it isn't starting its tick-counter until after the database query, the
number that it puts out should show how long the text-management part is
taking. If I put those lines around the "record = database[i + X]" line, I
get 0's and 1's, so that part is happening lightning-quick. It's very
definitely the text-management that's making it take so long. I was
thinking it was all the complicated tabs in the text field that were causing
the issue (8 columns are center-justified, 1 is left-justified, and 2 are
right-justified), but given that my separate-rows code, complete with tabs
on each row, worked much faster than the separate-columns code (no tabs,
just the entire text member justified), I doubt that's the issue. As for
altering the text at runtime, there will be options to filter the data based
on the values, so, yes, the database that displays would have to be
generated on the fly if you used the filters. But that part of it is not
even implemented yet. (And the creation of the database right now happens
almost instantly, even though I'm generating 500+ entries with a dozen
properties each.) The slowdown is undeniably from the text populating.
> The slowdown is undeniably from the text populating.
You are most likely correct - which is why I was wanting a file to test
to see if I could figure out where and why.
Perhaps it's related to member.tabs, perhaps your text update routine
could be optimised with put ... into ... or setContents(), but without
some code to check against a pre-created member and "database" it
remains guesswork. While I'm happy to help, you might need to provide
some help, too, before others can.
I have seen something similar, but it was back in the days of D8 or 8.5
and the #text-related slowdown existed on Win2K but not Win98 (or vice
versa) - my memory of the details is fading.
Could you not rip your existing text member from your project and copy
the updating handler (along with a #movie script that provides sample
data to populate it with) so that others can test it? It might be
isolated to your machine, or be caused by an OS-related update, or a 3rd
one thing comes to mind: In your repeat loop, use a string variable, and write it to your text member after the loop. Maybe you can bypass the slowness then a bit.
Unfortunately, the text for D11 is even slower. I can't upgrade because of this. :( (bummer)
> one thing comes to mind: In your repeat loop, use a string variable, and
> write it to your text member after the loop. Maybe you can bypass the
> slowness then a bit.
Belated thanks, but I haven't had the chance to get back to work on this
until now - that does help quite a bit, cut my draw-time in half. Still not
as fast as I'd like it to be, (still losing 2-3 ticks to this process) but
much faster than before. I'm still currently using 16 separate text
members, though, so maybe if I use this technique and switch it back to a
single text member, it might be even faster - I'll try that and report
Another thought, untested.
What if you initialize the text member without tabs, insert the data, then
set the tab stops on the member?
Mark A. Boyd
> What if you initialize the text member without tabs, insert the data, then
> set the tab stops on the member?
Not sure at this point whether the tabstops have any effect. Combining it
all into a single scrolling text member had a dramatic effect - the
scrolling now takes 0-1 ticks, which is perfect. Only problem is I'm paying
for it by having a 2-second delay when you first populate the text member -
though I can cover this up with a "Loading" text or something. I think the
real slow-down now is the color-coding I'm putting on the text - positive
numbers green, negative red, etc. This was only eating 1-2 ticks per cycle
in my previous iterations because I was only coloring 16 lines at a time.
Now that I'm pre-generating the entire text member, I have to color all 500
lines at once, and I think that's the only remaining source of slow-down,
even if the slow-down is only at the very beginning. (Of course if you use
any of the filters once they're implemented, it will have to regenerate and
re-color the whole thing again, so I'll have to put in a "Loading" indicator
every time.) Is there a faster way to assign colors than this?
member("Text Member").line .word[x].color = rgb(255,0,0)
Unfortunately, colors are not preserved in a string variable, so this sort
of thing has to be done at the member-level.
> member("Text Member").line .word[x].color = rgb(255,0,0)
One slight optimisation is to cache your member reference prior to
tMember = member("Text Member")
repeat with l = 1 to whatever
tMember.line[l].word[w].color = rgb(255, 0, 0)
You could also cache colours into local variables and add word indices
into a list:
tWord = 0
tRed = rgb(255, 0, 0)
tGreen = rgb(0, 255, 0)
lRed = 
lGreen = 
repeat with aNumber in numbers
tWord = tWord + 1
tString = tString & TAB & string(aNumber)
if aNumber < 0 then lRed.append(tWord)
else if aNumber > 0 then lGreen.append(tWord)
tMember = member("Text Member")
repeat with aWord in lRed
tMember.word[aWord].color = tRed
repeat with aWord in lGreen
tMember.word[aWord].color = tGreen
Again, it's very difficult to suggest optimisations without you posting
some code. I don't understand your reluctance to do this since we're
here trying to help you.
> Again, it's very difficult to suggest optimisations without you posting
> some code. I don't understand your reluctance to do this since we're here
> trying to help you.
It's not a reluctance so much as there's just so much code going on (much of
it not related to this issue at all) that it would be somewhat difficult to
extract the relevant bits in any meaningful way. But since you insist, here
goes: (greatly simplified because nobody wants to go through the mountain of
code that goes with this)
member("Table Text").text = "Loading..."
str = ""
repeat with i = 1 to MPL.count
SI = MPL
str = str & TAB & SI.Rating & TAB & SI.Size & TAB & SI.Eff & TAB &
SI.Comp & TAB &\
SI.Area & TAB & SI.Spike & TAB & SI.SellerName & TAB &
calcItemBuyPrice(i) & RETURN
delete str.char[str.char.count] --Kills that extra RETURN at the end
member("Table Text").text = str
repeat with i = 1 to MPL.count
SI = MPL
member("Table Text").line .word[2..6].color = rgb(0,0,255)
if SI.Size > 0 then member("Table Text").line.word.color =
else if SI.Size < 0 then member("Table Text").line .word.color =
if SI.Eff > 0 then member("Table Text").line.word.color =
else if SI.Eff < 0 then member("Table Text").line .word.color =
if SI.Comp > 0 then member("Table Text").line.word.color =
else if SI.Comp < 0 then member("Table Text").line .word.color =
if SI.Area > 0 then member("Table Text").line.word.color =
if SI.Spike > 0 then member("Table Text").line .word.color =
member("Table Text").line.word.color = rgb(255,255,0)
member("Table Text").scrollTop = 0
You don't need to see the calcItemBuyPrice function, it just does a bit of
basic arithmetic and returns a number.
Okay, so MPL is the master list, and SI is used to refer to a Single Item in
that list. (I kept the name short in order to fit it in that long line
without too many \'s) All the properties shown are properties from the MPL,
which are copied over to the SI when we're dealing with just one record.
Most of the numbers display green for positive, red for negative, and blue
for 0. The Area and Spike properties are never negative, but display green
or red respectively for values above 0, and blue for 0. The first number
showing Rating and the 7th showing the SellerName are always white. The
last column showing the price is always yellow. (There's actually 3 more
columns, but they're always white and I'm trying to keep it simple here.)
Now, I realize there are two repeat loops that go through the entire list,
but the first takes very little time. (4-5 ticks, not bad for a one-time
thing.) It's the second loop with the color settings that's killing the
load-time, average 120 ticks. Your method of separating it out to only go
through the ones that need color changing doesn't seem like it would be that
effective, since nearly every figure on the list is colored, and since
there's multiple items per line, it would actually be a longer list to go
through with that method. (Several longer lists, actually.) As for keeping
the rgb values as separate variables - would that actually help? Or would
it be faster to use the indexed colors? (Since it's all pure red, green,
blue, yellow, white, the limited number of colors in the palette index is
actually sufficient.) I'll try a few things...
> Or would it be faster to use the indexed colors? (Since it's all pure
> red, green, blue, yellow, white, the limited number of colors in the
> palette index is actually sufficient.) I'll try a few things...
Self response: The answer is "No". Changing to palette indexes (or indeed
variables containing either rgb or indexed colors) doesn't have any
noticeable effect on the speed of operation.
My guess at the source of the problem is that every time you change a property of the text member such as the color of a word, then director creates a new image object in the background. That is a lot of overhead for the many changes you want to make. The only solution is to operate on a model of the data you want to display and only force a screen update after All changes have been made to your model.
I threw together a proof of concept this morning using a linear list of lists from which I generate html to describe the look of the table/grid. Since only one line of code alters the contents of the text member, it is acceptably fast.
Attach the following behavior to a text member. A mouse click will add ten rows of sample data. A mouse click with the Control key down will randomly change the color of every cell in the grid. The mouseDown handler is just for testing.
Hopefully this will be of use.
-- Colored Data Grid
On GetBehaviorDescription me
return "Colored Data Grid."
end GetBehaviorDescription me
On GetPropertyDescriptionList me
Props = [:]
Props[#pColumnCnt] = [#default:6, #format:#integer, #Range:[#Min:1, #Max:20], #comment:"Number Of Columns"]
Props[#pBorderSize] = [#default:1, #format:#integer, #Range:[#Min:0, #Max:4], #comment:"Grid Border Size"]
Props[#pDefaultTextColor] = [#default:color(0,0,0), #format:#color, #comment:"Default Text Color"]
Props[#pBackgroundColor] = [#default:color(255,255,255), #format:#color, #comment:"Background Color"]
end GetPropertyDescriptionList me
on beginSprite me
pMe = sprite(me.spriteNum)
pDataSet = 
-- refresh the display of the text
on refresh me
if pDataSet.count then
-- create Table Html
Table = "<table border=" & pBorderSize & ">"
repeat with Row in pDataSet
put "<tr>" after Table
repeat with Col in Row
put "<td><font color=" & Quote & Col.Color & Quote & ">" & Col.Text & " </font></td>" after Table
put "</tr>" after Table
put "</table>" after Table
-- create full html string
Full_Html = "<html><body bgcolor=" & Quote & pBackgroundColor.hexString() & Quote & ">" & Table & "</body></html>"
pMe.member.html = Full_Html
-- add row of text. ie ["One","Two","Three","Four","Five","Six"]
on addRow me, ListOfStrings
Row = 
repeat with ColNum = 1 to ListOfStrings.count
return pDataSet.count -- return number of rows in data set
-- set the color of the text for a row
on setRowColor me, RowNum, ColorDef
Row = pDataSet[RowNum]
repeat with ColNum = 1 to pColumnCnt
Row[ColNum].Color = ColorDef.hexString()
-- set the color of the text for a single cell
on setCellColor me, RowNum, ColNum, ColorDef
pDataSet[RowNum][ColNum].Color = ColorDef.hexString()
-- for testing
on mouseup me
StartTimeMils = the milliseconds
if _key.controlDown then -- randomly change the color of every cell
repeat with RowNum = 1 to pDataSet.count
repeat with ColNum = 1 to pColumnCnt
me.setCellColor(RowNum, ColNum, rgb(random(255),random(255),random(255)))
else -- add ten more rows of data
aStringList = ["One","Two","Three","Four","Five","Six"]
repeat with cnt=1 to 10
LastRow = me.addRow(aStringList)
me.refresh() -- update the screen
put the milliseconds - StartTimeMils & " Milliseconds for " & pDataSet.count & " Rows"