Duplicate Objects in Script
by Brett Fattori · 10/19/2004 (6:55 pm) · 8 comments
SimObject allows you to clone itself, but only if the classes of the two objects match. This small functional update will allow you to clone one object into another, regardless of class.
MAKE SURE YOU BACK YOUR CODE UP!
In console/simBase.cc add the following right after the ConsoleMethod dump():
Now, from within script, you can make a copy of an object like so:
When the script runs, you will be left with an exact duplicate of the barObj, but it is an entirely new object referred to as %fooObj. What's more, if you added it to the MissionGroup simGroup, with:
Enjoy!
- Brett
MAKE SURE YOU BACK YOUR CODE UP!
In console/simBase.cc add the following right after the ConsoleMethod dump():
// BF :: Copy all fields from an object and write to a
// stream for passing to script
ConsoleMethod(SimObject,getAllFields, const char*, 2, 2, "obj.getAllFields()")
{
argc; argv;
U8 streamBuf[2048];
MemStream stream(2048, streamBuf, false, true);
object->writeFields(stream, 1);
// Dump stream to script return buf
char *retBuf = (char *)streamBuf;
U32 returnLeng = stream.getPosition();
retBuf[returnLeng] = '[[6288b07b40cae]]';
return (const char *)retBuf;
}Now, from within script, you can make a copy of an object like so:
// Create the object string
%fooObj = "new " @ %barObj.getClassName() @ "(foo) {" @ %barObj.getAllFields() @ "};";
// Build the object
%fooObj = "%fooObj = " @ %fooObj;
eval( %fooObj );When the script runs, you will be left with an exact duplicate of the barObj, but it is an entirely new object referred to as %fooObj. What's more, if you added it to the MissionGroup simGroup, with:
%missionGrp = nameToId("MissionGroup");
%missionGrp.add(%fooObj);You could then look it up as:%fooObj = nameToId("MissionGroup/foo");Enjoy!
- Brett
About the author
Recent Blogs
• A small hello• Recent Stuph
• So long and so out of touch...
• Plan for Brett Fattori
• Plan for Brett Fattori
#2
10/19/2004 (10:55 pm)
Marcelo's approach is probably a bit more portable - very cool to see two different ways of doing the same thing, though.
#3
I guess sometimes it takes someone raising their hand and speaking up for others to speak up too. Way to rain on my parade Marcelo! ;-)
- Brett
EDIT: My approach allows for someone to duplicate an object that has no similarities. Thus you could copy all of the fields from a player object into an item object. Or, as I'm using it, from ScriptObject's into an actual instance of another object. Maybe a blending of the two approaches would be best.
10/20/2004 (5:09 am)
Sure thing... That's the benefit of the community. Just surprised this never showed up before now.I guess sometimes it takes someone raising their hand and speaking up for others to speak up too. Way to rain on my parade Marcelo! ;-)
- Brett
EDIT: My approach allows for someone to duplicate an object that has no similarities. Thus you could copy all of the fields from a player object into an item object. Or, as I'm using it, from ScriptObject's into an actual instance of another object. Maybe a blending of the two approaches would be best.
#4
Maybe you can make SimObject::assignFieldsFrom acessible by script, this way you can copy the fields without using the language parser.
10/20/2004 (6:33 am)
Hehe, I have so many modifications in the engine that I don't have time to post resources of it. :)Maybe you can make SimObject::assignFieldsFrom acessible by script, this way you can copy the fields without using the language parser.
#5
- Brett
10/20/2004 (9:25 am)
I thought of using that assignFieldsFrom, but it meant that I couldn't duplicate an object unless it was the same class of object. With the method above, I can have a collection of ScriptObjects and then copy all their fields into Markers in the mission group. Thus there's no limitation on similarity in classes. It was just a design decision.- Brett
#6
Thank you for posting this, my eyes were bleeding trying to get some values into an Item from script without using "datablocks".
you might mention that this needs to be added at the top of simBase.cc:
also, if you want to copy a simobject to an Item, you will need to create a datablock and use this:
08/17/2005 (1:28 am)
brett:Thank you for posting this, my eyes were bleeding trying to get some values into an Item from script without using "datablocks".
you might mention that this needs to be added at the top of simBase.cc:
#include "core/memstream.h"
also, if you want to copy a simobject to an Item, you will need to create a datablock and use this:
datablock itemdata(simObjData){
category = "yourCategory";
};
%itemObj = "new Item(){datablock = simObjData;"@%simObj.getAllFields()@"\n};";
#7
09/06/2005 (8:41 am)
I used Marcelo's approach, and it compiled and ran well. However, when I try to duplicate an InteriorInstance, the duplicated interior does appear in the world, but it is all black. I'm guessing it needs to be relighted or something, but that would be expensive. Is there a way that the duplicated instance can share the lightmap from the object which it was copied from?
#8
I've tried to implement both suggestions, but get this error when the camera is moved in the direction of copied object:
Fatal:(c:\torquw\sdk\engine\interior\interior.cc @ 2078) Bad texture handle in rebuildVertexColors
Does anyone know how to fix this?
Thanks in advance :)
/Immdtu
11/18/2005 (6:53 am)
Hi,I've tried to implement both suggestions, but get this error when the camera is moved in the direction of copied object:
Fatal:(c:\torquw\sdk\engine\interior\interior.cc @ 2078) Bad texture handle in rebuildVertexColors
Does anyone know how to fix this?
Thanks in advance :)
/Immdtu

Torque Owner Marcelo Oliveira
Add to simBase.cc
SimObject* SimObject::duplicate(SimGroup *parentGroup) { ConsoleObject *obj = ConsoleObject::create(this->getClassName()); SimObject *newObject = dynamic_cast<SimObject *>(obj); if (!newObject) return NULL; newObject->assignFieldsFrom(this); newObject->setModStaticFields(true); newObject->setModDynamicFields(true); if (newObject->isProperlyAdded() == false && !newObject->registerObject()) { delete newObject; return NULL; } const char *name = getName(); if(name && name[0] && getClassRep()) { Namespace *parent = getClassRep()->getNameSpace(); if(Con::linkNamespaces(parent->mName, name)) newObject->mNameSpace = Con::lookupNamespace(name); } if (!parentGroup) parentGroup = this->getGroup(); parentGroup->addObject(newObject); return newObject; } ConsoleMethod(SimObject, duplicate, S32, 2, 2, "obj.duplicate()") { argc; argv; SimObject *newObj = object->duplicate(); if (newObj) return newObj->getId(); return -1; } SimObject* SimSet::duplicate(SimGroup *parentGroup) { SimSet *newObject = dynamic_cast<SimSet*>(Parent::duplicate(parentGroup)); if (!newObject) return NULL; // Duplicate childs for(U32 i = 0; i < size(); i++) (*this)[i]->duplicate((SimGroup*)newObject); return (SimObject*)newObject; }Insert at simBase.h
Then in the script:
It's a recursive function, so SimSets and SimGroups can be duplicated too (all the object inside it also), it works by creating a new object from the same class, copying all the fields (static and dynamic), linking the namespace and adding to the same parent group.