Jump to content

Nilium

Members
  • Posts

    22
  • Joined

  • Last visited

Posts posted by Nilium

  1. How do I produce this result?

     

    1. New Scene

    2. Create terrain: 512x512, 4 meters

    3. Sculpt the terrain a bit, just need some minor bumps, really

    4. Add two road nodes

     

    Things cease to work as expected right about there. I would attach an example SBX, but it won't let me.

  2. No, I have it pretty well isolated. It occurs when I try to do anything with modelreference after it is set to ...

     

    I'll keep messing around with it.

    Try adding error("<" .. type(modelreference) .. "> " .. tostring(modelreference), 1) right after you set modelreference. I'd be interested in knowing exactly what shows up as the error message there.

  3. I don't see anything in the script that would cause that error, and assuming your Lua type's methods are essentially one-to-one wrappers around the existing API, I don't know that there's a problem with that. Probably an error in another script.

  4. Forgot about the modelreference bit. Add local modelreference = ... just after the require line. Could also do local class = CreateClass(...).

     

    Also, when checking the result of luaL_loadfile, luaL_dofile, etc. you check to see if the result is zero, not if it's non-zero (so, result=0 means no errors), so that's also an error in your code there.

     

    Out of curiosity, Josh, do you have a Google Wave account?

  5. Replace the 'class=nil' bit at the end of that script with 'return class' and use luaL_loadfile like so:

     

    lua_pushstring(L, entity_class_name+"_CreateClass") ' e.g., light_directional
    luaL_loadfile(L, path_to_entity_script) ' loads the script as a Lua function
    lua_settable(L, LUA_GLOBALSINDEX) ' sets the global light_directional_CreateClass to the function

  6. I agree, fewer lines that I have to type the better. Your example of how to do it however isn't much fewer. I was more thinking of some kind of preprocessor macro stuff to make things look easier. Not sure if lua has that sort of thing.

    A preprocessor sounds like a horrifyingly bad idea.

     

    question: where is 'power' being defined at? should it be:

    Woops, editing stuff in the post window tends to do that.

  7. Is there any way that can be cleaned up somehow? 3 nested functions SetKey() and everything needs to be in a nested function Create() just seems kind of messy. Even if this is how it has to be, there might be a way to hide some of this so it looks more straight forward.

    What would your solution be?

     

    Personally, I see nothing wrong with this, aside from a bit of unnecessary code. E.g., in SetKey, all you'd need is this:

    function object:SetKey(key,value)
    if key=="resolution" then
    	local value = tonumber(value)
    	if 0 <= power and power <= 3 then object.light:SetShadowmapSize(256 * 2^power) end
    else
    	return self.super:SetKey(key,value)
    end
    end

    This probably comes down to coding style, however, but I like having fewer lines. Far as I'm concerned, nested functions in Lua are fine. You wouldn't have to put everything in Create, for one - you could store it in a local and reference that in the function, like so:

     

    require "scripts/class"
    
    do
    
    local function table_merge(table, into)
    	for k,v in next, table, nil do
    		into[k]=v
    	end
    end
    
    -- object methods
    local object_methods = {}
    
    function object_methods:SetKey(key,value)
    	if key=="resolution" then
    		local power = tonumber(value)
    		if 0 <= power and power <= 3 then object.light:SetShadowmapSize(256 * 2^power) end
    	else
    		return self.super:SetKey(key,value)
    	end
    end
    
    function object_methods:GetKey(key,value)
    	if key=="linearoffset" then
    		return object.light:GetShadowOffset(0,0)..","..object.light:GetShadowOffset(0,1)..","..object.light:GetShadowOffset(0,2)
    	elseif key=="shadowdistance" then
    		return object.light:GetShadowDistance(0)..","..object.light:GetShadowDistance(1)..","..object.light:GetShadowDistance(2)
    	else
    		return self.super:GetKey(key,value)
    	end
    end
    
    function object_methods:Kill(model)
    	if self.light then
    		self.light:Free()
    		self.light = nil
    	end
    	self.super:Kill()
    end
    
    
    -- class methods
    local class_methods = {}
    
    function class_methods:InitDialog(grid)
    	self.super:InitDialog(grid)
    	group=grid:AddGroup("Light")
    	group:AddProperty("Resolution",PROPERTY_CHOICE,"256,512,1024,2048")
    	group:AddProperty("linearoffset",PROPERTY_VEC3,"0,1,2","Linear offset" )
    	group:AddProperty("shadowdistance",PROPERTY_VEC3,"","Shadow distance" )
    	group:AddProperty("Range",PROPERTY_FLOAT)
    	group:Expand(1)	 
    end
    
    function class_methods:Spawn(model)
    	local object=self.super:Spawn(model)
    	object.model:SetKey("resolution","2")
    	object.light=CreateDirectionalLight(object.model)	       
    
    	table_merge(object_methods, object)
    
    	return object
    end
    
    
    -- light_directional_CreateClass
    function light_directional_CreateClass(modelreference)
    	local class=CreateClass(modelreference)
    	table_merge(class_methods, class)
    	return class
    end
    
    end
    

  8. I'm making a bunch of assumptions about how you're doing this, but I'm going to assume I'm right.

     

    ' doing this longhand so exactly what is going in is more apparent (synonymous with lua_getglobal(L, "entitytable"))
    lua_pushstring(L, "entitytable")		' stack =>  -1 = "entitytable"
    lua_gettable(L, LUA_GLOBALSINDEX)		' stack =>  -1 = entitytable ref
    
    lua_pushbmaxobject(L, model)			' stack =>  -2 = entitytable ref, -1 = model object
    ' get the "entity" table stored in "entitytable" (similar names make these examples confusing as hell)
    lua_gettable(L, -2)						' stack =>  -2 = entitytable ref, -1 = entity ref
    ' remove the "entitytable" reference since it's unneeded
    lua_remove(L, -2)						' stack =>  -1 = entity ref
    
    ' longhand (synonymous with lua_getfield(L, "SetKey", -2))
    lua_pushstring(L, "SetKey")				' stack =>  -2 = entity ref, -1 = "SetKey"
    ' get SetKey method
    lua_gettable(L, -2)						' stack =>  -2 = entity ref, -1 = function
    
    ' then push the "entity" table to the top of the stack so it will be the 'self' parameter
    lua_pushvalue(L, -2)					' stack =>  -3 = entity ref, -2 = function, -1 = entity ref (self argument)
    ' remove entity ref at -3
    lua_remove(L, -3)						' stack =>  -2 = function, -1 = entity ref (self argument)
    
    ' push a key and value
    
    ' by now the stack should be something like  -4 = function, -3 = entity ref (self argument), -2 = key argument, -1 = value argument
    lua_pcall(L, 3, 0, 0)					' stack =>  either nothing left or -1 = error string if there was an error
    

     

    The code highlighting on this forum desperately needs a 'turn the hell off' option.

  9. lua_getglobal(L, "referencetable") ' I'm assuming the "reference" table should be a local here, so not in the globals table
    lua_pushnumber(L, 3) ' push the key
    lua_gettable(L, -2) ' get the value
    
    ' or with an object:
    lua_getglobal(L, "classtable") ' _G["classtable"]
    lua_pushbmaxobject(L, modelreference) ' modelreference
    lua_createtable(L, 0, 0) ' {}
    lua_settable(L, -3) ' classtable[modelreference]={}
    lua_pop(L, 1) ' remove the table from classtable from the stack

     

    Not sure I see the problem. Maybe you're mistakenly thinking that the only way to get values out of/put values in a table is with lua_get/setfield?

  10. That doesn't seem to work. I have this code in the Update of vehicle_monstertruck.lua and that is in my scene. When I open up the scene I have saved with this code in it I get "attempt to call global 'iterate' (a nil value)" error.

     

    Did you make the iterate function in lua? If so what lua file?

    It's in the linked list script.

  11. dofile(...) is part of the Lua base package. It's not going to recognize any sort of abstract:: protocol. You need to write your own dofile/require/import/etc. routine if you want it to.

     

    E.g.,

    do
    local p_dofile = dofile
    dofile = function(filename)
    	local cap = string.match(filename, "^abstract:.+)")
    	return p_dofile((cap and AbstractPath(cap)) or filename)
    end
    end

  12. Are you sure? Where is the proof of this? I have seen the opposite asserted.

    It's mainly conjecture. To me, 100 garbage collectors means you're calling on a different garbage collector 100 times. If you can do it all in one shot, I would say it's less expensive than collecting the same object 100 times over multiple GCs (e.g., share an object between all the states, each GC has to work with that object, as opposed to having one GC that collects one object [LuGI will only ever push one instance of an object to a given state, so duplicates don't occur]). Furthermore, I doubt creating and closing states frequently is going to be very fast. Any potential speed benefits gained by using multiple garbage collectors probably won't be applicable in a game engine. Again, perhaps something like a server would be better-suited to using multiple states.

     

    Is memory use by Lua even an issue?
    It is as far as I'm concerned. He asked for my opinion, after all, and I gave mine - if memory use isn't a concern of yours, then that's fine.

     

    This is not a concern, since no game engine can call random commands on separate threads without locking everything.
    That's not entirely true, but really it's unrelated to Leadwerks.

     

    According to Josh, the Lua implementation he uses doesn't allow integers to be passed to BlitzMax and then back to Lua via his Entity Message System, thus I have to send them as strings and get them back out as strings using tostring and tonumber respectively.
    This is a flaw due to his use of multiple states and probably not writing the function properly. It's entirely avoidable if you just check the type at the index, but he probably wrote that routine and wrapped it using LuGI, which tries to match the BlitzMax method as exactly as it can. As such, this isn't an issue I need to address.
  13. Uhm, the fact you wrote a Lua wrapper for Blitzmax doesn't mean your vote should count for more, nor did I find it humorous if it was supposed to be as such. You need to prove your expertise on the variable state field.

     

    List some pros/cons of both multi-state and single-state in your own opinion, if you may.

     

     

    Also, since you coded the wrapper I believe Josh uses, are you the one I need to bug to be able to pass Lua tables and numbers to and from Blitzmax?

     

    I was being fairly serious about my opinion being more valuable than that of the unwashed masses here. I wrote the code that allows you to do what you can (edit: to clarify, I mean LuGI, not the engine/editor code using Lua, since I have my disagreements about the way it looks to be implemented [which Josh has his own reasons for]), and chances are I know a fair bit more about what Josh is describing than the majority of the people here. As such, my opinion has more value than many of the others'.

     

    Pros of multi-state:

    • Everything is definitely separate
    • The different states can run in parallel

    Cons:

    • Memory use sky-rockets
    • You're going to be running as many garbage collectors as you have states (this is expensive)
    • Communication between states is incredibly difficult
    • Accordingly, everything you share is duplicated between states, and keeping those objects in sync can be a nightmare

     

    Pros of single-state:

    • You can have separate execution contexts, as with the multi-state setup, by using Lua threads
    • Sharing data between threads is easy, keeping things in sync is easy.
    • One garbage collector handling it all, less expensive overall than 30 to 100 or more garbage collectors running every X frames.
    • Memory consumption is significantly less.

    Cons:

    • You can't entirely guarantee there's zero communication between threads/execution contexts (it's not really an issue, but I suppose in a secure environment, such as in a server, you would want them 100% separate).
    • Lua threads do not run in parallel

     

    As far as I'm concerned, there's no good reason to be using multi-state unless you're running a web server that uses PayPal or some other payment stuff in Lua, at which point I would question your sanity for attempting that.

     

    Now, you can pass Lua tables to BlitzMax as an array (or a TMap, I suppose), and you can pass arrays to Lua as tables currently. However, I am phasing this out with support for direct array access, since converting to/from arrays and tables is a speed and memory hit that doesn't need to occur. Ideally, this shouldn't affect any scripts unless you were sort of abusing tables created from arrays, at which point you'll have to implement a new routine for converting arrays to tables (or just copy the routine in the master branch of LuGI). If there's some other sort of problem that you think I'm supposed to address, you should be less vague in stating what problem it is.

     

    Following that, I'm not sure what problem with passing numeric values to/from Lua you're having, but I can assure you that if you have trouble passing numbers to/from BlitzMax/Lua, you do not have a whole lot of room for talking.

     

    I'm not sure if Lua can pass a pointer to a table back to the main program.

    You can pass a pointer to a table back to the program, but this is a one-way thing. You cannot take the pointer and put it back on the stack. I'm not sure what the reason is, but the function for getting the pointer (lua_topointer) is mainly for debugging purposes. There's probably a good reason, I'm sure if you asked on a Lua mailing list they'd have some answers. This limitation has never actually affected me, so I didn't spend any amount of time looking it up until you'd asked about it some time ago.

  14. How can we share variables between all entity scripts?

    If you put each entity in a separate Lua thread (bear in mind that I am only talking about having one actual Lua state) and then give that thread a separate environment while still retaining access to the globals table (fairly easy to do with metatables), then you should have the same effect without the wasted memory use, need for things like "SetGlobal*", etc. I don't think it's likely that you'll be able to do this without writing your own code to handle entities in Lua, however.

    • Upvote 1
×
×
  • Create New...