Restarted Assembly today could use some help

ok,

So I have a system, that is quite complex. I need help re-coding from scratch or simplifying commands.

1.“Component”
a piece that can be assembled with other pieces
Each component is a simple physics bound(cube sphere etc)
you can’t detect materials on anything except triangle mesh, however triangle mesh is not compoundable.
So, I spawn “Jack markers” aka Tmesh that are a triangle mesh object that copies each components location and rotation.


2. “DetectSocket”______________________________________

Raycast from component A(component to be parented) ,

if raycast from Component A and hits a Tmesh get Tmesh[‘Father’](the component associated with the TMESH),
if “MA_Jack” (a property named the same as the material of the jack)
if Father[hitMat]=False
(if the slot is empty)
continue

2.b- Center and mass_________
Calculate center of mass for component A + Father.childrenRecursive (component B and it’s children)
add “Fake Parent” at center of mass, assign mass of all objects to it, parent component A to it, and component B to it, and all of component B’s children.

3.“power and target passing”

Find root, do children recursive, pass “+power”(add power to items) or pass target if target!=“Empty”

Purpose-assembly of robotics in game


4.Unparent all,

unparent all and delete fake root

5.Unparent single
this is where I have issues, as there is no Parent/child hierarchy preserved when “Fake parent”

I could use the help of another coder,
and their patience

I started coding this as I just got into python, so it’s a mess.
all rights reserved at the moment. it’s not done
http://www.pasteall.org/blend/29784

I may just restart tonight…

Here is “simplified” restart.
Parenting Only

import bgefrom mathutils import Vector
from bge import render
scene=bge.logic.getCurrentScene()
def get_centroid_and_mass(objects):
    centroid = Vector()
    mass = 0.0
    for obj in objects:
        if 'Mass' in obj and obj.name!="Parent":
            mass += obj['Mass']
            print(mass,obj)    
    for obj in objects:
         if 'Mass' in obj and obj.name!="Parent":
            influence = obj['Mass'] / mass
            centroid += obj.worldPosition * influence
    return centroid, mass


def join_objects(obj,target):
    
    
    children = obj['target_objects']
    parent = scene.addObject('Parent', target,0)
    centroid, mass = get_centroid_and_mass(children)
    print(centroid, mass)
    parent.worldPosition = centroid
    parent.mass=mass
    
    obj['Root']=parent
    target['Root']=parent
    for objects in children:
        if objects.name!="Parent":
            objects.removeParent()
            objects.setParent(parent,1,0)
            
    if obj.name!="Parent":
        obj.setParent(parent, 1, 0)
    else:
        obj.applyMovement((0,0,-10),0) 








def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    scene=bge.logic.getCurrentScene()
    Mouse = cont.sensors['Mouse']
    Timer = cont.sensors['Property1']




    ##GetComponent A
    if Mouse.positive and Timer.positive:
        St = Vector ([0,1,0])
        Start = own.worldPosition+(own.worldOrientation * St)
        ##add= scene.addObject("HL",own,10)
        ##add.worldPosition=Start    
        St2 = Vector ([0,7.5,0])
        End = own.worldPosition+(own.worldOrientation * St2)
        ##add2= scene.addObject("HL",own,10)
        ##add2.worldPosition=End
        hitOb, hitPoint, hitNormal, hitPoly = own.rayCast(End, Start, 0, 'Tmesh', 0, 1, 1)
        render.drawLine(Start,End,(255,0,0))   
        H=hitOb
        print(H.name)
        if 'Tmesh' in H:
            if 'Component' in H:
                target=H['Component']
                print(target.name)
                own['PtargetA']=target
                
                
                
        ##GetComponent B
        t = Vector ([0,1.5,0])
        Start2 = target.worldPosition+(target.worldOrientation * St)
        ##add= scene.addObject("HL",own,10)
        ##add.worldPosition=Start    
        St2 = Vector ([0,7.5,0])
        End2 = hitOb.worldPosition+(hitOb.worldOrientation * St2)
        hitOb2, hitPoint2, hitNormal2, hitPoly2 = hitOb.rayCast(End2, Start2, 0, 'Tmesh', 0, 1, 1)
        render.drawLine(Start,hitPoint2,(0,0,255))
        if 'Tmesh' in hitOb2:
            H2=hitOb2
            Component_b=H2['Component']
            own['PTargetB']=Component_b
        
        
        ## Get jack and check if occupied
        if hitPoly:
            hitMat = hitPoly.material_name
    
            own['HitMat']=hitMat
            if 'Jack_' in hitMat:
                print(hitMat)    
                if Component_b[hitMat]==False:
                    print("Jack is empty")
                    Component_b[hitMat]=True
                    hitObPos=Component_b.worldPosition
                    spot=hitObPos+hitNormal
                    target.worldPosition=spot
                    hOffset = Vector([0,-1    ,0])
                    target.worldPosition += target.worldOrientation * hOffset
                    list=Component_b.childrenRecursive
                    list=list+[target]
                    list=list+[Component_b]
                    Component_b['target_objects']=list
                    target['Parent']=Component_b
                    join_objects(Component_b,target)
                    
