Game Development Community

Cloning & Tinting does not work...

by Lateral Punk · in Torque X 2D · 03/14/2007 (12:03 am) · 4 replies

..on individual cloned objects. What I mean is that if I clone a template object N times, and change one of the cloned objects it's material (namely DefaultEffect.DefaultLight.InternalColor), then ALL objects will get that colour. This seems out of place since other things like PhysicsComponent, position, size, etc. are all copied, but it seems Material is referenced. I've read the other postings on tinting, but I am writing specifically wrt to tinting template cloned objects. I wanted to make sure that it wasn't something wrong with my applicaiton, so I even just created a fresh starter torque x project with the GG logo and tried it there. Spawned tow cloned logos, changed the colour on one of them, but both of them changed colour. Not cool!

I do think this is an issue with the Clone method on the Material and maybe even a bug (I know doing deep copies is usually a hard thing to do). If this is not a bug, then I would question the design of this as it defeats the purpose of cloning. Think about it in this way. Datablocks form TGE are used to group common stuff, and then the instantiated objects deals with the dynamic nature. I think that's the purpose of templates and objects but not in so many words.

#1
03/14/2007 (8:04 am)
Another thread in the closed beta forums has pointed this out, but at the time no official response has been made. There are ways to tint using straight XNA. I forget the exact post, but you can find info on it at the XNA forums over at MS.

www.mmogamedev.info/images/imgdc_ad1.gif
#2
03/14/2007 (8:32 am)
Thanks. I really don't want to be hitting XNA as that would just be a temp solution until TorqueX is fixed. I've found another solution that I'm testing that just might work. I will post once tested.
#3
03/14/2007 (9:04 am)
Ok so I've found a temporary solution that works. The idea for us that we didn't want to maintain N definitions of sprite objects (think: if we change the poly collision of 1, you have to do them for all of them!). Instead create N materials in the .txscene file whose main purpose will be would be so that it can store different colours. Here here is some code that you can append to starterkit to see it in action:

Game.cs
protected override void BeginRun()
        {
            base.BeginRun();

            // load our scene objects from XML.  TorqueX is designed to load game data from XML, but this is not strictly required;
            // anything in an XML file can also be created manually in C# code.  The SceneLoader is provided by TorqueGame and can be
            // used to load and unload XML files.
            SceneLoader.Load(@"data\levels\levelData.txscene");

            //clone the sprites like normally
            T2DStaticSprite ggClone1 = (T2DStaticSprite)(TorqueObjectDatabase.Instance.FindObject("garageT") as T2DStaticSprite).Clone();
            T2DStaticSprite ggClone2 = (T2DStaticSprite)(TorqueObjectDatabase.Instance.FindObject("garageT") as T2DStaticSprite).Clone();
            TorqueObjectDatabase.Instance.Register(ggClone1);
            TorqueObjectDatabase.Instance.Register(ggClone2);
            ggClone1.Position = new Vector2(-10, 0);
            ggClone2.Position = new Vector2(10, 0);

            //now clone (basiclaly new) the materials
            RenderMaterial ggMatClone1 = (RenderMaterial)(TorqueObjectDatabase.Instance.FindObject("GGLogoMaterial1") as RenderMaterial).Clone();
            RenderMaterial ggMatClone2 = (RenderMaterial)(TorqueObjectDatabase.Instance.FindObject("GGLogoMaterial2") as RenderMaterial).Clone();

            //change their colours (you can avoid this if you made the colours different inside the .txscene file itself)
            (ggMatClone1 as DefaultEffect).DefaultLight.InternalColor = new Vector3(0, 0, 1);
            (ggMatClone2 as DefaultEffect).DefaultLight.InternalColor = new Vector3(1, 1, 0);

            //change the materials of the sprites themselves, most important step
            ggClone1.Material = ggMatClone1;
            ggClone2.Material = ggMatClone2;

            //and it works..
            //basically you copy and paste the material def inside of the .txcene file and just clone the materials here so that
            //each sprite object has it's own copy.  Also it would be safe not to define a material for the sprite in the txscene, but
            //this is not necessary

        }
