class SceneObject
def initialize(&generate)
@generate = generate
end
def render
self.instance_eval(&@generate)
end
end
class MyObject < SceneObject
def initialize
super() do
# Render some objects
end
end
end
a = MyObject.new
a.render
This all works, but I'd like to 'hide' the class definition stuff, the
reason being that the data files passed through this system will be
defined outside, and don't need to look like Ruby code, they 'use'
Ruby code to do the procedural stuff, but other than that I want them
to appear as simple as possible, so hiding classes, inheritance,
initialisation functions etc. would be a big benefit. Ideally I'd like
to do something like this, but can't...
def defineClass(name,&generate)
eval <<-"end_eval"
class #{name} < SceneObject
def initialize
super(&#{generate})
end
end
end_eval
end
Then in my data files use this function like so...
defineClass("MyObject") do
# Render some objects
end
a = MyObject.new
a.render
Can anyone offer any advice on how to achieve something like this?
Cheers
PaulG
P> defineClass("MyObject") do
P> # Render some objects
P> end
P> a = MyObject.new
P> a.render
This is with ruby 1.7
pigeon% cat b.rb
#!./ruby
class SceneObject
def initialize(&generate)
@generate = generate
end
alias init initialize
def render
instance_eval(&@generate)
end
end
def defineClass(name, &block)
Object.const_set(name, Class.new(SceneObject)).instance_eval do
define_method(:initialize) { init(&block) }
end
end
defineClass("MyObject") do
puts "render some object"
end
a = MyObject.new
a.render
pigeon%
pigeon% b.rb
render some object
pigeon%
Guy Decoux
On Wed, 20 Nov 2002, ts wrote:
> def render
> instance_eval(&@generate)
> end
Is there any difference (significant or otherwise) between this and:
def render
@generate.call
end
?
David
--
David Alan Black
home: dbl...@candle.superlink.net
work: blac...@shu.edu
Web: http://pirate.shu.edu/~blackdav
d> Is there any difference (significant or otherwise) between this and:
d> def render
d> @generate.call
d> end
Yes, self :-)
pigeon% cat b.rb
#!./ruby
class SceneObject
def initialize(&generate)
@generate = generate
end
alias init initialize
def render
instance_eval(&@generate)
end
def rendernot
@generate.call
end
end
def defineClass(name, &block)
Object.const_set(name, Class.new(SceneObject)).instance_eval do
define_method(:initialize) { init(&block) }
end
end
defineClass("MyObject") do
puts "render some object #{self}"
end
a = MyObject.new
a.render
a.rendernot
pigeon%
pigeon% b.rb
render some object #<MyObject:0x401abb78>
render some object main
pigeon%
Guy Decoux
Brilliant, thanks, that is exactly what I needed.
Cheers
PaulG
P> Brilliant, thanks, that is exactly what I needed.
Well, I don't really know what you want to do, and I've tried to do what
you want but personnally I'll write it like this
pigeon% cat b.rb
#!/usr/bin/ruby
class SceneObject
class << self
attr_accessor :generate
end
def render
instance_eval(&type.generate)
end
end
def defineClass(name, &block)
Object.const_set(name, Class.new(SceneObject)).generate = block
end
defineClass("MyObject") do
puts "render some object #{self}"
end
a = MyObject.new
a.render
pigeon%
pigeon% b.rb
render some object #<MyObject:0x401ad1f8>
pigeon%
I don't know why but it seems more natural, for me, to have a class
instance variable rather than try to call #initialize
Guy Decoux
Next question: is it possible to specify arguments to the initialize
method when defining it with this code?
I'd like to be able to do something like...
defineClass("MyObject", scale) {
scale(scale)
puts(scale)
}
And have this define a class which takes one argument in its
constructor, then use it thus...
a = MyObject.new(1.5)
Cheers
PaulG
P> Next question: is it possible to specify arguments to the initialize
P> method when defining it with this code?
Well, you can write
pigeon% cat b.rb
#!./ruby
class SceneObject
def initialize(scale, &generate)
@scale = scale
@generate = generate
end
alias init initialize
def render
instance_eval(&@generate)
end
end
def defineClass(name, &block)
Object.const_set(name, Class.new(SceneObject)).instance_eval do
define_method(:initialize) {|scale| init(scale, &block) }
end
end
defineClass("MyObject") do
puts "render some object #{self.inspect}"
end
a = MyObject.new(1.5)
a.render
pigeon%
pigeon% b.rb
render some object #<MyObject:0x401abc2c @generate=#<Proc:0x401abd30@./b.rb:21>, @scale=1.5>
pigeon%
P> I'd like to be able to do something like...
P> defineClass("MyObject", scale) {
P> scale(scale)
P> puts(scale)
P> }
but in this case you must write it
defineClass("MyObject") {
scale(@scale)
puts(@scale)
}
Or you can make someting more complex
pigeon% cat b.rb
#!./ruby
class SceneObject
def initialize(params, &generate)
params.each do |k, v|
class << self; self end.send(:attr_accessor, k)
send("#{k}=", v)
end
@generate = generate
end
alias init initialize
def render
instance_eval(&@generate)
end
end
def defineClass(name, var, &block)
Object.const_set(name, Class.new(SceneObject)).instance_eval do
define_method(:initialize) {|scale| init(var => scale, &block) }
end
end
defineClass("MyObject", "scale") do
puts "render some object #{self.inspect}"
p self.scale
end
a = MyObject.new(1.5)
a.render
pigeon%
pigeon% b.rb
render some object #<MyObject:0x401ab7e0 @scale=1.5, @generate=#<Proc:0x401ab8f8@./b.rb:24>>
1.5
pigeon%
but you must prefix `scale' with `self.' otherwise ruby interpret it as a
local variable.
Guy Decoux
t> class << self; self end.send(:attr_accessor, k)
This is stupid, there is a better way
pigeon% cat b.rb
#!./ruby
class SceneObject
def initialize(params, &generate)
params.each do |k, v|
k.each_with_index do |name, i|
send("#{name}=", v[i])
end
end
@generate = generate
end
alias init initialize
def render
instance_eval(&@generate)
end
end
def defineClass(name, *var, &block)
Object.const_set(name, Class.new(SceneObject)).instance_eval do
var.each {|v| send(:attr_accessor, v)}
define_method(:initialize) {|*scale| init(var => scale, &block) }
end
end
defineClass("MyObject", "scale") do
puts "render some object #{self.inspect}"
end
a = MyObject.new(1.5)
a.render
defineClass("MyObject2", "scale1", "scale2") do
puts "render another object #{self.inspect}"
end
a = MyObject2.new(1.5, 3.0)
a.render
pigeon%
pigeon% b.rb
render some object #<MyObject:0x401ab31c @generate=#<Proc:0x401ab498@./b.rb:26>, @scale=1.5>
render another object #<MyObject2:0x401aafd4 @scale1=1.5, @generate=#<Proc:0x401ab2a4@./b.rb:33>, @scale2=3.0>
pigeon%
Guy Decoux
Spot on! Thanks, that is exactly the sort of thing I'm after.
In case you are interested in what I am trying to achieve, I am trying
to make a procedural animation system based around Renderman. Similar in
principle to WavesWorld by Michael B. Johnson, and AL my Steve May.
Basincally you define your objects in terms of code segments, which
(when I get round to this bit) have links to avars (animated variables)
which can be altered over time by various methods, then by adjusting
these avars, and regenerating the scene sections which rely on them, you
get a powerful animation system.
Long way off yet tho' still just planning and throwing ideas around.
cheers
PaulG
Please keep us (or at least me) posted on your progress, Paul!
Thanks!
-- Glenn Lewis