Add CreateParticleAtBone script function

rope
Armin Burgmeier 2012-12-28 23:49:35 +01:00
parent 84c43f9a1d
commit c3c148d53a
3 changed files with 201 additions and 5 deletions

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>CreateParticleAtBone</title>
<category>Particle</category>
<version>5.4 OC</version>
<syntax>
<rtype>bool</rtype>
<params>
<param>
<type>string</type>
<name>szName</name>
<desc>Name of the particle</desc>
</param>
<param>
<type>string</type>
<name>szBoneName</name>
<desc>Name of the bone at which to create the particle</desc>
</param>
<param>
<type>array</type>
<name>pos</name>
<desc>Vector of three elements with the X,Y and Z coordinates of the particle relative to the bone position and orientation.</desc>
</param>
<param>
<type>array</type>
<name>dir</name>
<desc>Vector of three elements with the X,Y and Z components of the velocity of theparticle relative to the bone orientation.</desc>
</param>
<param>
<type>int</type>
<name>a</name>
<desc>Extra parameter. This is usually the size of the particle in 1/5 pixels.</desc>
</param>
<param>
<type>int</type>
<name>b</name>
<desc>Extra parameter. This is usually the color modulation of the particle.</desc>
</param>
<param>
<type>object</type>
<name>target</name>
<desc>Target object for object local particles. Object local particles are drawn directly on top of the object and are removed when the object is deleted.</desc>
<optional />
</param>
<param>
<type>bool</type>
<name>behind_target</name>
<desc>If specified and not <code>false</code>, the particle is drawn directly behind the target object.</desc>
<optional />
</param>
</params>
</syntax>
<desc>Creates a particle relative to a bone of the calling object's skeleton. The named particle definition must be loaded. For more information see the particle documentation.</desc>
<remark>This function returns <code>false</code> if the particle definition was not found, or the function is called for an object which does not have a mesh graphics, or the skeleton of the mesh does not have a bone called <code>szBoneName</code>. Otherwise, <code>true</code> is returned. There is no return value indicating whether the particle has actually been created. This must be so to prevent synchronization problems in network games, as particles may be handled differently on each computer in the network.</remark>
<examples>
<example>
<code>func InitializePlayer(int plr)
{
AddEffect("IntColorize", 0, 1, 1);
}
global func FxIntColorizeTimer()
{
FindObject(Find_ID(Clonk))->CreateParticleAtBone("PSpark", "skeleton_body", [0, 0, 0], [0, 0, 0], 8, RGB(255,0,0));
FindObject(Find_ID(Clonk))->CreateParticleAtBone("PSpark", "pos_hand1", [0, 0, 0], [0, 0, 0], 8, RGB(0,255,0));
FindObject(Find_ID(Clonk))->CreateParticleAtBone("PSpark", "pos_hand2", [0, 0, 0], [0, 0, 0], 8, RGB(0,0,255));
return(0);
}</code>
<text>Scenario script. Creates an effect which traces a Clonk's body, left hand and right hand with differently colored sparks.</text>
</example>
</examples>
<related>
<funclink>CreateParticle</funclink>
</related>
</func>
<author>Clonk-Karl</author><date>2012-12</date>
</funcs>

View File

