Multiple Object copy / positioning?

Blitz3D Forums/Blitz3D Beginners Area/Multiple Object copy / positioning?

Guy Fawkes(Posted 2012) [#1]
Hi all, As you saw in my last thread, I am making a multiple object level editor. Now... I have a small problem.... I need for this code when you press the C key, to make a copy of HOWEVER MANY objects are SELECTED, and make duplicates of each. then position them next to the other objects. SO for example:


O = A sphere
| = Space inbetween O & new O


O|O|O|O|O


Same thing with the Z Position. Only THAT one waits until a certain number of copies have been made, and adds the whole size of the mesh, and puts it under in a nice neat row.. So something like this:



O|O|O|O|O - Here, we have 5 O's
O|O|O|O|O - Now, it puts the 2nd set of the 5 O's DIRECTLY under the 1st set, and repeats the process. So:


O|O|O|O|O
O|O|O|O|O
O|O|O|O|O
...


Here's the code:







Thanks for any help everyone! :)

Last edited 2012


Ross C(Posted 2012) [#2]
Have you attempted to code this?


Guy Fawkes(Posted 2012) [#3]
Yes, look at this part:





I did this part. this is where im lost...


Ross C(Posted 2012) [#4]
Did you write that code yourself? You'll need to loop through all the entities stored in the selected type collection, and copy each of them.

Just as a side note, if you making an editor, you should seriously consider storing each entity in a type collection, to record properties about it that the blitz entity system can't hold. For now, your best sticking to what you have though.

For s.selected = each selected
Next


Is how you loop through each of your entities that is selected.


Guy Fawkes(Posted 2012) [#5]
Yes... for the 2nd time.. I wrote that part of the code... -.-


Ross C(Posted 2012) [#6]
You didn't say the firsdt time you had wrote that code. You said, here's what I have now, which could mean you've lifted a snippet from someone. I mearly ask, it doesn't contain any code to loop through each of the entities selected, which logically you need to do.


Guy Fawkes(Posted 2012) [#7]
http://blitzbasic.com/Community/posts.php?topic=97014#1124664


Yes, I did say it the 1st time...


Ross C(Posted 2012) [#8]
Ok, fair enough. Apologies! Anyway, I have given you the information to loop through your selected type collection. All you need to do is copy and move each entity.


Guy Fawkes(Posted 2012) [#9]
I got it to copy. thats not the problem. the problem is getting it positioned in rows....


Ross C(Posted 2012) [#10]
You can't position it in rows, if the original entities selected aren't in rows You don't have any reference. All you can do is offset the entities from their originals.

If you had:

---oo---
--o--o--
--o--o--
-o----o-
--o--o--
--o--o--
---oo---


You couldn't copy and position that in a row. By offsetting the copies from the orginals, if the originals are in a row, the copies will be. You just need to move them by a set amount, in a particular direction. MoveEntity entity,0,0,5 for instance.


Guy Fawkes(Posted 2012) [#11]
So let me get this straight. If I use Moveentity entity, 0, 0, 5, it will position in rows?


Ross C(Posted 2012) [#12]
No. You can only position them in rows, if the originals are in rows. You can only really offset them. To offset them is just to move them. So, thus the moveentity command is what you need.


Guy Fawkes(Posted 2012) [#13]
Ok, this is what I have...






I need a way for it to continue adding on each new object's mesh width, so that each new object created, has the coordinates of x = meshwidth(c\mesh)+spacing (spacing = the amount of space inbetween each object).


Ross C(Posted 2012) [#14]
Wait, how many times are you wanting the entity copied? I thought you were only copying every selected entity once, as per the usual copy operation.

Can you explain what the following code does?

					newents = CopyEntity(c\mesh)
					EntityType newents, type_obj
					EntityPickMode newents, 2, 1
					newents = c\mesh ; this line especially



Guy Fawkes(Posted 2012) [#15]
Makes a copy of a new entity. Sets the collision type of entity to type_obj. Turns on pickmode for that entity, and last but not least, converts that entity to a c\mesh, so that entity can be picked. otherwise, pick wont work.


Guy Fawkes(Posted 2012) [#16]
Ok. I'm a BIT close.... What I need for this code to do now, is when count is <= 6, it resets count, and resets the x position value back to the 1st object's x position. BUT. When it does this, it ALSO ADDS a meshdepth() to the y value, so that the objects appear in a 2nd row :)


Here's the code:






Guy Fawkes(Posted 2012) [#17]
Ok. I'm a BIT close.... What I need for this code to do now, is when count is <= 6, it resets count, and resets the x position value back to the 1st object's x position. BUT. When it does this, it ALSO SUBTRACTS a meshheight() to the y value, so that the objects appear in a 2nd row :)


Here's the code:





Last edited 2012


Ross C(Posted 2012) [#18]
whats does keyhit(46) do? Is that the copy key?


Guy Fawkes(Posted 2012) [#19]
Yes it is :)


Ross C(Posted 2012) [#20]
Ok, so, your doing things the wrong way round. Your looping through the entities, then your checking for a key hit. It should be:

Check for copy key hit.
If detected, then loop through and copy each entity in the type collection that is selected.

Also, are you keeping every entity you create in the type collection? If you are, then your losing all the copied entities by over writing the variables assigned to keep track of them:

newents = CopyEntity(c\mesh)
					EntityType newents, type_obj
					EntityPickMode newents, 2, 1
					newents = c\mesh ; this line especially


What the above is doing is:

Copying the entity and giving the copy a variable for itself.
Assigning that entity a pickmode and an entitytype
Then overwriting the very variable you are using to keep track of it.

If you aren't keeping track of every entity you create, then disregard what I have said.


Guy Fawkes(Posted 2012) [#21]
I'm still a bit confused... o.o


Rob the Great(Posted 2012) [#22]
Suppose you have an entity called "c\mesh". Blitz will not call it "c\mesh" when the game is running. Instead, "c\mesh" is called a pointer, which just means that when you type in "c\mesh", you're actually referring to the memory address generated when the game begins, and if you texted this information to the screen, it would display numbers like "0874360271".

So, when you create your new entity called "newents", "newents" is nothing more than a variable used for reference to another unique set of numbers. And just like any variable, you can change what its value is, which is what you're doing with this line:
newents = c\mesh ; this line especially

What you were trying to tell Blitz is that you wanted "newents" to be exactly like "c\mesh", but instead, Blitz changed the value of "newents" to now refer to "c\mesh". So, as a result, you've left the original "newents" in whatever state is was last, and you won't be able to get it back for the whole game. On top of that, Blitz thinks that "newents" and "c\mesh" are talking about the exact same entity, so now, this line:
MoveEntity newents,1,1,1

will do the exact same thing as this line:
MoveEntity c\mesh,1,1,1

To help you understand this further, consider this setup.

I'm going to create a variable called "x". I'm also going to create a variable called "y".
Global x = 1
Global y = 2

Next, think about what x becomes with this line of code:
x = y

Now that you have that in mind, think about this:
If x = 1 Then Print "This line will never be read."

When you use your code of "newents = c\mesh", you're not changing the entity, only the handle and what it refers to.


Guy Fawkes(Posted 2012) [#23]
That doesnt explain though how to gain control over the entities copying to rows.


Ross C(Posted 2012) [#24]
What do you mean, gain control?


Guy Fawkes(Posted 2012) [#25]
I mean like put the copied entities right next to each other up to a certain count, then reset the copys' X-Coords so that it goes to the second row after a certain count of objects have been copied


Ross C(Posted 2012) [#26]
You want to copy the selected entities.
You want to copy them a certain number of times.
You want to arrange them in columns and rows, say 4 by 5?

Fair enough, But what if you have multiple objects selected. That could end up a jumbled mess. How to you plan to adjust the the number of rows and columns it generates within the application and along what axis would they copy? What if you want to change the axis?

You should focus firstly on getting the program to simply copy each entity selected just once and position it a set distance away from the original. Get that to work, then you can modify what you have to build rows and what not.


Guy Fawkes(Posted 2012) [#27]
I did that already. the problem is rows, and multiple copying







Select ONE object, and press the C key 2 or more times.


Ross C(Posted 2012) [#28]
No it doesn't. It only copies one entity. I meant get the code to a point where it copies multiple entities, by looping through all the entities that have the selection flag set, once the copy key has been pressed.


Guy Fawkes(Posted 2012) [#29]
Ok, Ross. I've TRIED to fix the problem, but I still can't get it...



Here's the code:







Pay particular attention to this part:







Now, pay attention to this part, and this is where I get stuck:





Last edited 2012


Ross C(Posted 2012) [#30]
Your first piece of code. You only camerapick once. Your doing it every loop, which is wrong and will slow your code down ALOT. Place that command at the top, just before your loop starts. I don't know if that's you that put that there or not, but it needs to move.

Your last piece of code. As i said before, you need to:

1. check for the copy keyhit - your already doing this via keyhit(46)
2. loop through all the of the objects in your type collection. I have already shown you how to do this earlier, and you do in in your own code:

For c.Obj = each object

Next


3. Inside your loop you need to check firstly if the object is selected. You have a field in the type collection for this you can check.
4. If it is selected, do ahead with your copy code, which is already in place.

You haven't changed/removed:

newents = c\mesh

This will still leave the entity with no handle to allow you to alter it. For the time being, remove that line.

kind of psuedo code:

if key pressed for copy then
   start loop (looping through the type objects)
      check "selected" field in the type object
      If selected field = 1 then
         copy the entity to a new object:
            create a new object, using a different variable from the loop
            EG: loop is c.Obj, so say new.Obj = New Obj
            Use new\mesh = CopyEntity(c\mesh)
            set the entity type and pick mode refering to new\mesh
      End If
   Next Loop
End if


That's what the structure should look like. It is important you don't set the copies to be selected when doing this, or else you'll create an infinite loop of entity creation. So, just do it how you are just now.


Guy Fawkes(Posted 2012) [#31]



Ross, this is what I have so far...

Last edited 2012


Ross C(Posted 2012) [#32]
Where did e.enemy come from? You were building an editor with shapes. These were stored in the Obj type collection. You need to loop through the obj type collection, not enemy, as that's where your entities are stored.

What I would do, is created an entirely new function for the copying. Remove:

Function ObjUpdate()
	
	
	
	For c.Obj=Each Obj
		
			
			
			EntityAlpha c\mesh, .5
			
			
			
			If picked
				
				
				If KeyHit(46) Then
					For e.enemy = Each enemy
						e\selected = True
						If c\selected = 1 Then
							ne.Obj = New Obj
							ne\mesh = CopyEntity(c\mesh)
							EntityType ne\mesh, type_obj
							EntityPickMode ne\mesh, 2, 1
						End If
					Next
				End If


and create a new function called check_copy(). Without looking at your main code, it's hard to tell if you have code that checks key presses.

Call the check_copy() function from within your main update loop. You also don't seem to have moved the camerapick command you used to have. You seem to have completely removed it. Without that, the picking with the mouse won't work.


Guy Fawkes(Posted 2012) [#33]



Here's the code


Ross C(Posted 2012) [#34]
Ok...

1. There is no e.enemy anywhere being declared. You had pulled that from thin air, so delete that.

2. In your PickAll() function, CameraPick needs to go BEFORE the FOR loop starts.

3. Delete the entire function ObjUpdate(). It does nothing really. You should be setting the object selected's alpha when it is selected:

Function PickAll(camera)
	
	For c.Obj=Each Obj
		
		picked = CameraPick(camera,MouseX(),MouseY())
		
		If picked=c\mesh And EntityVisible(camera,c\mesh);If the object is clicked, change the field "c\selected" to 1.
			c\selected=1-c\selected
			If c\selected = 1 Then
                            objcountselected = objcountselected + 1
                            ; IN HERE SET ENTITY ALPHA OF THE SELECTED OBJECT
                        End If
			If c\selected = 0 Then objcountselected = objcountselected - 1
		EndIf
			
		If PickedEntity()=ground c\selected=0 : objcountselected = 0 ;Clicking the ground will de-select all the objects by setting "c\selected" to 0.
				
	Next
			
End Function




4. Copy the code you have for the keyhit(46) stuff:

			If KeyHit(46) Then
					For e.enemy = Each enemy
						e\selected = True
						If c\selected = 1 Then
							ne.Obj = New Obj
							ne\mesh = CopyEntity(c\mesh)
							EntityType ne\mesh, type_obj
							EntityPickMode ne\mesh, 2, 1
						End If
					Next
				End If


Into another function. Call it check copy key or something.

Instead of the e.enemy = each enemy, you should have...? Something to do with .Obj...


Also, it's cleaner when:
	If ObjsSelected=0 picked=0 
	
	
	If MouseHit(1) Then inpickmode = PickAll(camera) ;Run the function for selecting an object
	If ObjsSelected<>0 Then inpickmode = True : Else inpickmode = False;THIS LINE IS BETTER :)
	



Looks like:

	If ObjsSelected=0 picked=0 
	
	
	If MouseHit(1) Then
              inpickmode = PickAll(camera) ;Run the function for selecting an object
        End If

	If ObjsSelected<>0 Then
              inpickmode = True
        Else
              inpickmode = False;NOT REALLY :)
        End If
	
		


It maybe more lines, but it's easier to follow.


Guy Fawkes(Posted 2012) [#35]
Alright, now I'm lost...






Ross C(Posted 2012) [#36]
Your lost at what? Points number 1 and 2 are super easy to do. What specifically are you having trouble with?

Last edited 2012


Guy Fawkes(Posted 2012) [#37]
Well, when I compile this for some reason, it crashes :)


Ross C(Posted 2012) [#38]
You haven't changed the other things I told you too:


2. In your PickAll() function, CameraPick needs to go BEFORE the FOR loop starts.

3. Delete the entire function ObjUpdate(). It does nothing really. You should be setting the object selected's alpha when it is selected:



You are now setting the alpha so the ObjUpdate function is redudant.

And this:

	
	If KeyHit(46) Then
		For e.obj = Each Obj
			For c.obj = Each Obj
			e\selected = True
			If c\selected = 1 Then
				ne.Obj = New Obj
				ne\mesh = CopyEntity(c\mesh)
				EntityType ne\mesh, type_obj
				EntityPickMode ne\mesh, 2, 1
			End If
		Next
		Next
	End If


You don't need the:

For e.obj loop at all, or the e\selected.


Guy Fawkes(Posted 2012) [#39]
Ok, Ross, I did everything u said, here's the new code, and it's copying the object in the SAME coordinates as the old object:







Thanks, Ross! :)


Ross C(Posted 2012) [#40]
As I said in my last post, remove the e.obj and the e/selected from your Check_Copy_key() function.

You need to understand your own code. If you wanted to move a mesh, after it was copied, where would you put code to do that?

Your code is coming together.

Last edited 2012


Guy Fawkes(Posted 2012) [#41]
Moveentity e\mesh, 0, 0, 5 ?


Ross C(Posted 2012) [#42]

As I said in my last post, remove the e.obj and the e/selected from your Check_Copy_key() function



What variable did you put your copy into?

ne\mesh = CopyEntity(c\mesh)


This is the entity you need to move. And please remove the e.obj loop and e\selected references.


Guy Fawkes(Posted 2012) [#43]
EDITED

Last edited 2012


Ross C(Posted 2012) [#44]
??? That's completely different code from your editor.


Guy Fawkes(Posted 2012) [#45]
Woops, sorry ross. I accidently posted the wrong code o.o


Here's my editor:






Guy Fawkes(Posted 2012) [#46]
Sorry bout that, Ross :)


Ross C(Posted 2012) [#47]
... You still have the e.obj loop in there and the reference to e\selected. In fact, you haven't changed anything in there since last time?


Guy Fawkes(Posted 2012) [#48]
I know what's goin' on, Ross.. I accidently forgot I was using a function and put the fixed code in the main loop, not in the function itself. I fixed it :P Sorry about that :P






Ross C(Posted 2012) [#49]
Ok, good stuff. Now where do you reckon you'll put the MoveEntity command, to offset the copy?


Guy Fawkes(Posted 2012) [#50]




?


Don't u mean copIES? :)


Ross C(Posted 2012) [#51]
Ok, your above code will push the copied entity 5 units into the screen, along the z-axis. Does it work? More importantly, does it work with multiple entities?

Last edited 2012


Guy Fawkes(Posted 2012) [#52]
Yes, it DOES copy multiple entities. problem is, after the 1st COPIED entities, it keeps bunching up the copies AFTER the 1st copies, at the same coordinates ><


Ross C(Posted 2012) [#53]
It's only making one copy of each entity selected. You haven't built the functionality to produce more than one copy yet. Small fix. You need to set the alpha of the newly copied entity back to 1, as it's copying the transparency of the original:

	If KeyHit(46) Then
		For c.obj = Each Obj
			If c\selected = 1 Then
				ne.Obj = New Obj
				ne\mesh = CopyEntity(c\mesh)
				EntityType ne\mesh, type_obj
				EntityPickMode ne\mesh, 2, 1
                                MoveEntity ne\mesh, 0, 0, 5
                                EntityAlpha ne\mesh,1
			End If
		Next
	End If


Also, you want to set the entityalpha of the entity if it's deselected:

Function PickAll(camera)
	
	picked = CameraPick(camera,MouseX(),MouseY())
	
	For c.Obj=Each Obj
		
		If picked=c\mesh And EntityVisible(camera,c\mesh);If the object is clicked, change the field "c\selected" to 1.
			c\selected=1-c\selected
			If c\selected = 1 Then
				objcountselected = objcountselected + 1
                            ; IN HERE SET ENTITY ALPHA OF THE SELECTED OBJECT
				EntityAlpha c\mesh, .5
			End If
			If c\selected = 0 Then
				objcountselected = objcountselected - 1
				EntityAlpha c\mesh,1
			EndIf
		
		If PickedEntity()=ground c\selected=0 : objcountselected = 0 ;Clicking the ground will de-select all the objects by setting "c\selected" to 0.
			
		Next
		
End Function


Last edited 2012


Guy Fawkes(Posted 2012) [#54]
Ok, here's the updated code:







Now THIS is where im stuck.. how do i make more than 1 copied objects at once? :/


Ross C(Posted 2012) [#55]
Well, that's something you'll have to think about. You can rule out pressing the copy key lots of times and have rows build up. That's much too complex a process, with the possiblity of things changing between presses.

Your best bet it to have a changable option on screen, where you can adjust the amount of copies it makes. You still have the problem of these copies intersecting or getting lost inside other meshes. But I suppose that's a problem for most editors.

Last edited 2012


Ross C(Posted 2012) [#56]
.

Last edited 2012


Guy Fawkes(Posted 2012) [#57]
Ok, then how can I have it just make copies in rows, using the meshwidth of the last copied object, with a LITTLE space inbetween each object?


Ross C(Posted 2012) [#58]
How many rows? Again, you need to consider the wider usage. What about checking for the CTRL key, plus one of the numbers keys? That way, if you want to copy, you simply press CTRL + 4 for 4 copies? That would work well. If you wanted more, you'd simply select the last object copied and do CTRL + 9 on that.


Guy Fawkes(Posted 2012) [#59]
That would work! =D Ok, ALLs I need, is a way to add on a SMALL space to the mesh's width, for EACH mesh that is copied & position the newly created meshes at that location.






Thanks, Ross! :)


Ross C(Posted 2012) [#60]
Well, how do you reckon you will do this? Baring in mind keys 1 to 9 have scancodes numbers right next to each other.

This operation for multiple copies will need to occur in the same part of the code you are generating the copy, so that's a clue.

pseudo code (kind of)

So, the basic principle is:

Your checking to see if the Control has been pressed, if so,
Your checking to see if the numbers keys 1 to 9 have been pressed:
You will need a loop. Before you start your loop, you will need to set a variable to zero, to hold the number pressed if it is found. Call it "Number_of_copies"
You will need to set up a loop from 2 to 10 (this is the scancodes for keys 1 to 9) and check each using "If Keydown(loop) = true".
If/when you have found a keydown(loop) that matches, then assign the variable "Number_of_copies" to the value of the loop - 1
Next, after the loop is finished, check to see if "Number_of_copies" is greater than zero.
If it is, then set up another loop, going from 1 to "Number_of_copies"
Inside this loop you will do your normal copy code (moving, assigning, setting the entity type), exactly the way you are just now.
When it comes to moving the copy, like you are currently doing, you can use the value of the loop, to increase the offset more is it increases. EG moveentity mesh,0,0,(meshdepth(mesh)+3)*loop <<< Put your own reference for the mesh in here

This should get you the desired result. Just follow each step as you have done. If it helps, create a new function altogether, that way your not breaking the functionalty until it's finished.

Good luck.


Guy Fawkes(Posted 2012) [#61]
?.?


Ross C(Posted 2012) [#62]
?.?.?


Kippykip(Posted 2013) [#63]
This code was incredibly helpful for me learning multiple models/objects :D