main()



now that I actually can code, I rewrote that in about a hour…

now, how do I store a list, of the assembly hierarchy ?

I think own[‘Parent’]

should work for unparenting…

Attachments

parenting.blend (517 KB)

Your game becoming unworkable due to complexity may be the fault of excessively long scripts, unorganized code that isn’t sectioned into blocks based on the prevailing game mechanics (using comments to separate sections), badly done variable/dictionary/list/script names (your code example above has a list names ‘list’, not good practice at all if you want to be able to use the search function to easily find code that works with a certain thing, and using convoluted acronyms or abbreviations should be out of the question as well).

Simply put, the first part can be done by breaking extremely long scripts into a small family of them and tying them together with a few more logic bricks. The others can be resolved in the way they sound, give clear and concise names to functions, lists, and variables. Section off scripts so that code dealing with components are not mixed in with the initial initiation code, those sort of things.

This is something the BGE cannot do for you, in fact no engine can organize logic in the way that can be done by a human developer, this is something you will have to do yourself.

Well, I have it working now,

and “independent”

I can rename “list” but the rest of the naming is so I understand it.

my next task is to unparent a component, and if it has “psudo children” join_objects(component) and join_objects(remaining components)

then it’s solved

targetPassing is my next re-write, after that, and then that is all that has been bugging me :smiley:

You need to explain further what this is attempting to achieve, rather than how it currently works, and what you would like it to do:

You have mentioned a component, but not what it is - how should components talk to one another (do they provide data, or just need to tell the other components that they exist).

Here’s a template that should be of some use. It allows physical “components” to snap with one another, (it performs a raycast along all 6 axis directions).

Components can send messages to adjacent components, or to the entire “group”. ComponentParents will recalculate their centre of mass (origin) and mass according to added or removed children.

Components have an update function, and the manager runs this, alongside a scheduler. The update method is just a use case of having a scheduler, it’s the first priority - so update() is called then any additional scheduling you choose to implement on top of that.

[ATTACH]314930[/ATTACH]

I have
Parenting= assemble compound object and get center of mass, add a object at center of mass and parent items to it.

I need
unparent= break apart compound object, and take children with broken off piece

using the properties bestowed on items in “parent”

recaluculate center of mass for (removed component+psudo children) and (remaining components)

Ok, I found a few lines that were off



import bge
from mathutils import Vector
from bge import render
scene=bge.logic.getCurrentScene()
def get_centroid_and_mass(objects):
    centroid = Vector()
    mass = 0.0
    for obj in objects:
        if 'Mass' in obj and obj.name!="Parent":
            mass += obj['Mass']
            print(mass,obj)    
    for obj in objects:
         if 'Mass' in obj and obj.name!="Parent":
            influence = obj['Mass'] / mass
            centroid += obj.worldPosition * influence
    return centroid, mass