@ -1089,8 +1089,8 @@ namespace
glPopMatrix();
#if 0
const StdMeshMatrix& own_trans = instance.GetBoneTransform(attach->ParentBone)
* StdMeshMatrix::Transform(instance.Mesh.GetBone(attach->ParentBone).Transformation);
const StdMeshMatrix& own_trans = attach->Parent->GetBoneTransform(attach->ParentBone)
* StdMeshMatrix::Transform(attach->Parent->GetMesh().GetBone(attach->ParentBone).Transformation);
// Draw attached bone
glDisable(GL_DEPTH_TEST);
@ -1137,13 +1137,12 @@ namespace
glPolygonMode(GL_BACK, modes[1]);
}
#if 0
// Draw attached bone
if (instance.GetAttachParent())
{
const StdMeshInstance::AttachedMesh* attached = instance.GetAttachParent();
const StdMeshMatrix& own_trans = instance.GetBoneTransform(attached->ChildBone) * StdMeshMatrix::Transform(instance.Mesh.GetBone(attached->ChildBone).Transformation);
const StdMeshMatrix& own_trans = instance.GetBoneTransform(attached->ChildBone) * StdMeshMatrix::Transform(instance.GetMesh().GetBone(attached->ChildBone).Transformation);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
@ -1270,7 +1269,7 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
parity = !parity;
// Scale so that the mesh fits in (tx,ty,twdt,thgt)
const float rx = -std::min(v1.x,v1.y) / fabs(v2.x - v1.x);
const float rx = -std::min(v1.x,v2.x) / fabs(v2.x - v1.x);
const float ry = -std::min(v1.y,v2.y) / fabs(v2.y - v1.y);
const float dx = tx + rx*twdt;
const float dy = ty + ry*thgt;

View File

@ -28,6 +28,7 @@
#include <C4AulDefFunc.h>
#include <C4Command.h>
#include <C4DefList.h>
#include <C4Draw.h>
#include <C4GameMessage.h>
#include <C4GraphicsResource.h>
#include <C4Material.h>
@ -2092,6 +2093,120 @@ static bool FnSetMeshMaterial(C4Object *Obj, C4String* Material, int iSubMesh)
return true;
}
static bool FnCreateParticleAtBone(C4Object* Obj, C4String* szName, C4String* szBoneName, C4ValueArray* Pos, C4ValueArray* Dir, long a, long b, C4Object* pTarget, bool fBehindTarget)
{
// safety
if(pTarget && !pTarget->Status) return false;
// Get bone
if(!Obj->pMeshInstance) return false;
const StdMesh& mesh = Obj->pMeshInstance->GetMesh();
const StdMeshBone* bone = mesh.GetBoneByName(szBoneName->GetData());
if(!bone) return false;
// Get transform
Obj->pMeshInstance->UpdateBoneTransforms();
const StdMeshMatrix transform = Obj->pMeshInstance->GetBoneTransform(bone->Index) * StdMeshMatrix::Transform(bone->Transformation);
// Get offset and direction
StdMeshVector x, dir;
if(Pos)
{
if(Pos->GetSize() != 3)
throw new C4AulExecError("CreateParticleAtBone: Pos is not a three-vector");
x.x = (*Pos)[0].getInt();
x.y = (*Pos)[1].getInt();
x.z = (*Pos)[2].getInt();
}
else { x.x = x.y = x.z = 0.0f; }
if(Dir)
{
if(Dir->GetSize() != 3)
throw new C4AulExecError("CreateParticleAtBone: Dir is not a three-vector");
dir.x = (*Dir)[0].getInt() / 10.0f;
dir.y = (*Dir)[1].getInt() / 10.0f;
dir.z = (*Dir)[2].getInt() / 10.0f;
}
else { dir.x = dir.y = dir.z = 0.0f; }
// Apply the bone transformation to them, to go from bone coordinates
// to mesh coordinates (note that bone coordinates use the OGRE
// coordinate system, so they need to be transformed to Clonk coordinates).
const StdMeshMatrix ClonkToOgre = StdMeshMatrix::Inverse(C4Draw::OgreToClonk);
// This is a good example why we should have different types for
// position vectors and displacement vectors. TODO.
StdMeshVector transformed_x = transform * (ClonkToOgre * x);
transformed_x.x += transform(0,3);
transformed_x.y += transform(1,3);
transformed_x.z += transform(2,3);
x = C4Draw::OgreToClonk * transformed_x;
dir = C4Draw::OgreToClonk * (transform * (ClonkToOgre * dir));
// Apply MeshTransformation in the mesh reference frame
C4Value value;
Obj->GetProperty(P_MeshTransformation, &value);
StdMeshMatrix MeshTransform;
if (!C4ValueToMatrix(value, &MeshTransform))
MeshTransform = StdMeshMatrix::Identity();
x = MeshTransform * x;
dir = MeshTransform * dir;
x.x += MeshTransform(0,3);
x.y += MeshTransform(1,3);
x.z += MeshTransform(2,3);
// Now go to world coordinates -- this code is copied from and needs to
// stay in sync with C4DrawGL::PerformMesh, so the particles are
// created at the correct position.
// TODO: This should be moved into a common function.
const StdMeshBox& box = mesh.GetBoundingBox();
StdMeshVector v1, v2;
v1.x = box.x1; v1.y = box.y1; v1.z = box.z1;
v2.x = box.x2; v2.y = box.y2; v2.z = box.z2;
v1 = C4Draw::OgreToClonk * v1; // TODO: Include translation
v2 = C4Draw::OgreToClonk * v2; // TODO: Include translation
const float tx = fixtof(Obj->fix_x) + Obj->Def->Shape.GetX();
const float ty = fixtof(Obj->fix_y) + Obj->Def->Shape.GetY();
const float twdt = Obj->Def->Shape.Wdt;
const float thgt = Obj->Def->Shape.Hgt;
const float rx = -std::min(v1.x,v2.x) / fabs(v2.x - v1.x);
const float ry = -std::min(v1.y,v2.y) / fabs(v2.y - v1.y);
const float dx = tx + rx*twdt;
const float dy = ty + ry*thgt;
x.x += dx;
x.y += dy;
// Finally, apply DrawTransform to the world coordinates
StdMeshMatrix DrawTransform;
if(Obj->pDrawTransform)
{
C4DrawTransform transform(*Obj->pDrawTransform, fixtof(Obj->fix_x), fixtof(Obj->fix_y));
DrawTransform(0, 0) = transform.mat[0];
DrawTransform(0, 1) = transform.mat[1];
DrawTransform(0, 2) = 0.0f;
DrawTransform(0, 3) = transform.mat[2];
DrawTransform(1, 0) = transform.mat[3];
DrawTransform(1, 1) = transform.mat[4];
DrawTransform(1, 2) = 0.0f;
DrawTransform(1, 3) = transform.mat[5];
DrawTransform(2, 0) = 0.0f;
DrawTransform(2, 1) = 0.0f;
DrawTransform(2, 2) = 1.0f;
DrawTransform(2, 3) = 0.0f;
}
else
{
DrawTransform = StdMeshMatrix::Identity();
}
x = DrawTransform * x;
dir = DrawTransform * dir;
x.x += DrawTransform(0,3);
x.y += DrawTransform(1,3);
x.z += DrawTransform(2,3);
// get particle
C4ParticleDef *pDef=::Particles.GetDef(FnStringPar(szName));
if (!pDef) return false;
// cast
::Particles.Create(pDef, x.x, x.y, dir.x, dir.y, (float) a/10.0f, b, pTarget ? (fBehindTarget ? &pTarget->BackParticles : &pTarget->FrontParticles) : NULL, pTarget);
// success, even if not created
return true;
}
//=========================== C4Script Function Map ===================================
C4ScriptConstDef C4ScriptObjectConstMap[]=
@ -2412,6 +2527,7 @@ void InitObjectFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "SetAttachTransform", FnSetAttachTransform);
AddFunc(pEngine, "GetMeshMaterial", FnGetMeshMaterial);
AddFunc(pEngine, "SetMeshMaterial", FnSetMeshMaterial);
AddFunc(pEngine, "CreateParticleAtBone", FnCreateParticleAtBone);
AddFunc(pEngine, "ChangeDef", FnChangeDef);
AddFunc(pEngine, "GrabContents", FnGrabContents);
AddFunc(pEngine, "Punch", FnPunch);