Browse Source

support block animations and dialog close notifications

Kolja Strohm 2 years ago
parent
commit
e34b571470

+ 13 - 8
FactoryCraft/Block.cpp

@@ -98,14 +98,14 @@ void Block::api(char* message)
             if (this->skelett)
             {
                 float z = (float)fluidAmount / 1000.f;
-                Knochen* k = this->skelett->zKnochen()->zKind();
-                k->setPosition(Vec3<float>(0.f, 0.f, z - 1));
-                k = k->zGeschwister();
-                k->setPosition(Vec3<float>(0.f, 0.f, z - 1));
-                k = k->zGeschwister();
-                k->setPosition(Vec3<float>(0.f, 0.f, z - 1));
-                k = k->zGeschwister();
-                k->setPosition(Vec3<float>(0.f, 0.f, z - 1));
+                Bone* b = this->skelett->zRootBone()->zFirstChild();
+                b->setPosition(Vec3<float>(0.f, 0.f, z - 1));
+                b = b->zFirstSibling();
+                b->setPosition(Vec3<float>(0.f, 0.f, z - 1));
+                b = b->zFirstSibling();
+                b->setPosition(Vec3<float>(0.f, 0.f, z - 1));
+                b = b->zFirstSibling();
+                b->setPosition(Vec3<float>(0.f, 0.f, z - 1));
             }
         }
     }
@@ -184,6 +184,11 @@ const BlockType* Block::zBlockType() const
     return zType;
 }
 
+Skeleton* Block::zSkeleton() const
+{
+    return skelett;
+}
+
 Textur* Block::zEffectTextur()
 {
     if (hp < maxHP) return breakTextur;

+ 1 - 0
FactoryCraft/Block.h

@@ -46,6 +46,7 @@ public:
 
     Vec3<int> getLocation() const;
     const BlockType* zBlockType() const;
+    Skeleton* zSkeleton() const;
     Textur* zEffectTextur() override;
     float getEffectPercentage() override;
     friend Chunk;

+ 55 - 0
FactoryCraft/BlockAnimation.cpp

@@ -0,0 +1,55 @@
+#include "BlockAnimation.h"
+
+BlockAnimation::BlockAnimation(
+    Block* block, Framework::SkeletonAnimation* animation)
+    : ReferenceCounter(),
+      block(block),
+      animation(animation)
+{}
+
+BlockAnimation::~BlockAnimation() {
+    block->release();
+    if(animation) animation->release();
+}
+
+void BlockAnimation::appendAnimation(int boneId,
+    double time,
+    Framework::Vec3<float> pos,
+    Framework::Vec3<float> rot)
+{
+    BoneAnimation* ba = animation->zAnimation(boneId);
+    if (ba)
+    {
+        ba->addKeyFrame(ba->getMaxTime() + time, pos, rot);
+    }
+    else
+    {
+        Bone* bone = block->zSkeleton()->zBone(boneId);
+        animation->addAnimation(
+            boneId, bone->getPosition(), bone->getRotation());
+        animation->addKeyFrame(boneId, time, pos, rot);
+    }
+}
+
+bool BlockAnimation::tick(double time) {
+    if (animation)
+    {
+        animation->tick(time);
+        animation->apply(block->zSkeleton());
+        if (animation->isFinished())
+        {
+            animation->release();
+            animation = 0;
+        }
+        return 1;
+    }
+    return 0;
+}
+
+bool BlockAnimation::isFinished() const {
+    return animation == 0;
+}
+
+Block* BlockAnimation::zBlock() const {
+    return block;
+}

+ 25 - 0
FactoryCraft/BlockAnimation.h

@@ -0,0 +1,25 @@
+#pragma once
+
+#include <Animation3D.h>
+
+#include "Block.h"
+
+class BlockAnimation : public Framework::ReferenceCounter
+{
+private:
+    Block* block;
+    Framework::SkeletonAnimation* animation;
+
+public:
+    BlockAnimation(Block* block, Framework::SkeletonAnimation* animation);
+    ~BlockAnimation();
+    
+    void appendAnimation(int boneId,
+        double time,
+        Framework::Vec3<float> pos,
+        Framework::Vec3<float> rot);
+    bool tick(double time);
+    
+    bool isFinished() const;
+    Block* zBlock() const;
+};

+ 75 - 5
FactoryCraft/Chunk.cpp

@@ -22,6 +22,28 @@ Chunk::~Chunk()
     World::INSTANCE->zClient()->chunkAPIRequest(location, &msg, 1);
 }
 