def join_objects(obj,target):
    
    
    children = obj['target_objects']
    parent = scene.addObject('Parent', target,0)
    centroid, mass = get_centroid_and_mass(children)
    print(centroid, mass)
    parent.worldPosition = centroid
    parent.mass=mass
    
    obj['Root']=parent
    target['Root']=parent
    for objects in children:
        if objects.name!="Parent":
            objects.removeParent()
            objects.setParent(parent,1,0)
            
    if obj.name!="Parent":
        obj.setParent(parent, 1, 0)
    else:
        obj.applyMovement((0,0,-10),0) 
        obj.endObject()






def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    scene=bge.logic.getCurrentScene()
    Mouse = cont.sensors['Mouse']
    Timer = cont.sensors['Property1']




    ##GetComponent A
    if Mouse.positive and Timer.positive:
        St = Vector ([0,1,0])
        Start = own.worldPosition+(own.worldOrientation * St)
        ##add= scene.addObject("HL",own,10)
        ##add.worldPosition=Start    
        St2 = Vector ([0,7.5,0])
        End = own.worldPosition+(own.worldOrientation * St2)
        ##add2= scene.addObject("HL",own,10)
        ##add2.worldPosition=End
        hitOb, hitPoint, hitNormal, hitPoly = own.rayCast(End, Start, 0, 'Tmesh', 0, 1, 1)
        render.drawLine(Start,End,(255,0,0))   
        H=hitOb
        print(H.name)
        if 'Tmesh' in H:
            if 'Component' in H:
                target=H['Component']
                print(target.name)
                own['PtargetA']=target
                
                
                
        ##GetComponent B
        t = Vector ([0,1.5,0])
        Start2 = target.worldPosition+(target.worldOrientation * St)
        ##add= scene.addObject("HL",own,10)
        ##add.worldPosition=Start    
        St2 = Vector ([0,7.5,0])
        End2 = hitOb.worldPosition+(hitOb.worldOrientation * St2)
        hitOb2, hitPoint2, hitNormal2, hitPoly2 = hitOb.rayCast(End2, Start2, 0, 'Tmesh', 0, 1, 1)
        render.drawLine(Start,hitPoint2,(0,0,255))
        if 'Tmesh' in hitOb2:
            H2=hitOb2
            Component_b=H2['Component']
            own['PTargetB']=Component_b
        
        
        ## Get jack and check if occupied
        if hitPoly:
            hitMat = hitPoly.material_name
    
            own['HitMat']=hitMat
            if 'Jack_' in hitMat:
                print(hitMat)    
                if Component_b[hitMat]==False:
                    print("Jack is empty")
                    Component_b[hitMat]=True
                    hitObPos=Component_b.worldPosition
                    spot=hitObPos+hitNormal
                    target.worldPosition=spot
                    hOffset = Vector([0,-1    ,0])
                    target.worldPosition += target.worldOrientation * hOffset
                    if Component_b['Root']!="Empty":
                        Component_b=Component_b['Root']
                    list=Component_b.childrenRecursive
                    list=list+[target]
                    list=list+[Component_b]
                    Component_b['target_objects']=list
                    target['Parent']=Component_b
                    join_objects(Component_b,target)
                    
main()



I fixed some things however, line 39 crashes the game engine,
I have removed all children, and I don’t understand…

Step 1 -Parent
Part 1 + Part 2 = working

Step 2-
Parent Parts 1 + Part 2 + Part 3

works but adds a extra “Parent” to the scene(old parent)

even though nothing is parented to “extra parent” ending it kills game engine…

with line 39

without line 39(uploading)

Bump - Found bug?

I thought it may be a feature of children,

but I tried

print(obj.children) instead of

obj.endObject()

I got

[]

Where I am

Assemble components - set location of center of mass and set mass.

what I need,
Break assembly at component(via raycast)
split into 2 assemblies

if the assemblies contain more then 1 object, calculate center of gravity,
and assign mass of assembly.

look over my code?

check the .blend?

Attachments

CompoundParentingV3.blend (521 KB)

Found the bug,

I had a property that was subscribed to the old parent…

EndObject=Kill game

Now all that is left if break in pieces based on hierarchy.

Edit:False Alarm… No idea why it crashes.

this works for parenting, and saves the game object.name of the psudo-parent as object[‘Parent’]

So now using the information stored in


root=object['Root']
for items in root.children:
    ???items['Parent']?????
 

