CrazyM Posted August 25, 2014 Share Posted August 25, 2014 I'm familiarizing myself with Leadwerks and so I have a simple test map that lets me place block prefabs like Minecraft. How can I retrieve the name from a pickinfo.entity? I tried the following, but it throws an error in Print in the window:MouseDown(1) check: (argument #3 is 'string'; '[no object]' expected.) function Script:UpdateWorld() if block == nil then block = Prefab:Load("Prefabs/CM/Block.pfb") block:SetKeyValue("name","Block") block:SetCollisionType(Collision.Prop) end local pickinfo = PickInfo() local mousePos = window:GetMousePosition() if (self.player.script.camera:Pick(mousePos.x, mousePos.y, pickinfo, pickradius, true)) then block:SetPosition(Vec3(math.floor(pickinfo.position.x), math.floor(pickinfo.position.y), math.floor(pickinfo.position.z)) + Vec3(pickinfo.normal.x, pickinfo.normal.y/2, pickinfo.normal.z)) end if window:MouseDown(2) then -- Place the block block = nil end if window:MouseDown(1) then -- Delete the block if pickinfo ~= nil then if pickinfo.entity ~= nil then System:Print(pickinfo.entity:GetKeyValue("name")) end --if pickinfo.entity:GetKeyValue("Name") == "Block" then -- pickinfo.entity:Release() --end end end end The other issue I'm having is that the placed prefabs have no physics collision. Thanks, Mike Quote CrazyMinnowStudio.com Youtube, Twitter, Facebook, G+ Link to comment Share on other sites More sharing options...
CrazyM Posted August 26, 2014 Author Share Posted August 26, 2014 Let me ask about entity identification another way. If I have a collision with an entity, what is the best way to distinguish the entity from another? For example: instantiated blocks have the name "Block" and the ground the blocks sit on is a CSG with the name "Ground". If I want to Release() blocks, but not the ground, I need to check the collision entity to determine it's a block and to Release it, or if it's the ground and to ignore the collision. Should I use the name of the entity (how do I get this), does Leadwerks have a layer system that I can place items on and check if the collision entity is on that layer, or maybe place a script on the ignore items and check for the type? Thanks Quote CrazyMinnowStudio.com Youtube, Twitter, Facebook, G+ Link to comment Share on other sites More sharing options...
AggrorJorn Posted August 26, 2014 Share Posted August 26, 2014 Fyi. In your first post you are using getkeyvalue with Name instead of name. 1 Quote Link to comment Share on other sites More sharing options...
Haydenmango Posted August 26, 2014 Share Posted August 26, 2014 Object:GetClass() is useful as well for things like telling if an object is terrain or if it is a model, etc. http://www.leadwerks.com/werkspace/page/documentation/_/command-reference/object/objectgetclass-r19 Quote Check out my game Rogue Snowboarding- https://haydenmango.itch.io/roguesnowboarding Link to comment Share on other sites More sharing options...
Guppy Posted August 26, 2014 Share Posted August 26, 2014 Given that you can set any old value with setKeyValue why not set a property telling your if it's destructible? :SetKeyValue("canBeMined",true) That way you can also have blocks that cannot be destroyed ( and comparing a bool almost certainly faster than doing string comparision ) Quote System: Linux Mint 17 ( = Ubuntu 14.04 with cinnamon desktop ) Ubuntu 14.04, AMD HD 6850, i5 2500k Link to comment Share on other sites More sharing options...
CrazyM Posted August 26, 2014 Author Share Posted August 26, 2014 @Aggor - yes the GetKeyValue() with upper case "Name" was a test, I tried upper and lower, they both produce the same error. @Haydenmango - Thanks, I'll try GetClass() and GetClassName() out. @Guppy - This sounds great because it would allow me to categories everything, and in my case I really only need a bool check, but can you spot anything I'm doing wrong with the code above, and why it errors: I instantiate the prefab, then set a key/value pair with name/Block block = Prefab:Load("Prefabs/CM/Block.pfb") block:SetKeyValue("name","Block") then, in the pickinfo I'm attempting to read the key/value pair System:Print(pickinfo.entity:GetKeyValue("name")) But the Print is producing this error: argument #3 is 'string'; '[no object]' expected. Thanks guys! Quote CrazyMinnowStudio.com Youtube, Twitter, Facebook, G+ Link to comment Share on other sites More sharing options...
shadmar Posted August 26, 2014 Share Posted August 26, 2014 Isn't csg blocks collapsed, so they are not really seperate runtime as entities, unless they have mass or have a connected script. Quote HP Omen - 16GB - i7 - Nvidia GTX 1060 6GB Link to comment Share on other sites More sharing options...
Ma-Shell Posted August 26, 2014 Share Posted August 26, 2014 I'm not too experienced in LUA but I would guess, you didn't define the key-value "name" for the ground and thus the function returning nil for that case and a comparison between nil and a String isn't possible (as said, I don't know about LUA, but I would guess that's the case). So have you tried checking whether it is nil before doing that? Something like: if pickinfo.entity:GetKeyValue("Name") then --This is the same as a comparison with ~= nil if pickinfo.entity:GetKeyValue("Name") == "Block" then pickinfo.entity:Release() end end 1 Quote Link to comment Share on other sites More sharing options...
Guppy Posted August 26, 2014 Share Posted August 26, 2014 Ran head long into much the same problem - I wanted to check if a specific key had NOT been set. In this case you would expect GetKeyValue to return nil - however it always returns a string and in the case of unset values it returns an empty string So if entity:GetKeyValue("unsetkey") ~= nil then System:Print('this will be printed'); end Where as if entity:GetKeyValue("unsetkey") ~= "" then System:Print('this wont be printed'); end Embarrassingly enough this is actually mentioned in the docs; http://www.leadwerks.com/werkspace/page/documentation/_/command-reference/entity/entitygetkeyvalue-r773 Quote System: Linux Mint 17 ( = Ubuntu 14.04 with cinnamon desktop ) Ubuntu 14.04, AMD HD 6850, i5 2500k Link to comment Share on other sites More sharing options...
CrazyM Posted August 27, 2014 Author Share Posted August 27, 2014 @shadmar - After you mentioned it, I started looking deeper into my prefab and the Leadwerks collision rules. I have made a little progress. I swapped my CSG block for a basic blender cube, and I'm now setting SetPickMode(0) and SetCollisionType(4) on the instantiated prefab so that it won't be picked while positioning for placement. I've adjusted my camera picks to use collision type to (2), and after I place a block I set SetPickMode(1) and SetCollisionType(2) so that it should be pickable again. Once a block is placed however, I can collide with it when walking up to it or jumping on top of it with the FPSPlayer, but I still can't camera pick the placed blocks. I have the exact same scenario using the CSG cube prefab after SetPickMode and SetCollisionType adjustments, the collider stops me from walking through it, but I can't pick it from the camera. These pick failure are what I was perceiving as Key/Value failures. If I place an instance of my prefab in the scene at design time, I can pick it at runtime and read the Key/Value, but not when instantiated during runtime. I tried adding world:Update and world:Render() after block placement just in case some physics update was necessary, but it had no effect. So it seems something must be required to commit pickmode and collisiontype changes at runtime, but I can't seem to figure out what. The current state of my script: Script.player = nil --entity "Player" window = Window:GetCurrent() world = World:GetCurrent() context = Context:GetCurrent() pickradius = 0.1 block = nil blockMode = false pickinfo = nil mousePos = nil function Script:Start() pickinfo = PickInfo() end function Script:UpdateWorld() mousePos = window:GetMousePosition() -- Toggle blockMode if window:KeyHit(Key.ControlKey) then if blockMode == false then blockMode = true else blockMode = false end end -- blockMode if blockMode == true then -- Load a new block if block == nil then block = Prefab:Load("Prefabs/CM/Cube.pfb") block:SetPickMode(0) -- ignore block:SetCollisionType(4) block:SetKeyValue("name","Block") end -- Position the block grid aligned and normal offset if block ~= nil then if (self.player.script.camera:Pick(mousePos.x, mousePos.y, pickinfo, pickradius, true, 2)) then block:SetPosition(Vec3(math.floor(pickinfo.position.x), math.floor(pickinfo.position.y), math.floor(pickinfo.position.z)) + Vec3(pickinfo.normal.x, pickinfo.normal.y, pickinfo.normal.z)) end end -- Place the block if window:MouseHit(2) then -- right mouse button block:SetPickMode(1) -- sphere block:SetCollisionType(2) block = nil end -- Debug if pickinfo ~= nil then if pickinfo.entity ~= nil then System:Print("pickinfo: " .. pickinfo.entity:GetKeyValue("name")) end end -- Release the block if window:MouseHit(1) then -- left mouse button if (self.player.script.camera:Pick(mousePos.x, mousePos.y, pickinfo, pickradius, true, 2)) then if pickinfo.entity:GetKeyValue("name") == "Block" then pickinfo.entity:Release() end end end else -- Not in blockMode, release the block if block ~= nil then block:Release() block = nil end end end Quote CrazyMinnowStudio.com Youtube, Twitter, Facebook, G+ Link to comment Share on other sites More sharing options...
CrazyM Posted August 29, 2014 Author Share Posted August 29, 2014 I finally got everything working to some degree. It could use some more refinement, but this was just an API familiarization exercise for me. Thanks everyone for you input and assistance. Just in case anyone is interested in the basis of a Minecraft style block pick/placement script, here it is. 1. Create a one unit (meter?) cube in your favorite 3D app. 2. Import and save as a prefab. 3. Create a pivot, and attached this script to it, then parent the pivot to your FPSPlayer. 4. Link in the player, prefab, a pickup sound, a placement sound, and a texture reticle. Left Ctrl = toggles in and out of block building mode Right mouse click = places a block Left mouse click = removes a block Cheers! EDIT: Updated to fix some issues Script.player = nil --entity "Player" Script.blockPrefab = "" --path "Prefab" "Prefab (*.pfb):pfb" Script.pickSound = "" --path "Pick Sound" "Sound File (*.wav):wav;Ogg Vorbis (*.ogg):ogg" Script.placeSound = "" --path "Place Sound" "Sound File (*.wav):wav;Ogg Vorbis (*.ogg):ogg" Script.reticle = "" --path "Reticle" "Tex file (*.tex):tex;" window = Window:GetCurrent() world = World:GetCurrent() context = Context:GetCurrent() pickradius = 0.1 block = nil blockMode = false pickinfo = nil mousePos = nil pickSnd = nil placeSnd = nil reticleOptic = nil function Script:Start() pickinfo = PickInfo() pickinfoTest = PickInfo() pickSnd = Sound:Load(self.pickSound) placeSnd = Sound:Load(self.placeSound) reticleOptic = Texture:Load(self.reticle) end function Script:UpdateWorld() mousePos = window:GetMousePosition() -- Toggle blockMode if window:KeyHit(Key.ControlKey) then if blockMode == false then blockMode = true else blockMode = false end end -- blockMode if blockMode == true then -- Load a new block if block == nil then block = Prefab:Load(self.blockPrefab) block:SetPickMode(0) -- ignore block:SetCollisionType(4) block:SetKeyValue("name","Block") end -- Position the block grid aligned and normal offset if block ~= nil then if (self.player.script.camera:Pick(mousePos.x, mousePos.y, pickinfo, pickradius, true)) then local blockPos = Vec3(Math:Round(pickinfo.position.x), Math:Round(pickinfo.position.y), Math:Round(pickinfo.position.z)) block:SetPosition(blockPos, true) end end -- Place the block if window:MouseHit(2) then -- right mouse button if placeSnd ~= nil then placeSnd:Play() end block:SetPickMode(2) -- Polygon block:SetCollisionType(2) block:SetShape(Shape:Box()) block:SetRotation(Vec3(0,0,0), true) block = nil end -- Release the block if window:MouseHit(1) then -- left mouse button if pickinfo.entity:GetKeyValue("name") == "Block" then System:Print("Release") pickinfo.entity:Release() if pickSnd ~= nil then pickSnd:Play() end end end else -- Not in blockMode, release the block if block ~= nil then block:Release() block = nil end end end function Script:PostRender(context) if reticleOptic ~= nil then context:SetColor(1,1,1,1) context:SetBlendMode(Blend.Alpha) context:DrawImage(reticleOptic, context:GetWidth()/2-32, context:GetHeight()/2-32, 64, 64) context:SetBlendMode(Blend.Solid) end end Quote CrazyMinnowStudio.com Youtube, Twitter, Facebook, G+ Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.