+void Chunk::appendAnimation(
+    Block* zB, int boneId, double time, Vec3<float> pos, Vec3<float> rot)
+{
+    if (!zB->zSkeleton() || !zB->zSkeleton()->zBone(boneId)) return;
+    acs.lock();
+    for (BlockAnimation* animation : animations)
+    {
+        if (animation->zBlock() == zB)
+        {
+            animation->appendAnimation(boneId, time, pos, rot);
+            acs.unlock();
+            return;
+        }
+    }
+    SkeletonAnimation* sa = new SkeletonAnimation();
+    Bone* bone = zB->zSkeleton()->zBone(boneId);
+    sa->addAnimation(boneId, bone->getPosition(), bone->getRotation());
+    sa->addKeyFrame(boneId, time, pos, rot);
+    animations.add(new BlockAnimation(dynamic_cast<Block*>(zB->getThis()), sa));
+    acs.unlock();
+}
+
 void Chunk::api(char* message)
 {
     switch (message[0])
@@ -47,6 +69,28 @@ void Chunk::api(char* message)
             }
             break;
         }
+    case 1: // animate block
+        {
+            int index = *(int*)(message + 1);
+            int boneId = *(int*)(message + 5);
+            double time = *(double*)(message + 9);
+            Framework::Vec3<float> pos;
+            pos.x = *(float*)(message + 17);
+            pos.y = *(float*)(message + 21);
+            pos.z = *(float*)(message + 25);
+            Framework::Vec3<float> rot;
+            rot.x = *(float*)(message + 29);
+            rot.y = *(float*)(message + 33);
+            rot.z = *(float*)(message + 37);
+            Framework::Vec3<int> location((index / WORLD_HEIGHT) / CHUNK_SIZE,
+                (index / WORLD_HEIGHT) % CHUNK_SIZE,
+                index % WORLD_HEIGHT);
+            location.x += this->location.x - CHUNK_SIZE / 2;
+            location.y += this->location.y - CHUNK_SIZE / 2;
+            Block* zB = zBlockAt(location);
+            if (zB) appendAnimation(zB, boneId, time, pos, rot);
+            break;
+        }
     }
 }
 
@@ -161,7 +205,8 @@ void Chunk::load(Framework::StreamReader* zReader)
                     pos.y + location.y - CHUNK_SIZE / 2,
                     pos.z});
             blocks.add(b);
-            blockCache.set((char*)&index, 4, dynamic_cast<Block*>(b->getThis()));
+            blockCache.set(
+                (char*)&index, 4, dynamic_cast<Block*>(b->getThis()));
             cs.unlock();
             vcs.lock();
             if (b->isVisible())