to make 2 lists,

“Snapped off” and “original”

for breaking component assemblies in game.

if I can generate the two lists I can do the rest…

Attachments

CompoundParentingV3_1.blend (521 KB)

actually most of complexity is given by a hugly syntax ,
and surely not a good know of how work local variable.
the local variable (except some exception as cont, owner)
should have a brief life, for a little piece of code

plus, you can overrite a local variable already used before,
so, is not the case of call hitOb1, hitOb2, hitOb3 …

this is how you can write the same piece of code , step by step


original code


    ##GetComponent A
    if Mouse.positive and Timer.positive:
        St = Vector ([0,1,0])
        Start = own.worldPosition+(own.worldOrientation * St)
        ##add= scene.addObject("HL",own,10)
        ##add.worldPosition=Start    
        St2 = Vector ([0,7.5,0])
        End = own.worldPosition+(own.worldOrientation * St2)
        ##add2= scene.addObject("HL",own,10)
        ##add2.worldPosition=End
        hitOb, hitPoint, hitNormal, hitPoly = own.rayCast(End, Start, 0, 'Tmesh', 0, 1, 1)
        render.drawLine(Start,End,(255,0,0))   
        H=hitOb
        print(H.name)
        if 'Tmesh' in H:
            if 'Component' in H:
                target=H['Component']
                print(target.name)
                own['PtargetA']=target
                








part 1 , clean trash lines (print and lines broken)


    ##GetComponent A
    if Mouse.positive and Timer.positive:
        St = Vector ([0,1,0])
        Start = own.worldPosition+(own.worldOrientation * St)




        St2 = Vector ([0,7.5,0])
        End = own.worldPosition+(own.worldOrientation * St2)


        hitOb, hitPoint, hitNormal, hitPoly = own.rayCast(End, Start, 0, 'Tmesh', 0, 1, 1)
        render.drawLine(Start,End,(255,0,0))   
        H=hitOb


        if 'Tmesh' in H:
            if 'Component' in H:
                target=H['Component']


                own['PtargetA']=target














part 2 , remotion of local variable useless


    ##GetComponent A
    if Mouse.positive and Timer.positive:
        Start = own.worldPosition+(own.worldOrientation * Vector ([0,1,0]))






        End = own.worldPosition+(own.worldOrientation * Vector ([0,7.5,0]))


        hitOb, hitPoint, hitNormal, hitPoly = own.rayCast(End, Start, 0, 'Tmesh', 0, 1, 1)
        render.drawLine(Start,End,(255,0,0))   


        if 'Tmesh' in hitOb:
            if 'Component' in hitOb:


                own['PtargetA']=hitOb['Component']








part 3 , simmetrization and change of some name


    ##GetComponent A
    if Mouse.positive and Timer.positive:
        p1 = own.worldPosition + (own.worldOrientation * Vector ([0,  1, 0]))
        p2 = own.worldPosition + (own.worldOrientation * Vector ([0,  7. 5,0]))


        hitOb, hitPoint, hitNormal, hitPoly = own.rayCast(End, Start, 0, 'Tmesh', 0, 1, 1)
        render.drawLine(Start, End, (255, 0, 0))   


        if 'Tmesh' in hitOb:
            if 'Component' in hitOb:
                own['PtargetA'] = hitOb['Component']








part 4 , condensation 


    ##GetComponent A
    if Mouse.positive and Timer.positive:
        p1 = own.worldPosition + (own.worldOrientation * Vector([0,  1,   0]))
        p2 = own.worldPosition + (own.worldOrientation * Vector([0,  7.5, 0]))


        render.drawLine(p1, p2, (255, 0, 0)) 


        hitOb = own.rayCast(p2, p1, 0, 'Tmesh', 0, 1, 1)[0]
        if 'Tmesh' in hitOb and 'Component' in hitOb:
            own['PtargetA'] = hitOb['Component']

is not more simple?
but the code do the same things

That does look better,

Right now I am knee deep in a bug,

care to help me sort it out?

Remove parent on compound objects seems to crash the game engine?
can you confirm?

click 1 time(Join first set)

click 2nd time (join all three)

