Thanks for the replies guys.
@Czar Flavius - Ive read that doing the memcopy can really mess up the GC, especially if you have got objects within objects.
@TaskMaster, looks like your right... Azathoth CloneObject function doesnt like to copy the TSlotList field (I kept getting null pointers!? when trying to {Clone} it)...so here is what Ive come up with:
TBuildingInfo (notice the NoClone on the lists)
Type TBuildingInfo
Field name$ {Clone}
Field slots:TSlotList{NoClone}
Field buildingInfoList:TBuildingInfoList {NoClone}
Method clone:TBuildingInfo()
Local b:TBuildingInfo = TBuildingInfo (CloneObject(Self))
b.slots = New TSlotList
For Local s:TSlot = EachIn Self.slots
Local ss:TSlot = s.clone(slots)
b.slots.AddSlot(ss.x,ss.y)
Next
b.buildingInfoList = Self.buildingInfoList
Return b
End Method
End Type
And to create the clone:
Local buildings:TBuildingList = New TBuildingList ' create the global building list
Local b:TBuilding
b = buildings.AddNew(100,100, "HOUSE") ' create a new building and add it to the list
Local houseInfo:TbuildingInfo = infoList.Find("HOUSE") 'get the data for the building
b.info = houseinfo.clone() ' create a new copy of the data and assign it to the new building
b.info.name = "1st House" ' check to see if the clone has worked
Here is the full code:
SuperStrict
Graphics 800,600,0
Type TSlot
Field x%,y%
Field empty%
Field slotList:TSlotList
Method clone:TSlot(sl:TSlotList )
Local s:TSlot = New TSlot
s.x = x
s.y = y
s.empty = empty
s.slotList = sl
DebugLog s.x
Return s
End Method
End Type
Type TSlotList Extends TList
Method AddSlot:TSlot(x:Int, y:Int)
Local s:TSlot = New TSlot
s.x = x
s.y = y
s.empty = True
s.slotList = Self
AddLast(s)
Return s
End Method
Method findFreeSlot:TSlot()
For Local s:TSlot = EachIn Self
If s.empty Then Return s
Next
' reset slots if all are full
For Local s:TSlot = EachIn Self
s.empty = True
Next
Return Null
End Method
End Type
Type TBuildingInfo
Field name$ {Clone}
Field slots:TSlotList{NoClone}
Field buildingInfoList:TBuildingInfoList {NoClone}
Method clone:TBuildingInfo()
Local b:TBuildingInfo = TBuildingInfo (CloneObject(Self))
b.slots = New TSlotList
For Local s:TSlot = EachIn Self.slots
Local ss:TSlot = s.clone(slots)
b.slots.AddSlot(ss.x,ss.y)
Next
b.buildingInfoList = Self.buildingInfoList
Return b
End Method
End Type
Type TBuildingInfoList Extends TList
Method AddNew:TBuildingInfo(name:String)
Local b:TBuildingInfo = New TBuildingInfo
b.name = name
b.slots = New TSlotList
b.buildingInfoList = Self
AddLast(b)
Return b
End Method
Method Find:TBuildingInfo(name:String)
For Local i:TBuildingInfo = EachIn Self
If Upper(i.name) = Upper(name) Then Return i
Next
Return Null
End Method
End Type
Type TBuilding
Field x%,y%
Field h%,w%
Field info:TBuildingInfo
Field name$
Field buildings:TBuildingList 'points to list it's part of
Function Create:TBuilding(tx%, ty%,name$)
Local b:TBuilding = New TBuilding
b.x = tx
b.y = ty
b.h = 100
b.w = 100
b.name = name
b.info = New TBuildingInfo
b.info.slots = New TSlotList
Return b
End Function
End Type
Type TBuildingList Extends TList
Method AddNew:TBuilding(x%,y%,name$)
Local b:TBuilding = TBuilding.Create(x, y,name)
b.buildings = Self 'point to this list
AddLast(b)
Return b
End Method
Method Draw()
For Local b:TBuilding = EachIn Self
SetColor 255,255,255
DrawRect b.x,b.y,b.h,b.w
SetColor 255,0,0
DrawText b.name, b.x,b.y
DrawText b.info.name, b.x,b.y+10
For Local s:TSlot = EachIn b.info.slots
If s.empty SetColor 0,255,0 Else SetColor 255,0,0
DrawOval b.x+s.x , b.y+s.y , 10 , 10
Next
Next
SetColor 255,255,255
End Method
Method find:TBuilding(name$)
For Local b:TBuilding = EachIn Self
If Upper(b.name) = Upper(name) Return b
Next
Return Null
End Method
End Type
' set up objects
Local infoList:TBuildingInfoList = New TBuildingInfoList
Local info:TBuildingInfo = infoList.AddNew("HOUSE")
info.slots.AddSlot(-20,10)
info.slots.AddSlot(50,120)
info.slots.AddSlot(120,10)
info:TBuildingInfo = infoList.AddNew("BAR")
info.slots.AddSlot(-20,10)
info.slots.AddSlot(50,120)
info.slots.AddSlot(120,10)
Local buildings:TBuildingList = New TBuildingList
Local b:TBuilding
b = buildings.AddNew(100,100, "HOUSE")
Local houseInfo:TbuildingInfo = infoList.Find("HOUSE")
b.info = houseinfo.clone()
b.info.name = "1st House"
b = buildings.AddNew(300,300, "HOUSE")
b.info = houseinfo.clone()
b.info.name = "2nd House"
b = buildings.AddNew(500,100, "BAR")
Local barInfo:TbuildingInfo = infoList.Find("BAR")
b.info = barInfo.clone()
b.info.name = "The Bar"
Repeat
If MouseHit(1)
For Local b:TBuilding = EachIn buildings
If RectsOverlap(MouseX(),MouseY(),1,1,b.x,b.y,b.w,b.h)
Local freeSlot:TSlot = b.info.slots.findFreeSlot()
If freeSlot <> Null
freeSlot.empty = False
End If
EndIf
Next
End If
Cls
buildings.Draw()
Flip
Until KeyHit(KEY_ESCAPE)
Function RectsOverlap:Int(x0:Float, y0:Float, w0:Float, h0:Float, x2:Float, y2:Float, w2:Float, h2:Float)
If x0 > (x2 + w2) Or (x0 + w0) < x2 Then Return False
If y0 > (y2 + h2) Or (y0 + h0) < y2 Then Return False
Return True
End Function
' Clones an object and returns the clone. - by Azathoth
' Any fields that references an object only gets the reference copied unless MetaData contains {Clone}
' which then a copy is also made of the object referenced.
' {NoClone} prevents the field being copied.
Function CloneObject:Object(obj:Object)
Local cobj:Object
If obj=Null Then Return Null
Local objId:TTypeId=TTypeId.ForObject(obj)
If objId.ExtendsType(StringTypeId)
Return String(obj)
EndIf
If objId.ExtendsType(ArrayTypeId)
If objId.ArrayLength(obj)>0
cobj=objId.NewArray(objId.ArrayLength(obj))
If cobj
For Local i:Int = 0 Until objId.ArrayLength(obj)
If objId.ElementType().ExtendsType(ArrayTypeId) Or objId.ElementType().ExtendsType(StringTypeId) ..
Or objId.ElementType().ExtendsType(ObjectTypeId)
objId.SetArrayElement(cobj,i,CloneObject(objId.GetArrayElement(obj,i)))
Else
objId.SetArrayElement(cobj,i,objId.GetArrayElement(obj,i))
EndIf
Next
EndIf
EndIf
Return cobj
EndIf
cobj=New obj
For Local fld:TField=EachIn objId.EnumFields()
Local fldId:TTypeId=fld.TypeId()
If fld.Get(obj)<>Null And fld.MetaData("NoClone")=Null
DebugLog fld.name()+" "+fld.MetaData()+" " fld.get(obj)
If Not fld.MetaData("Clone")=Null
fld.Set(cobj,CloneObject(fld.Get(obj)))
Else
fld.Set(cobj,fld.Get(obj))
EndIf
EndIf
Next
Return cobj
EndFunction
@Brucey, thanks for the info - Ill have a look at your persistence module - sounds interesting...