@@ -190,8 +235,7 @@ void Chunk::load(Framework::StreamReader* zReader)
             zReader->lese(lightData, 6);
             if (x == -1)
             {
-                int cacheIndex
-                    = y * WORLD_HEIGHT + z;
+                int cacheIndex = y * WORLD_HEIGHT + z;
                 Block* zB = blockCache.z((char*)&cacheIndex, 4);
                 if (zB)
                 {
@@ -209,7 +253,8 @@ void Chunk::load(Framework::StreamReader* zReader)
             }
             else if (x == CHUNK_SIZE)
             {
-                int cacheIndex = ((CHUNK_SIZE - 1) * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
+                int cacheIndex
+                    = ((CHUNK_SIZE - 1) * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
                 Block* zB = blockCache.z((char*)&cacheIndex, 4);
                 if (zB)
                 {
@@ -340,4 +385,29 @@ void Chunk::forAll(std::function<void(Model3D*)> f)
     vcs.unlock();
 }
 
-void Chunk::tick(std::function<void(Model3D*)> f) {}
+bool Chunk::tick(std::function<void(Model3D*)> f, double time)
+{
+    bool res = 0;
+    acs.lock();
+    auto iterator = animations.begin();
+    while (iterator)
+    {
+        if (iterator->tick(time))
+        {
+            res |= iterator->zBlock()->tick(time);
+            if (iterator->isFinished())
+            {
+                iterator.remove();
+                continue;
+            }
+        }
+        else
+        {
+            iterator.remove();
+            continue;
+        }
+        ++iterator;
+    }
+    acs.unlock();
+    return res;
+}

+ 6 - 1
FactoryCraft/Chunk.h

@@ -9,6 +9,7 @@
 
 #include "Area.h"
 #include "Block.h"
+#include "BlockAnimation.h"
 
 class Chunk : public Framework::Model3DCollection
 {
@@ -20,6 +21,10 @@ private:
     bool isLoading;
     Framework::Critical cs;
     Framework::Critical vcs;
+    Framework::Critical acs;
+    Framework::RCArray<BlockAnimation> animations;
+
+    void appendAnimation(Block* zB, int boneId, double time, Vec3<float> pos, Vec3<float> rot);
 
 public:
     Chunk(Framework::Punkt location);
@@ -35,5 +40,5 @@ public:
     Framework::Vec3<int> getMin() const;
     Framework::Vec3<int> getMax() const;
     void forAll(std::function<void(Model3D*)> f) override;
-    void tick(std::function<void(Model3D*)> f) override;
+    bool tick(std::function<void(Model3D*)> f, double time) override;
 };

+ 5 - 1
FactoryCraft/Constants.h

@@ -2,5 +2,9 @@
 
 #define CHUNK_SIZE             16
 #define WORLD_HEIGHT           500
-#define CHUNK_VISIBILITY_RANGE 4
+#ifdef _DEBUG
+#    define CHUNK_VISIBILITY_RANGE 1
+#else
+#    define CHUNK_VISIBILITY_RANGE 4
+#endif
 #define MAX_VIEW_DISTANCE      CHUNK_SIZE* CHUNK_VISIBILITY_RANGE

+ 50 - 2
FactoryCraft/Dialog.cpp

@@ -46,6 +46,31 @@ UIMLDialog::UIMLDialog(
     {
         view->setSize(view->getBreite(), view->calculateContentSize().y);
     }
+    bool notifyOnClose = 0;
+    int notifyOnCloseDimension = -1;
+    Vec3<int> notifyOnCloseBlock;
+    if (xml->hasAttribute("notifyOnClose"))
+    {
+        notifyOnClose = 1;
+        Text value = xml->getAttributeValue("notifyOnClose");
+        if (value.hat(","))
+        {
+            Text* first = value.getTeilText(0, value.positionVon(",", 0) + 1);
+            Text* second = value.getTeilText(
+                value.positionVon(",", 0) + 1, value.positionVon(",", 1));
+            Text* third = value.getTeilText(
+                value.positionVon(",", 1) + 1, value.positionVon(",", 2));
+            Text* forth = value.getTeilText(value.positionVon(",", 2) + 1);
+            notifyOnCloseDimension = (int)*first;
+            notifyOnCloseBlock.x = (int)*second;
+            notifyOnCloseBlock.y = (int)*third;
+            notifyOnCloseBlock.z = (int)*forth;
+            first->release();
+            second->release();
+            third->release();
+            forth->release();
+        } // TODO: else entity id
+    }
     addMember(view);
 
     LTDBDatei iconsDat;
@@ -67,8 +92,31 @@ UIMLDialog::UIMLDialog(
     setSize(view->getBreite() + 4, view->getHeight() + 24);
     setPosition(window->zBildschirm()->getBackBufferSize() / 2 - getSize() / 2);
     setRBreite(2);
-    setClosingMe([onClose, this](void* p, void* o, MausEreignis me) {
-        if (me.id == ME_RLinks) onClose(this);
+    setClosingMe([onClose,
+                     notifyOnClose,
+                     notifyOnCloseDimension,
+                     notifyOnCloseBlock,
+                     this](void* p, void* o, MausEreignis me) {
+        if (me.id == ME_RLinks)
+        {
+            if (notifyOnClose)
+            {
+                if (notifyOnCloseDimension >= 0)
+                {
+                    char* msg = new char[name.getLength() + 3];
+                    msg[0] = 1; // dialog closed
+                    *(short*)(msg + 1) = (short)name.getLength();
+                    memcpy(msg + 3, name.getText(), name.getLength());
+                    World::INSTANCE->zClient()->blockAPIRequest(
+                        notifyOnCloseDimension,
+                        notifyOnCloseBlock,
+                        msg,
+                        name.getLength() + 3);
+                    delete[] msg;
+                } // TODO: else entity notification
+            }
+            onClose(this);
+        }
         return 1;
     });
     setRFarbe(0xFF52525E);

+ 20 - 2
FactoryCraft/FactoryClient.cpp

@@ -385,6 +385,25 @@ void FactoryClient::blockAPIRequest(
     cs.unlock();
 }
 
+void FactoryClient::blockAPIRequest(
+    int dimensionId, Vec3<int> pos, char* message, unsigned short length)
+{
+    if (!foreground) return;
+    cs.lock();
+    length += 18;
+    foreground->sende((char*)&length, 2);
+    char msgId = 7;
+    foreground->sende(&msgId, 1);
+    foreground->sende((char*)&dimensionId, 4);
+    msgId = 1;
+    foreground->sende(&msgId, 1);
+    foreground->sende((char*)&pos.x, 4);
+    foreground->sende((char*)&pos.y, 4);
+    foreground->sende((char*)&pos.z, 4);
+    foreground->sende(message, length - 18);
+    cs.unlock();
+}
+
 void FactoryClient::chunkAPIRequest(
     Punkt center, char* message, unsigned short length)
 {
@@ -402,8 +421,7 @@ void FactoryClient::chunkAPIRequest(
     cs.unlock();
 }
 
-void FactoryClient::dimensionAPIRequest(
-    char* message, unsigned short length)
+void FactoryClient::dimensionAPIRequest(char* message, unsigned short length)
 {
     if (!foreground) return;
     length += 1;

+ 1 - 0
FactoryCraft/FactoryClient.h

@@ -43,6 +43,7 @@ public:
     void sendPlayerMovement(MovementFrame& frame);
     void entityAPIRequest(int entityId, char* message, unsigned short length);
     void blockAPIRequest(Vec3<int> pos, char* message, unsigned short length);
+    void blockAPIRequest(int dimensionId, Vec3<int> pos, char* message, unsigned short length);
     void chunkAPIRequest(
         Framework::Punkt center, char* message, unsigned short length);
     void dimensionAPIRequest(char* message, unsigned short length);

+ 2 - 0
FactoryCraft/FactoryCraft.vcxproj

@@ -174,6 +174,7 @@ copy "..\..\..\..\..\Allgemein\Network\x64\Release\Network.dll" "network.dll"</C
     <ClCompile Include="AddEntityUpdate.cpp" />
     <ClCompile Include="Area.cpp" />
     <ClCompile Include="Block.cpp" />
+    <ClCompile Include="BlockAnimation.cpp" />
     <ClCompile Include="BlockType.cpp" />
     <ClCompile Include="Chat.cpp" />
     <ClCompile Include="ChatHistory.cpp" />
@@ -257,6 +258,7 @@ copy "..\..\..\..\..\Allgemein\Network\x64\Release\Network.dll" "network.dll"</C
     <ClInclude Include="Load.h" />
     <ClInclude Include="MapOptions.h" />
     <ClInclude Include="MapWindow.h" />
+    <ClInclude Include="BlockAnimation.h" />
     <ClInclude Include="OptionsWindow.h" />
     <ClInclude Include="RecipieGroup.h" />
     <ClInclude Include="RecipieIngredient.h" />

+ 9 - 0
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -62,6 +62,9 @@
     <Filter Include="Menu\utils">
       <UniqueIdentifier>{85fd0935-ea54-491e-bd78-f6547890cfca}</UniqueIdentifier>
     </Filter>
+    <Filter Include="graphics\animations">
+      <UniqueIdentifier>{4c7b207a-85f2-470f-9e27-42ea57c0cde9}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Main.cpp">
@@ -211,6 +214,9 @@
     <ClCompile Include="OptionsWindow.cpp">
       <Filter>Menu\utils</Filter>
     </ClCompile>
+    <ClCompile Include="BlockAnimation.cpp">
+      <Filter>graphics\animations</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Area.h">
@@ -366,6 +372,9 @@
     <ClInclude Include="OptionsWindow.h">
       <Filter>Menu\utils</Filter>
     </ClInclude>
+    <ClInclude Include="BlockAnimation.h">
+      <Filter>graphics\animations</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <FxCompile Include="DX11CustomVertexShader.hlsl">

+ 8 - 7
FactoryCraft/Load.cpp

@@ -94,7 +94,8 @@ void createDefaultCube(Bildschirm* zScreen)
     // the order of the polygons has to be NORTH (front), EAST (left), SOUTH
     // (back), WEST (right), TOP, BOTTOM according to the Area definition front
     // side
-    Polygon3D* p = new Polygon3D(); // looking from (0,0,0) to (1,0,0) to see this side
+    Polygon3D* p
+        = new Polygon3D(); // looking from (0,0,0) to (1,0,0) to see this side
     p->indexAnz = 6;
     p->indexList = new int[p->indexAnz];
     p->indexList[0] = 0;
@@ -747,12 +748,12 @@ void createFluidCube(Bildschirm* zScreen)
     p->indexList[5] = 2 + 20;
     data->addPolygon(p);
 
-    Skelett* s = new Skelett();
-    s->addKnochen(new Knochen(0));
-    s->addKnochen(new Knochen(1), 0);
-    s->addKnochen(new Knochen(2), 0);
-    s->addKnochen(new Knochen(3), 0);
-    s->addKnochen(new Knochen(4), 0);
+    Skeleton* s = new Skeleton();
+    int rootId = s->addBone(Vec3<float>(0, 0, 0), Vec3<float>(0, 0, 0), -1);
+    s->addBone(Vec3<float>(0, 0, 0), Vec3<float>(0, 0, 0), rootId);
+    s->addBone(Vec3<float>(0, 0, 0), Vec3<float>(0, 0, 0), rootId);
+    s->addBone(Vec3<float>(0, 0, 0), Vec3<float>(0, 0, 0), rootId);
+    s->addBone(Vec3<float>(0, 0, 0), Vec3<float>(0, 0, 0), rootId);
     data->setSkelettZ(s);
 
     data->calculateNormals();

+ 3 - 1
FactoryCraft/MapWindow.cpp

@@ -23,8 +23,10 @@ MapWindow::MapWindow()
             - getHeight() / 2);
     setKMin(200, 200);
     options = new MapOptions();
+    options->getThis(); // increase reference counter outside of dynamic_cast to
+                        // avoid compiler warning
     uiFactory.initParam.bildschirm->addMember(
-        dynamic_cast<Zeichnung*>(options->getThis()));
+        dynamic_cast<Zeichnung*>(options));
 }
 
 MapWindow::~MapWindow()