help shorten my script / 2 for loops

Hi,
i found the first half of the script by forum search.
Then i added the second half.
I already tried, but couldn´t find a way to stuff them together.
My Problem is, that the two loops take too long, so drawLine() flickers.

import GameLogic as gl
import Rasterizer as r

own = gl.getCurrentController().owner

def findObjectsByProperty(propName, value=None):
  objects = []
  for obj in gl.getCurrentScene().objects:
    if propName in obj:
      if value == None or obj[propName] == value:
        objects.append(obj) 
  return objects
#...

objects = findObjectsByProperty("instance")
for obj in objects:
    if (own['drawcount'] < len(objects)):
        r.drawLine(objects[own['drawcount']].position,objects[own['drawcount']-1].position,[1.0,1.0,1.0])
        own['drawcount'] = own['drawcount'] +1
    else:
        own['drawcount'] = 0

all that does is draw lines between objects i added to the scene in another script.

Can someone try to shorten it, so it calculates faster, or point me to how i can remove the flickering
(should i add the ‘added’ objects directly to a (maybe global) list and parse that?)

thanks

From what I see, you have GameLogic in there. Blender 2.5 doesn’t use that (so if you’re using 2.5, replace that with from bge import logic as GameLogic, if you don’t wish to replace all the GameLogic references). Also, you’re drawing duplicate lines. For example, in the code, you draw lines like this:

object 1 - object 2
object 1 - object 3
object 2 - object 1 <- unnecessary
object 2 - object 3
object 3 - object 1 <- unnecessary
object 3 - object 2 <- unnecessary

You should record which objects are drawn lines between, and keep track of those.

are you shure about that duplicate drawing?

breakdown:

loop through the objects:
check the counter: am i already at the last object in the list?
if not: draw a line from current object(derived from counter) to object in the list before
current
increase counter and repeat

so it´s :
0 line -1(none)
1 line 0
2 line 1
3 line 2 and so on
until:

counter is at last object, then:
counter is set to 0 to start over again

Edit: and i´m using 2.49 cause… i just like it :slight_smile:

Not sure how to reduce the number of loops, but you can speed up the first loop by getting rid of the .append as dotted elements are re-evaluated at every iteration causing slowdown. It would be faster to write:


def findObjectsByProperty(propName, value=None):
  objects = []
  append = objects.append
  for obj in gl.getCurrentScene().objects:
    if propName in obj:
      if value == None or obj[propName] == value:
        append(obj) 
  return objects

Using a global list for objects would be slower as python accesses local variables faster than global ones. You could also increase speed by only calling findObjectsByProperty when an object is added or removed instead of collecting the object list at every iteration of the code.

Finally, I believe that object properties are dictionary elements, so it might be faster use try/except rather than if. As the function checks the properties for all the objects in the scene if is likely to evaluated false a lot:


def findObjectsByProperty(propName, value=None):
  objects = []
  append = objects.append
  for obj in gl.getCurrentScene().objects:
    try:
      obj[propName] # breaks the loop if the obj dict doesn't have the property
      if value == None or obj[propName] == value:
        append(obj) 
    except KeyError:
      None
  return objects
# I've not tested this, but hopefully it's faster!

Hope this Helps!

Re-evaluation of dotted elements is negligible, in terms of performance (in almost every case).

The same could be said for persistent calls to findObjectsByProperty, even for relatively large sets of objects (in this case).

However, even if it was a performance issue, there should be no “line flickering”. The frame-rate would dip to some abysmally low number, but all the lines would still be drawn, on each and every frame.

My guess: you’re not executing the drawLine script on each and every frame.

In either case, I made a demo for you (attached). Press space to add objects; lines are drawn when there are 2 or more objects in the scene.

Attachments

draw_line.blend (138 KB)

Works and looks really right and good.
I especially like that line:
objects = [obj for obj in scene.objects if “instance” in obj]
i didn´t know, it could be that short.

i will adjust-copy-paste, if that´s ok.

Thank you.

heijulien