All pastes #818006 Raw Edit

Unnamed

public diff v1 · immutable
·published 2007-12-16 00:44 UTC
rendered paste body
Index: src/common/effects/pseffectobjlabel.h===================================================================--- src/common/effects/pseffectobjlabel.h	(revision 0)+++ src/common/effects/pseffectobjlabel.h	(revision 436)@@ -0,0 +1,82 @@+/*+ * Author: Roland Schulz+ *+ * Copyright (C) 2007 Atomic Blue (info@planeshift.it, http://www.atomicblue.org)+ *+ *+ * This program is free software; you can redistribute it and/or+ * modify it under the terms of the GNU General Public License+ * as published by the Free Software Foundation (version 2 of the License)+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.+ *+ */++#ifndef PS_EFFECT_OBJ_LABEL_HEADER+#define PS_EFFECT_OBJ_LABEL_HEADER++#include "pseffectobj.h"+#include <imesh/genmesh.h>+#include <csutil/cscolor.h>+#include "pseffectobjtextable.h"++struct iGraphics3D;+struct iGraphics2D;+struct iTextureManager;+struct iTextureWrapper;+struct iFont;+struct iParticle;+class  psEffect2DRenderer;++class psEffectObjLabel : public psEffectObj, public psEffectObjTextable+{+private:+    // needed managers+    csRef<iTextureManager>  txtmgr;+    csRef<iGeneralFactoryState> facState;+    csRef<iGeneralMeshState> genState;++    // font+    csString       sizeFileName;+    csArray<uint16> xpos;+    csArray<uint16> ypos;+    csArray<uint16> width;++public:+    psEffectObjLabel(iView *parentView, psEffect2DRenderer * renderer2d);+    virtual ~psEffectObjLabel();++    /** Creates a material that will fit an array of text elements and draws those elements.+     */+    virtual bool SetText(const csArray<psEffectTextElement> & elements);+    virtual bool SetText(const csArray<psEffectTextRow> & rows);+    virtual bool SetText(int rows, ...);++    bool Load(iDocumentNode * node);+    void LoadGlyphs(csString name);+    psEffectObj * Clone() const;+    // inherited function overloads+    virtual bool Render(const csVector3 &up);+    virtual bool Update(csTicks elapsed);+    virtual void CloneBase(psEffectObj * newObj) const;++protected:+    /** performs the post setup (after the effect obj has been loaded).+     *  Things like create mesh factory, etc are initialized here.+     */+    bool PostSetup();++    void DrawTextElement(const psEffectTextElement & element);++    /** Creates a mesh factory for this quad.+     */+    virtual bool CreateMeshFact();++};++#endifIndex: src/common/effects/pseffect.cpp===================================================================--- src/common/effects/pseffect.cpp	(revision 435)+++ src/common/effects/pseffect.cpp	(revision 436)@@ -45,6 +45,7 @@ #include "pseffectobjtrail.h" #include "pseffectobjdecal.h" #include "pseffectobjtext2d.h"+#include "pseffectobjlabel.h"  #include "util/log.h" #include "util/pscssetup.h"@@ -184,6 +185,10 @@         {             obj = new psEffectObjText(parentView, renderer2d);         }+        else if (type == "label")+        {+            obj = new psEffectObjLabel(parentView, renderer2d);+        }         else if (type == "trail")         {             obj = new psEffectObjTrail(parentView, renderer2d);Index: src/common/effects/pseffectobjlabel.cpp===================================================================--- src/common/effects/pseffectobjlabel.cpp	(revision 0)+++ src/common/effects/pseffectobjlabel.cpp	(revision 436)@@ -0,0 +1,436 @@+/*+* Author: Roland Schulz+*+* Copyright (C) 2007 Atomic Blue (info@planeshift.it, http://www.atomicblue.org)+*+*+* This program is free software; you can redistribute it and/or+* modify it under the terms of the GNU General Public License+* as published by the Free Software Foundation (version 2 of the License)+* This program is distributed in the hope that it will be useful,+* but WITHOUT ANY WARRANTY; without even the implied warranty of+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+* GNU General Public License for more details.+* You should have received a copy of the GNU General Public License+* along with this program; if not, write to the Free Software+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.+*+*/+#include <ctype.h>+#include <psconfig.h>++#include <csutil/xmltiny.h>+#include <iengine/engine.h>+#include <iengine/material.h>+#include <ivideo/material.h>+#include <iengine/mesh.h>+#include <iengine/movable.h>+#include <iengine/camera.h>+#include <cstool/csview.h>+#include <iengine/region.h>+#include <imesh/objmodel.h>+#include <csutil/flags.h>+#include <csgeom/tri.h>++#include "effects/pseffectobjlabel.h"+#include "effects/pseffectanchor.h"+#include "effects/pseffect2drenderer.h"++#include "util/log.h"+#include "util/pscssetup.h"++#define NUM_GLYPHS 256++psEffectObjLabel::psEffectObjLabel(iView * parentView, psEffect2DRenderer * renderer2d)+               : psEffectObj(parentView, renderer2d)+{+    meshFact = 0;+    xpos.SetSize(NUM_GLYPHS,0);+    ypos.SetSize(NUM_GLYPHS,0);+    width.SetSize(NUM_GLYPHS,64);+    for(int i=0; i<256; i++)+    {+        xpos[i] = (i%16) * 64;+        ypos[i] = (i/16-2) * 64;+    }+}++psEffectObjLabel::~psEffectObjLabel()+{+    if( meshFact )+    {+        engine->RemoveObject(meshFact);+    }+    if( mesh )+    {+        engine->RemoveObject(mesh);+    }++}++bool psEffectObjLabel::Load(iDocumentNode *node)+{+    // get the attributes+    name = "";+    materialName = "";+    csRef<iDocumentAttributeIterator> attribIter = node->GetAttributes();+    while (attribIter->HasNext())+    {+        csRef<iDocumentAttribute> attr = attribIter->Next();+        csString attrName = attr->GetName();++        attrName.Downcase();+        if (attrName == "name")+            name = attr->GetValue();+        else if (attrName == "material")+            materialName = attr->GetValue();+        else if (attrName == "sizefile")+            sizeFileName = attr->GetValue();+    }+    if (name == "")+    {+        csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Attempting to create an effect obj with no name.\n");+        return false;+    }+    if (materialName == "")+    {+        csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Attempting to create an effect obj with no material.\n");+        return false;+    }+    if (sizeFileName == "")+    {+        LoadGlyphs(sizeFileName);+    } +    +    if (!psEffectObj::Load(node))+    {+        return false;+    }+    return PostSetup();+}+++void psEffectObjLabel::LoadGlyphs(csString filename)+{+    csRef<iVFS> vfs = csQueryRegistry<iVFS > ( psCSSetup::object_reg );+    csRef<iDocumentSystem> xml = csQueryRegistry<iDocumentSystem> (psCSSetup::object_reg);+    csRef<iDocument> doc = xml->CreateDocument();+    csRef<iDataBuffer> buf (vfs->ReadFile (filename));+    if (!buf || !buf->GetSize ())+    {+        return ;+    }+    const char* error = doc->Parse( buf );+    if ( error )+    {+        printf("Error loading glyphs file: %s\n", error);+        return ;+    }++    csRef<iDocumentNodeIterator> iter = doc->GetRoot()->GetNode("glyphs")->GetNodes();+    int number;++    while ( iter->HasNext() )+    {+        csRef<iDocumentNode> child = iter->Next();++        if ( child->GetType() != CS_NODE_ELEMENT )+            continue;+        sscanf(child->GetValue(), "glyph%d", &number);+        if (number < 0 || number >= NUM_GLYPHS)+            continue;+        width[number] = child->GetAttributeValueAsInt("width");+        xpos[number] = child->GetAttributeValueAsInt("x");+        ypos[number] = child->GetAttributeValueAsInt("y");+    }+}+++bool psEffectObjLabel::PostSetup()+{+//    if (!CreateMeshFact())+//      return false;++    return true;+}++bool psEffectObjLabel::CreateMeshFact()+{+    static unsigned int uniqueID = 0;+    csString facName = "effect_label_fac_";+    facName += uniqueID++;+    +    meshFact = engine->CreateMeshFactory ("crystalspace.mesh.object.genmesh", facName.GetData());+    region->Add(meshFact->QueryObject());+    +    iMeshObjectFactory * fact = meshFact->GetMeshObjectFactory();+    facState =  scfQueryInterface<iGeneralFactoryState> (fact);+    if (!facState)+    {+        csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Couldn't create genmesh: %s\n", name.GetData());+        return false;+    }++    // setup the material+    csRef<iMaterialWrapper> mat = region->FindMaterial(materialName);+    if (mat)+    {+        fact->SetMaterialWrapper(mat);+    } else {+        csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "No material for label mesh: %s\n", materialName.GetData());+    }+    +#if 0+    facState->SetVertexCount(4);++    // we have to set the vertices so that the quad actually gets rendered+    facState->GetVertices()[0].Set( 0.5f, 0,  0.5f);+    facState->GetVertices()[1].Set(-0.5f, 0,  0.5f);+    facState->GetVertices()[2].Set(-0.5f, 0, -0.5f);+    facState->GetVertices()[3].Set( 0.5f, 0, -0.5f);+    facState->GetTexels()[0].Set(5.0/8,4.0/16);+    facState->GetTexels()[1].Set(4.0/8,4.0/16);+    facState->GetTexels()[2].Set(4.0/8,5.0/16);+    facState->GetTexels()[3].Set(5.0/8,5.0/16);+    facState->GetNormals()[0].Set(0,1,0);+    facState->GetNormals()[1].Set(0,1,0);+    facState->GetNormals()[2].Set(0,1,0);+    facState->GetNormals()[3].Set(0,1,0);++    facState->SetTriangleCount(4);++    facState->GetTriangles()[0].Set(0, 2, 1);+    facState->GetTriangles()[1].Set(0, 2, 3);+    facState->GetTriangles()[2].Set(2, 0, 1);+    facState->GetTriangles()[3].Set(2, 0, 3);+#endif+    return true;+}+++bool psEffectObjLabel::Render(const csVector3 &up)+{+    if(!CreateMeshFact())+      return false;++    objUp = up;++    static unsigned long nextUniqueID = 0;+    csString effectID = "effect_label_";+    effectID += nextUniqueID++;++    // create a mesh wrapper from the factory we just created+    mesh = engine->CreateMeshWrapper(meshFact, effectID.GetData());+    if (!mesh)+    {+        csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Couldn't create meshwrapper in label effect\n");+        return false;+    }++    // do the up vector+//    csReversibleTransform rt;+//    rt.LookAt(csVector3(up.x, up.z, up.y), csVector3(0,2,1));+//    matUp = rt.GetT2O();+//    matBase = matUp;++    // common flags+    mesh->GetFlags().Set(CS_ENTITY_NOHITBEAM);+    mesh->GetFlags().Set(CS_ENTITY_NODECAL);+    // we can have labels overlay geometry, or we can have them be occluded by it like normal objects+    //priority = engine->GetAlphaRenderPriority();+    // zFunc = CS_ZBUF_NONE;+    priority = engine->GetObjectRenderPriority();+    zFunc = CS_ZBUF_USE;+    mixmode = CS_FX_COPY;+    //printf("zbufmode: %d pri: %d mixmode: %d\n", zFunc, priority, mixmode);+    mesh->SetZBufMode(zFunc);+    mesh->SetRenderPriority(priority);++    // disable culling+    csRef<iStringSet> globalStringSet = csQueryRegistryTagInterface<iStringSet> +        (psCSSetup::object_reg, "crystalspace.shared.stringset");+    csStringID viscull_id = globalStringSet->Request ("viscull");+    mesh->GetMeshObject()->GetObjectModel()->SetTriangleData(viscull_id, 0);++    genState =  scfQueryInterface<iGeneralMeshState> (mesh->GetMeshObject());+    genState->SetLighting(false);++    // obj specific++    if (mixmode != CS_FX_ALPHA)+      mesh->GetMeshObject()->SetMixMode(mixmode);  // to check+      // genState->SetMixMode(mixmode); //was not working with latest CS++    return true;+}++bool psEffectObjLabel::Update(csTicks elapsed)+{+    if (!anchor || !anchor->IsReady()) // wait for anchor to be ready+        return true;++    if (!psEffectObj::Update(elapsed))+        return false;++    return true;+}++void psEffectObjLabel::CloneBase(psEffectObj * newObj) const+{+    psEffectObj::CloneBase(newObj);++    psEffectObjLabel * newLabelObj = dynamic_cast<psEffectObjLabel *>(newObj);++    newLabelObj->materialName = materialName;+}++psEffectObj * psEffectObjLabel::Clone() const+{+    psEffectObjLabel * newObj = new psEffectObjLabel(view, renderer2d);+    CloneBase(newObj);+    +    return newObj;+}++bool psEffectObjLabel::SetText(const csArray<psEffectTextElement> & elements)+{+   printf("settext <array> not supported\n");+   return false;+}++bool psEffectObjLabel::SetText(const csArray<psEffectTextRow> & rows)+{+   printf("settext <textrow> not supported\n");+   return false;+}++bool psEffectObjLabel::SetText(int rows, ...)+{+    size_t lettercount = 0;++    static csArray<psEffectTextElement> elemBuffer;+    psEffectTextElement newElem;+    psEffectTextRow * row = 0;+    int y = 0;++    // calculate dimensions of text area+    int maxWidth = 0;+    int maxHeight = 0;++    elemBuffer.Empty();++    va_list arg;+    va_start(arg, rows);++    // Loop through all rows+    for (int a=0; a<rows; a++)+    {+        row = va_arg(arg, psEffectTextRow *);++        // Text and Formatting+        newElem.colour = row->colour;+        newElem.hasOutline = row->hasOutline;+        newElem.hasShadow = row->hasShadow;+        newElem.shadowColour = row->shadowColour;+        newElem.outlineColour = row->outlineColour;+        newElem.text = row->text;+        newElem.align = row->align;+        newElem.width = 0;+        for(uint b=0; b<newElem.text.Length(); b++)+        {+            newElem.width += width[newElem.text[b]];+        }+        // Positioning+        //font->GetDimensions(newElem.text, newElem.width, newElem.height);+        newElem.height = 64;+        newElem.x = 0;+        newElem.y = y;+        elemBuffer.Push(newElem);+        y += newElem.height;+        lettercount += newElem.text.Length();++        int right = newElem.x + newElem.width;+        int bottom = newElem.y + newElem.height;++        if (right > maxWidth)+            maxWidth = right;+        if (bottom > maxHeight)+            maxHeight = bottom;+    }+    va_end(arg);++    CS_ASSERT(facState!=0);+    iMeshObjectFactory * fact = meshFact->GetMeshObjectFactory();+    int mw,mh;+    fact->GetMaterialWrapper()->GetMaterial()->GetTexture()->GetOriginalDimensions(mw, mh);++    facState->SetVertexCount( lettercount * 4 );+    facState->SetTriangleCount( lettercount * 2 );++    size_t elementCount = elemBuffer.GetSize();+    int cp = 0;++    for(size_t i=0; i<elementCount; i++)+    {+        int x = elemBuffer[i].width;+        +        switch (elemBuffer[i].align)+        {+            case ETA_LEFT:+                x = maxWidth;+                break;+            case ETA_CENTER:+                x = (maxWidth-x)/2;+                break;+            case ETA_RIGHT:+                x = maxWidth-x;+                break;+        }+        int y = elemBuffer[i].y;+        const char * text = elemBuffer[i].text;+        for(size_t j=0; j<strlen(text); j++)+        {+            uint c =text[j];+            float fx1, fy1, fx2, fy2;+            fx1 = (float)x / maxWidth*3 - 1.5;+            fy1 = (float)y / maxWidth*3;+            fx2 = (float)(x+width[c]) / maxWidth*3 - 1.5;+            fy2 = (float)(y+64) / maxWidth*3;+            //printf("rendering char %d pos %d,%d - %f %f %f %f\n", cp/4, x, y, fx1, fy1, fx2, fy2);+            facState->GetVertices()[cp  ].Set(fx2,0,fy1); +            facState->GetVertices()[cp+1].Set(fx1,0,fy1); +            facState->GetVertices()[cp+2].Set(fx1,0,fy2); +            facState->GetVertices()[cp+3].Set(fx2,0,fy2);+            // texture is assumed to be 8x8, each cell 64x64+            float fracx1 = (float)xpos[c] / mw;+            float fracy1 = (float)ypos[c] / mh;+            float fracx2 = (float)(xpos[c]+width[c]) / mw;+            float fracy2 = (float)(ypos[c]+64) / mh;+            //printf("texels %c %d,%d - %f %f %f %f\n", text[j], xpos[c], ypos[c], fracx1, fracy1, fracx2, fracy2);+            facState->GetTexels()[cp  ].Set( fracx2, fracy2 );+            facState->GetTexels()[cp+1].Set( fracx1, fracy2 );+            facState->GetTexels()[cp+2].Set( fracx1, fracy1 );+            facState->GetTexels()[cp+3].Set( fracx2, fracy1 );+            facState->GetNormals()[0].Set(0,1,0);+            facState->GetNormals()[1].Set(0,1,0);+            facState->GetNormals()[2].Set(0,1,0);+            facState->GetNormals()[3].Set(0,1,0);+            //facState->GetTriangles()[(cp/2)  ].Set( cp  , cp+2, cp+1);+            facState->GetTriangles()[(cp/2)  ].Set( cp  , cp+2, cp+3);+            facState->GetTriangles()[(cp/2)+1].Set( cp+2, cp  , cp+1);+            //facState->GetTriangles()[cp+3].Set( cp+2, cp  , cp+3);+            cp += 4;+            x += 64;+        }+        csColor color((float)((newElem.colour>>16) & 255)/255.0F,+                      (float)((newElem.colour>> 8) & 255)/255.0F,+                      (float)((newElem.colour    ) & 255)/255.0F);+        mesh->GetMeshObject()->SetColor(color);+    }+//    facState->CalculateNormals();+//    facState->SetColor(csColor(1.0,1.0,1.0));+//    facState->SetLighting(false);+//    fact->SetMixMode(CS_FX_ADD);+//    Render2(objUp);+    return true;+}Index: data/effects/misc/labelfontglyphs.xml===================================================================--- data/effects/misc/labelfontglyphs.xml	(revision 0)+++ data/effects/misc/labelfontglyphs.xml	(revision 436)@@ -0,0 +1,3 @@+<glyphs>+    <glyph032 width=20 x=0 y=256></glyph032>+</glyphs>Index: data/effects/misc/label.eff===================================================================--- data/effects/misc/label.eff	(revision 0)+++ data/effects/misc/label.eff	(revision 436)@@ -0,0 +1,28 @@+<?xml version="1.0" encoding="utf-8" ?> +<library>+    <textures>+        <texture name="labelfonttable">+            <file>/this/art/effects/character_set_myriad.dds</file>+            <alpha><binary/></alpha>+        </texture>+    </textures>+    <materials>+        <material name="mat_labelfonttable">+            <texture>labelfonttable</texture>+        </material>+    </materials>+    <addon plugin="PSEffects">+        <effect name="label">+            <anchor type="basic" name="pos">+                <dir>none</dir>+            </anchor>+            <obj type="label" name="label" material="mat_labelfonttable"+             sizefile="/this/data/effects/misc/labelfontglyphs.xml">+                <mixmode>alpha</mixmode>+                <attach>pos</attach>+                <death>none</death>+                <dir>billboard</dir>+            </obj>+        </effect>+    </addon>+</library>Index: src/client/entitylabels.h===================================================================--- src/client/entitylabels.h	(revision 447)+++ src/client/entitylabels.h	(working copy)@@ -138,9 +138,9 @@     void CreateLabelOfObject( GEMClientObject* object );      /**-     * Shows or hides label of given entity (only sets visibility, doesn't create/destruct it)-     * This is used when visibility mode is OnMouseOver - labels are created for all entities,-     * but only one is set visible (or none at all).+     * Shows or hides label of given entity, and creates the label if it does not exist+     * and needs to be shown, this is used for the mouseover setting, to create+     * labels just before they are viewed for the first time      */     void ShowLabelOfObject( GEMClientObject* object, bool show );     Index: src/client/entitylabels.cpp===================================================================--- src/client/entitylabels.cpp	(revision 447)+++ src/client/entitylabels.cpp	(working copy)@@ -224,8 +224,7 @@         csString guild( actor->GetGuildName() );         csString guild2( psengine->GetGuildName() ); -        if ( guild.Length() )-        if ( guild.Length() )+        if ( guild2.Length() && guild.Length() == guild2.Length() )         {             // If same guild, indicate with color             if (guild == guild2)@@ -276,6 +275,19 @@  void psEntityLabels::CreateLabelOfObject(GEMClientObject *object) {+    if (!object)+    {+        Debug1( LOG_ANY, 0, "NULL object passed to psEntityLabels::CreateLabelOfObject" );+        return;+    }++    // Don't make labels for the player or action locations+    if (object->GetEntity() == celClient->GetMainActor() || object->GetObjectType() == GEM_ACTION_LOC)+        return;++    psEffectManager* effectMgr = psengine->GetEffectManager();+    CS_ASSERT_MSG("Effects Manager must exist before loading entity labels!", effectMgr );+     iMeshWrapper* mesh = object->pcmesh->GetMesh();      // Has it got a mesh to attach to?@@ -285,16 +297,13 @@     // Get the height of the model     const csBox3& boundBox = mesh->GetMeshObject()->GetObjectModel()->GetObjectBoundingBox(); -    psEffectManager* effectMgr = psengine->GetEffectManager();-     // Create the effect-    unsigned int id = effectMgr->RenderEffect( "entitylabel", +    unsigned int id = effectMgr->RenderEffect( "label",                                                 csVector3(0.0f,boundBox.Max(1) + 0.25f,0.0f),                                                mesh );      psEffect* effect = effectMgr->FindEffect(id);     object->SetEntityLabel(effect);-    effectMgr->ShowEffect(id,false);  // Hide until told to show      // Update text     SetObjectText(object);@@ -315,21 +324,10 @@  void psEntityLabels::OnObjectArrived( GEMClientObject* object ) {-    CS_ASSERT_MSG("Effects Manager must exist before loading entity labels!", psengine->GetEffectManager() );--    if (!object)-    {-        Debug1( LOG_ANY, 0, "NULL object passed to psEntityLabels::OnObjectArried" );+    if (visibility == LABEL_NEVER || visibility == LABEL_ONMOUSE)         return;-    } -    // Action location?-    if (object->GetObjectType() == GEM_ACTION_LOC)-        return;--    DeleteLabelOfObject(object); // just to be sure-    if ( object->GetEntity() != celClient->GetMainActor() )-        CreateLabelOfObject( object );+    CreateLabelOfObject( object ); }  @@ -473,9 +471,20 @@  inline void psEntityLabels::ShowLabelOfObject(GEMClientObject* object, bool show) {-    psEffect* effect = object->GetEntityLabel();-    if (effect != NULL)-        psengine->GetEffectManager()->ShowEffect(effect->GetUniqueID(),show);+    if (object->GetEntityLabel() == NULL)+    {+        // If the label is not created, don't bother creating and hiding it, it won't be visible+        if (!show)+            return;++        CreateLabelOfObject(object);+    }++    psEffect* entityLabel = object->GetEntityLabel();+    if (entityLabel != NULL)+    {+        psengine->GetEffectManager()->ShowEffect(entityLabel->GetUniqueID(),show);+    } }  void psEntityLabels::RepaintAllLabels()Index: src/client/psengine.cpp===================================================================--- src/client/psengine.cpp	(revision 447)+++ src/client/psengine.cpp	(working copy)@@ -826,8 +826,10 @@         {             UnmuteAllSounds();         }-        if (IsGameLoaded())-            celclient->GetEntityLabels()->RepaintAllLabels();+        // RS: this causes a freeze switching back to the client window+        // for up to a few seconds, and seems very much unnecessary+        //if (IsGameLoaded())+        //    celclient->GetEntityLabels()->RepaintAllLabels();     }         else if (ev.Name == event_focusgained)     {@@ -1056,7 +1058,7 @@ { } -inline void psEngine::FinishFrame()+void psEngine::FinishFrame() {     g3d->FinishDraw ();     g3d->Print (NULL);