Ridley5 opened this issue on Jul 26, 2010 · 1724 posts
bagginsbill posted Wed, 25 August 2010 at 9:37 AM
Quote - > Quote - Some other differences in my exporter:
- Each exporter produces a "section" of the lux scene file. Mine can put these in separate files or all in one file, or any combination.
Oh boy. This is something we talked about very early. This is the reason why we distribute the parameter "file" and do print >> file, "another string to output to a file or stream".
The worker parts must not know where output goes to. The workers just have to write to "file". This is part of the framework from the first testversion.
You just reinventing the wheel.
But go ahead.
Well, yes, you have print >> file and you can pass any file to the exporter worker.
But, first thing I don't like is the exporter worker has to use print and format everything itself. Second, there is no provision for printing things out of order, which is sometimes necessary.
In my framework, there is a 'lux' object. This is a smart wrapper around files or other stream-like objects. It maintains a stack of streams, so you can push a new stream on it, write some stuff, and pop the stream.
Anybody can use print >>lux or lux.write(...) but this is not the most convenient approach.
Instead, the lux object understands a lot of methods.
To push a new scene sub-file, you say:
lux.pushFile('foo.lxx')
This automatically inserts an Include directive into the current output file which will include foo.lxx. Then it opens the foo.lxx file and pushes it on the output stack. When you're done with that subfile, you call lux.pop() and the file is closed. If a filename has a path it will be used, otherwise the output folder of the current file before pushing is used.
To push a new file without "including" it, just call lux.pushFile(filename, False). To just push an arbitrary stream call lux.push(stream). This stream will not be closed. To auto close it on pop, calls lux.push(stream, True).
As I said, you can format everything yourself, but that is error prone and is a lot of typing. Instead, the lux object has a special attribute setter. Assigning any attribute to it that is not one if it's own existing attributes is assumed to be a request to put a lux-style property.
For example, to set the camera field of view, instead of:
print >> file, ' "float fov" [%s]' % fov
I write:
lux.fov = fov
That does the same thing, because fov is a float.
To set the camera autofocus, instead of:
print >> file, ' "bool autofocus" ["%s"]' % gp.get("autofocus", "false")
I write:
lux.autofocus = autofocus
Lists and tuples are automatically examined to see what is inside, and the type is set from that. But sometimes a tuple can be a float vector, a color vector, a vector vector, etc. So there are easy ways to specify.
For example, instead of:
print >> file, ' "color L" [%s %s %s]' % tuple(self.color)
I write:
lux.color.L = color
To copy a bunch of values, you can use the method lux.copy.
Instead of:
print >> file, ' "bool autofocus" ["%s"]' % gp.get("autofocus", "false")
print >> file, ' "integer blades" [%s]' % gp.get("blades", 6)
print >> file, ' "string distribution" "%s"' % gp.get("distribution", "uniform")
print >> file, ' "integer power" [%s]' % gp.get("power", 1)
I write:
lux.copy(section, 'autoFocus', 'blades', 'distribution', 'power')
There is no need to specify types in this case because the actual values are already typed as bool, int, or string.
Whenever any of these setter methods are used, the values passed in are automatically transformed via the function s2lux. This converts True to "true", False to "false", etc. Also for strings, lux wants no spaces and all lower case, so it does that. For the rare case where you have a string that you do not want converted, you say:
lux.someProperty = literally(someValue)
To start a new lux object, you use the .typeof attribute like this:
lux.typeof.LightSource = 'spot'
lux.typeof.Camera = 'Perspective'
In the rare case where you really have to manually format something, you can just call lux and it works like C's printf.
lux('someOddThing [%.02d %02d %02d]n', a, b, c)
There are many other helper functions. With this scheme I stopped making errors in formatting, or forgetting what the type was supposed to be and, for example, printing a float when I wanted an integer or a bool.
Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)