right click(unparent)=blender crash

I guess I can unparent all, and re parent?


import bge




def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner


    Ray = cont.sensors['Ray']
    MouseR = cont.sensors['Mouse1']


    if Ray.positive and MouseR.positive:
        target=Ray.hitObject
        own['RParentTarget']=target
        Comp=target['Component']
        P1=Comp['Parent']
        P1[Comp['hitMat']]=False
        Comp.removeParent()
        
main()



Edit:I made a new.blend and I can’t reproduce… just with

delay----------python(compound parent)

space bar------python(Remove parent)

Attachments

CompoundParentingV3_1 (1).blend (528 KB)

yes , crash also to me, removing the coupond seem that not happen

here is where I am right now,

“Unparent”


import bge
from mathutils import Vector
scene=bge.logic.getCurrentScene()


def get_centroid_and_mass(objects):
    centroid = Vector()
    mass = 0.0
    for obj in objects:
        if 'Mass' in obj and obj.name!="Parent":
            mass += obj['Mass']
            print(mass,obj)    
    for obj in objects:
         if 'Mass' in obj and obj.name!="Parent":
            influence = obj['Mass'] / mass
            centroid += obj.worldPosition * influence
    return centroid, mass


def join_objects(obj):
    
    
    children = obj['target_objects']
    parent = scene.addObject('Parent', obj,0)
    centroid, mass = get_centroid_and_mass(children)
    print(centroid, mass)
    parent.worldPosition = centroid
    parent.mass=mass
    
    
    
   
    
    
    for objects in children:
        if objects.name!="Parent":
            objects.removeParent()
            objects.setParent(parent,1,0)
            
    if obj.name!="Parent":
        obj.setParent(parent, 1, 0)
    else:
        obj.applyMovement((0,0,-100),0) 


def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    
    Ray = cont.sensors['Ray']
    MouseR = cont.sensors['Mouse1']


    if Ray.positive and MouseR.positive:
        target=Ray.hitObject
        own['RParentTarget']=target
        Comp=target['Component']
        Root=Comp['Root']
        list1=Root.children
        P1=Comp['Parent']
        P1[Comp['hitMat']]=False
        Comp['target_objects']=Comp.children
        list2=Comp.children
        Root['target_objects']=list1
        x=0
        index=0
           
        if Comp in list1: list1=list1-Comp
        for items in Comp.children:
            if items in list1: list1=list1-items
        
        if len(list2)>1:
            join_objects(Comp)
            
        else:
            Comp.removeParent()
        join_objects(Root)
          
main()



however I don’t understand how to remove a item from a list using bge python…

list1= “Remnant list”

list2=“Break off list”

Based on the code snippets you posted, I think your code needs major refactoring:

  • Before anybody can help you properly, they need to be able to read your code so first and foremost, I would start by following the PEP-8 guidelines.
    [LIST=1]
  • Compare this:
    [LIST=1]
target=Ray.hitObject
own['RParentTarget']=target
Comp=target['Component']
P1=Comp['Parent']
P1[Comp['hitMat']]=False
Comp.removeParent()
  • To this:

target = Ray.hitObject
own['RParentTarget'] = target
Comp = target['Component']
P1 = Comp['Parent']
P1[Comp['hitMat']] = False
Comp.removeParent()

[/LIST]

  • I would suggest using an object-oriented model - I’m guessing you’re not since I see no classes defined anywhere.

  • When people start programming, they start creating functions to operate on an object passed to the function (aka an argument). Soon they have a bunch of functions. Then they start this process over on another object or multiple objects, functions calling other functions, and before you know it, the code is all over the place.

  • Of course, this is not something you learn overnight but from experience.

  • To start, think of data, and then properties (attributes) and functions associated with that data.
    [LIST=1]

  • For example, you have a list and you want to add an object to that list. What do you do? You call a method of the list object:
    [LIST=1]

listObject.append(newItem)

[/LIST]

[/LIST]

[/LIST]

Also people can assist you better if you mention specific parts and describe the context for us, rather than present the entire system and hope we’ll understand it all. And if you are having a hard time narrowing your question, this might because be parts of your problem are scattered and hard to find which indicates your code needs refactoring.