#4
03/14/2007 (9:04 am)
And the corresponding levelData.txscene file
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<!--Torque Game Builder - http://www.garagegames.com-->
<!--Type: Scene-->
<!--Target: TorqueX-->
<!--Version: 1-->
<!--Creator: Torque Game Builder-->
<TXNALevelData name="DefaultSceneGraph">
    <Version>1.0</Version>
    <SceneData>
        <T2DSceneGraph>
            <Name>DefaultSceneGraph</Name>
            <IsPersistent>true</IsPersistent>
            <T2DSceneContainer>
                <SceneGraph nameRef="DefaultSceneGraph" />
                <BinSize>20</BinSize>
                <BinCount>256</BinCount>
            </T2DSceneContainer>
        </T2DSceneGraph>
        <Camera2D>
            <CenterPosition>
                <X>0</X>
                <Y>0</Y>
            </CenterPosition>
            <Extent>
                <X>100</X>
                <Y>75</Y>
            </Extent>
            <ResizeToDisplayAspectRatioWithFixedWidth>true</ResizeToDisplayAspectRatioWithFixedWidth>
        </Camera2D>
    </SceneData>
    <Materials>
        <DefaultEffect name="GGLogoMaterial1">
            <BaseTex>data/images/GGLogo.png</BaseTex>
            <Translucent>true</Translucent>
            <DefaultLight>
                <Direction>
                    <X>0.577</X>
                    <Y>0.577</Y>
                    <Z>0.577</Z>
                </Direction>
                <Ambient>
                    <X>1.000000</X>
                    <Y>1.000000</Y>
                    <Z>0.996078</Z>
                </Ambient>
                <InternalColor>
                    <X>1</X>
                    <Y>1.000000</Y>
                    <Z>1</Z>
                </InternalColor>
            </DefaultLight>
            <SpecularPower>1</SpecularPower>
            <SpecularColor>
                <X>1</X>
                <Y>1</Y>
                <Z>1</Z>
                <W>1</W>
            </SpecularColor>
            <EnableLighting>false</EnableLighting>
            <EnableDefaultLighting>true</EnableDefaultLighting>
            <RefractiveAmount>1</RefractiveAmount>
            <Additive>false</Additive>
        </DefaultEffect>
		<DefaultEffect name="GGLogoMaterial2">
			<BaseTex>data/images/GGLogo.png</BaseTex>
			<Translucent>true</Translucent>
			<DefaultLight>
				<Direction>
					<X>0.577</X>
					<Y>0.577</Y>
					<Z>0.577</Z>
				</Direction>
				<Ambient>
					<X>1.000000</X>
					<Y>1.000000</Y>
					<Z>0.996078</Z>
				</Ambient>
				<InternalColor>
					<X>1</X>
					<Y>1.000000</Y>
					<Z>1</Z>
				</InternalColor>
			</DefaultLight>
			<SpecularPower>1</SpecularPower>
			<SpecularColor>
				<X>1</X>
				<Y>1</Y>
				<Z>1</Z>
				<W>1</W>
			</SpecularColor>
			<EnableLighting>false</EnableLighting>
			<EnableDefaultLighting>true</EnableDefaultLighting>
			<RefractiveAmount>1</RefractiveAmount>
			<Additive>false</Additive>
		</DefaultEffect>
	</Materials>
    <Objects>
        <T2DPhysicsMaterial>
            <Name>PhysicsMaterial0</Name>
            <Restitution>1</Restitution>
            <Friction>0.3</Friction>
            <Priority></Priority>
        </T2DPhysicsMaterial>
        <T2DPhysicsMaterial>
            <Name>PhysicsMaterial1</Name>
            <Restitution>1</Restitution>
            <Friction>0.3</Friction>
            <Priority>0.5</Priority>
        </T2DPhysicsMaterial>
        <StaticSprite name="garageT">
            <CreateWithPhysics>false</CreateWithPhysics>
            <CreateWithCollision>false</CreateWithCollision>
            <Components inPlace="true">
                <T2DCollisionComponent type="GarageGames.Torque.T2D.T2DCollisionComponent">
                    <Images>
                        <T2DPolyImage>
                            <CollisionPolyScale>
                                <X>1.000</X>
                                <Y>1.000</Y>
                            </CollisionPolyScale>
                            <CollisionPolyBasis>
                                <Vector2>
                                    <X>-1.000</X>
                                    <Y>-1.000</Y>
                                </Vector2>
                                <Vector2>
                                    <X>1.000</X>
                                    <Y>-1.000</Y>
                                </Vector2>
                                <Vector2>
                                    <X>1.000</X>
                                    <Y>1.000</Y>
                                </Vector2>
                                <Vector2>
                                    <X>-1.000</X>
                                    <Y>1.000</Y>
                                </Vector2>
                            </CollisionPolyBasis>
                        </T2DPolyImage>
                    </Images>
                    <RenderCollisionBounds>false</RenderCollisionBounds>
                </T2DCollisionComponent>
                <T2DPhysicsComponent type="GarageGames.Torque.T2D.T2DPhysicsComponent">
                    <PhysicsMaterial nameRef="PhysicsMaterial1" />
                    <Velocity>
                        <X>0.0</X>
                        <Y>0.0</Y>
                    </Velocity>
                    <AngularVelocity>0.0</AngularVelocity>
                    <InverseMass>1.0</InverseMass>
                    <RotationScale>1.0</RotationScale>
                    <SolveOverlap>false</SolveOverlap>
                    <ResolveCollision valueOf="GarageGames.Torque.T2D.T2DPhysicsComponent.BounceCollision" />
                </T2DPhysicsComponent>
                <MovementComponent type="StarterGame.MovementComponent">
                    <PlayerNumber>0</PlayerNumber>
                </MovementComponent>
            </Components>
            <ObjectType>
                <object objTypeRef="t2dSpriteType" />
            </ObjectType>
            <Pool>false</Pool>
            <PoolWithComponents>true</PoolWithComponents>
            <IsTemplate>true</IsTemplate>
            <IsPersistent>false</IsPersistent>
            <Layer>0</Layer>
            <Size>
                <X>10.000</X>
                <Y>10.000</Y>
            </Size>
            <Position>
                <X>0.000</X>
                <Y>-44.000</Y>
            </Position>
            <Rotation>0</Rotation>
            <CollisionsEnabled>true</CollisionsEnabled>
            <Visible>true</Visible>
            <VisibilityLevel>1</VisibilityLevel>
            <FlipX>false</FlipX>
            <FlipY>false</FlipY>
            <SortPoint>
                <X>0.000000</X>
                <Y>0.000000</Y>
            </SortPoint>
        </StaticSprite>
    </Objects>
</TXNALevelData>

Basically this is a ugly hack, but it gets things working with the beta. Hopefully this will be fixed in the future.