There are various ways to do this. You can do list.pop(index) to remove a single item. You can splice the list. However, removing items from lists are inefficient, deques are better…

Tutorials on lists:
http://www.tutorialspoint.com/python/python_lists.htm
http://www.diveintopython.net/native_data_types/lists.html

Python API:
https://docs.python.org/3.4/tutorial/datastructures.html

Python video tutorial series: https://www.youtube.com/watch?v=iGQv7bR6zCQ&list=PLDFB7FFF90EE6F0C1

ok I just needed


list1=[]
for items in Root.children:
    if items!=Comp:
        list=list+[items]



the list is what I want, however I am getting behavior I don’t understand.

Attachments

CompoundParentingV3_1 (23b).blend (536 KB)

Do you all understand what I am doing?

this is for physical assemblies,

adding objects,

and removing them, and keeping a accurate center of gravity and mass.

it works, however there are some bugs…

0 views.

I can reformat the code, or even rewrite it from scratch however, this bug, was why I rewrote it today.

and it’s back in a new file…

been reading about code refactor for

RemoveCompoundChild()

Attachments

CompoundParentingDebug.blend (537 KB)

got it!

this works to remove any single item in the assembly,

now I need to maintain a hierarchy somehow to build “list1” the removed list

Unparent


import bge
from mathutils import Vector
scene=bge.logic.getCurrentScene()




##get center of mass
def get_centroid_and_mass(objects):
    centroid = Vector()
    mass = 0.0
    for obj in objects:
        if 'Mass' in obj and obj.name!="Parent":
            mass += obj['Mass']
            print(mass,obj)    
    for obj in objects:
         if 'Mass' in obj and obj.name!="Parent":
            influence = obj['Mass'] / mass
            centroid += obj.worldPosition * influence
    return centroid, mass
##Parent objects to "fake center"
def join_objects(obj):
    
    
    children = obj['target_objects']
    ##Add fake root
    parent = scene.addObject('Parent', obj, 0)
    ##get new center of mass and mass
    centroid, mass = get_centroid_and_mass(children)
    
    print(centroid, mass)
    ##Move Fake root to center of mass
    parent.worldPosition = centroid
    
    parent.mass = mass
    ## trying to ditch extra fake centers as ending them crashes blender
    for objects in children:
        if objects.name != "Parent":
            
            objects.setParent( parent , 1 ,  0)
        else:
            obj.applyMovement(( 0, 0, -100), 0)    
    ## trying to ditch extra fake centers as ending them crashes blender        
    if 'Parent' not in obj.name:
        obj.setParent( parent,  1,  0)
    else:
        
        obj.applyMovement((0, 0, -100), 0) 


def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    
    Ray = cont.sensors[ 'Ray' ]
    MouseR = cont.sensors[ 'Mouse1']
    
    
    ##selection of target of unparent logic
    if Ray.positive and MouseR.positive and own[ 'Parenttimer' ] == 0:
        target=Ray.hitObject
        ## Tmesh object
        own['RParentTarget'] = target
        ## component assosiated with Tmesh flag
        Comp=target['Component']
        ## root assosiated with component
        if Comp['Root']=="Empty":
            
            Root=Comp['Root']
        else:
            Root=Comp
        list2=[]
        for items in Comp.children:
            
            list2 += [items]        
        list1=[]
        for items in Root.children:
            if items != Comp:
                
                list1 = list1+[items]
        
        P1=Comp['Parent']
        P1[Comp['hitMat']] = False
        
        
        
        Root['target_objects'] = list1
        Comp['target_objects'] = list2
        print(list1)
        print(list2)
        print(len(list2))
        
        for items in Root.childrenRecursive:
            items.removeParent()
        
        if 'COM' in Root:
            Root.endObject()
              
        Comp.removeParent()
        Comp.reinstancePhysicsMesh()
        Comp.applyMovement((0,-1,.5),1)
        if len(list1)>1:  
            join_objects(Root)
        else:
            if 'COM' in Root:
                Root.endObject()
                    
        ##for items in scene.objects:
        ##    print(items.name)
                
          
main()



Parent


import bge
from mathutils import Vector
from bge import render
scene=bge.logic.getCurrentScene()
def get_centroid_and_mass(objects):
    centroid = Vector()
    mass = 0.0
    for obj in objects:
        if 'Mass' in obj and obj.name!="Parent":
            mass += obj['Mass']
            print(mass,obj)    
    for obj in objects:
         if 'Mass' in obj and obj.name!="Parent":
            influence = obj['Mass'] / mass
            centroid += obj.worldPosition * influence
    return centroid, mass


def join_objects(obj,target):
    
    
    children = obj['target_objects']
    parent = scene.addObject('Parent', target,0)
    centroid, mass = get_centroid_and_mass(children)
    print(centroid, mass)
    parent.worldPosition = centroid
    parent.mass=mass
    
    obj['Root']=parent
    obj['RootName']=parent.name
    target['Root']=parent
    target['RootName']=parent.name
    P2=target['Parent']
    
    target.setParent(parent,1,0)
    for objects in children:
        if objects.name!="Parent" and objects.name!=target:
            objects.removeParent()
            objects.setParent(parent,1,0)
            objects['Root']=parent
            objects['RootName']=parent.name
    if obj.name!="Parent":
        obj.setParent(parent, 1, 0)
    else:
        obj.applyMovement((0,0,-100),0) 
        ##obj.endObject()






def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    scene=bge.logic.getCurrentScene()
    Mouse = cont.sensors['Mouse']
    Timer = cont.sensors['Property1']




    ##GetComponent A
    if Mouse.positive and Timer.positive:
        St = Vector ([0,1,0])
        Start = own.worldPosition+(own.worldOrientation * St)
        ##add= scene.addObject("HL",own,10)
        ##add.worldPosition=Start    
        St2 = Vector ([0,7.5,0])
        End = own.worldPosition+(own.worldOrientation * St2)
        ##add2= scene.addObject("HL",own,10)
        ##add2.worldPosition=End
        hitOb, hitPoint, hitNormal, hitPoly = own.rayCast(End, Start, 0, 'Tmesh', 0, 1, 1)
        render.drawLine(Start,End,(255,0,0))   
        H=hitOb
        print(H.name)
        if 'Tmesh' in H:
            if 'Component' in H:
                target=H['Component']
                print(target.name)
                own['PtargetA']=target
                
                
                
        ##GetComponent B
        t = Vector ([0,1.5,0])
        Start2 = target.worldPosition+(target.worldOrientation * St)
        ##add= scene.addObject("HL",own,10)
        ##add.worldPosition=Start    
        St2 = Vector ([0,7.5,0])
        End2 = hitOb.worldPosition+(hitOb.worldOrientation * St2)
        hitOb2, hitPoint2, hitNormal2, hitPoly2 = hitOb.rayCast(End2, Start2, 0, 'Tmesh', 0, 1, 1)
        render.drawLine(Start2,End2,(0,0,255))
        if 'Tmesh' in hitOb2:
            H2=hitOb2
            Component_b=H2['Component']
            own['PTargetB']=Component_b
        
        
        ## Get jack and check if occupied
        if hitPoly:
            hitMat = hitPoly.material_name
    
            own['HitMat']=hitMat
            if 'Jack_' in hitMat:
                print(hitMat)    
                if Component_b[hitMat]==False:
                    target['hitMat']=hitMat
                    target['Parent']=Component_b
                    target['ParentName']=Component_b.name
                    print("Jack is empty")
                    Component_b[hitMat]=True
                    hitObPos=Component_b.worldPosition
                    spot=hitObPos+hitNormal2
                    target.alignAxisToVect(-hitNormal2, 1, 1)
                    
                    target.worldPosition=spot
                    hOffset = Vector([0,-1    ,0])
                    target.worldPosition += target.worldOrientation * hOffset
                    if Component_b['Root']!="Empty":
                        Component_b=Component_b['Root']
                    list=Component_b.childrenRecursive
                    list=list+[target]
                    list=list+[Component_b]
                    Component_b['target_objects']=list
                    
                    join_objects(Component_b,target)
                    
main()