瀏覽代碼

implement recipie lookup menue

Kolja Strohm 2 年之前
父節點
當前提交
422eeed94a

+ 4 - 1
FactoryCraft/CraftingGrid.cpp

@@ -60,6 +60,7 @@ void CraftingGridElement::layout(Framework::XML::Element& element,
     int pHeight,
     int pHeight,
     Framework::UIMLContainer& generalLayouter)
     Framework::UIMLContainer& generalLayouter)
 {
 {
+    z.setSize(500, 500); // TODO: calculate size
     UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
     UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
 }
 }
 
 
@@ -120,7 +121,7 @@ CraftingGridView::CraftingGridView(Text id,
     recipies->setMausEreignis([this](void* p, void* o, MausEreignis me) {
     recipies->setMausEreignis([this](void* p, void* o, MausEreignis me) {
         if (me.id == ME_RLinks)
         if (me.id == ME_RLinks)
         {
         {
-            // Open Item Recipies
+            ((Game*)(Menu*)menuRegister->get("game"))->showItemList();
         }
         }
         return 1;
         return 1;
     });
     });
@@ -385,6 +386,8 @@ void CraftingGridView::render(Bild& rObj)
         }
         }
     }
     }
     craft->render(rObj);
     craft->render(rObj);
+    recipies->setStyle(Knopf::Style::Sichtbar,
+        !((Game*)(Menu*)menuRegister->get("game"))->isItemListVisible());
     recipies->render(rObj);
     recipies->render(rObj);
     rObj.fillRegion(rowSize * 60, gr.y / 2 - 5, 25, 10, 0xFF52525E);
     rObj.fillRegion(rowSize * 60, gr.y / 2 - 5, 25, 10, 0xFF52525E);
     rObj.drawDreieck(Punkt(rowSize * 60 + 25, gr.y / 2 - 15),
     rObj.drawDreieck(Punkt(rowSize * 60 + 25, gr.y / 2 - 15),

+ 230 - 0
FactoryCraft/CraftingRecipies.cpp

@@ -0,0 +1,230 @@
+#include "CraftingRecipies.h"
+
+#include <Bild.h>
+#include <XML.h>
+
+#include "RecipieGroup.h"
+#include "Globals.h"
+
+CraftingRecipiesElement::CraftingRecipiesElement()
+    : Framework::UIMLElement()
+{}
+
+//! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
+//! ist
+bool CraftingRecipiesElement::isApplicableFor(Framework::XML::Element& element)
+{
+    return element.getName().istGleich("craftingRecipies");
+}
+
+//! erstellt eine neue Zeichnung zu einem gegebenen xml Element
+Framework::Zeichnung* CraftingRecipiesElement::parseElement(
+    Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
+{
+    CraftingRecipies* recipies = new CraftingRecipies();
+    element.selectChildsByName("craftingRecipieGroup")
+        .forEach([recipies, &generalFactory](
+                     Framework::XML::Element* zElement) {
+            RecipieGroup* group = new RecipieGroup();
+            group->setToolTip(zElement->getAttributeValue("name"));
+            if (zElement->hasAttribute("itemIcon"))
+            {
+                int type = (int)zElement->getAttributeValue("itemIcon");
+                group->setIcon(dynamic_cast<Framework::Bild*>(
+                    zItemType(type)->zIcon()->getThis()));
+            }
+            zElement->selectChildren().forEach(
+                [group, &generalFactory](Framework::XML::Element* zRecipie) {
+                    group->addRecipie(
+                        generalFactory.parseElement(*zRecipie, generalFactory));
+                });
+            recipies->addRecipieGroup(group);
+        });
+    return recipies;
+}
+
+//! wendet die layout parameter zu einer Zeichnung an
+void CraftingRecipiesElement::layout(Framework::XML::Element& element,
+    Framework::Zeichnung& z,
+    int pWidth,
+    int pHeight,
+    Framework::UIMLContainer& generalLayouter)
+{
+    z.setSize(500, 500); // TODO: calculate size
+    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
+    element.selectChildsByName("craftingRecipieGroup")
+        .selectChildren()
+        .forEach([&z, &generalLayouter](Framework::XML::Element* zElement) {
+            Framework::Zeichnung* child = 0;
+            if (zElement->hasAttribute("id"))
+            {
+                child = generalLayouter.zZeichnungById(
+                    zElement->getAttributeValue("id"));
+            }
+            if (child)
+            {
+                generalLayouter.layout(*zElement,
+                    *child,
+                    z.getBreite(),
+                    z.getHeight(),
+                    generalLayouter);
+            }
+        });
+}
+
+CraftingRecipies::CraftingRecipies()
+    : Framework::ZeichnungHintergrund()
+{
+    setStyle(Framework::Zeichnung::Style::Erlaubt
+             | Framework::Zeichnung::Style::Sichtbar);
+
+    previousPage = uiFactory.createKnopf(uiFactory.initParam);
+    previousPage->setText("<");
+    previousPage->setToolTipText("Previous Page",
+        uiFactory.initParam.bildschirm,
+        uiFactory.initParam.schrift);
+    previousPage->setSize(20, 20);
+    previousPage->setPosition(0, 35);
+    previousPage->setStyle(
+        Framework::Knopf::Style::Normal & ~Framework::Knopf::Style::Sichtbar);
+    previousPage->setMausEreignis([this](void* p, void* z, MausEreignis me) {
+        if (me.id == ME_RLinks)
+        {
+            RecipieGroup* previous = 0;
+            for (RecipieGroup* group : recipieGroups)
+            {
+                if (group->hatStyle(Zeichnung::Style::Sichtbar) && previous)
+                {
+                    group->removeStyle(Zeichnung::Style::Sichtbar);
+                    previous->addStyle(Zeichnung::Style::Sichtbar);
+                }
+                previous = group;
+            }
+        }
+        return 1;
+    });
+
+    nextPage = uiFactory.createKnopf(uiFactory.initParam);
+    nextPage->setText(">");
+    nextPage->setToolTipText("Next Page",
+        uiFactory.initParam.bildschirm,
+        uiFactory.initParam.schrift);
+    nextPage->setSize(20, 20);
+    nextPage->setPosition(0, 35);
+    nextPage->setStyle(
+        Framework::Knopf::Style::Normal & ~Framework::Knopf::Style::Sichtbar);
+    nextPage->setMausEreignis([this](void* p, void* z, MausEreignis me) {
+        if (me.id == ME_RLinks)
+        {
+            bool next = 0;
+            int index = 0;
+            for (RecipieGroup* group : recipieGroups)
+            {
+                if (next)
+                {
+                    group->addStyle(Zeichnung::Style::Sichtbar);
+                    break;
+                }
+                if (group->hatStyle(Zeichnung::Style::Sichtbar)
+                    && recipieGroups.getEintragAnzahl() > index + 1)
+                {
+                    group->removeStyle(Zeichnung::Style::Sichtbar);
+                    next = 1;
+                }
+                index++;
+            }
+        }
+        return 1;
+    });
+}
+
+void CraftingRecipies::addRecipieGroup(RecipieGroup* recipieGroup)
+{
+    recipieGroups.add(recipieGroup);
+}
+
+bool CraftingRecipies::tick(double tickVal)
+{
+    int visibleGroupIndex = -1;
+    int index = 0;
+    for (RecipieGroup* group : recipieGroups)
+    {
+        if (group->hatStyle(Zeichnung::Style::Sichtbar))
+        {
+            visibleGroupIndex = index;
+        }
+        rend |= group->tick(tickVal);
+        index++;
+    }
+    nextPage->setX(getBreite() - 20);
+    previousPage->setStyle(Knopf::Style::Sichtbar, visibleGroupIndex > 0);
+    nextPage->setStyle(
+        Knopf::Style::Sichtbar, visibleGroupIndex < recipieGroups.getEintragAnzahl() - 1);
+    rend |= previousPage->tick(tickVal);
+    rend |= nextPage->tick(tickVal);
+    return ZeichnungHintergrund::tick(tickVal);
+}
+
+void CraftingRecipies::render(Framework::Bild& rObj)
+{
+    if (!hatStyle(Zeichnung::Style::Sichtbar)) return;
+    ZeichnungHintergrund::render(rObj);
+    if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return;
+    int visibleGroupIndex = -1;
+    int index = 0;
+    for (RecipieGroup* group : recipieGroups)
+    {
+        if (group->hatStyle(Zeichnung::Style::Sichtbar))
+        {
+            visibleGroupIndex = index;
+        }
+        group->setPosition(0, 60);
+        group->setSize(getBreite(), getHeight() - 60);
+        group->render(rObj);
+        index++;
+    }
+    int totalWidth = recipieGroups.getEintragAnzahl() * 31 + 1;
+    int possibleDisplayedIcons = getBreite() / 31;
+    int x = 0;
+    if (possibleDisplayedIcons < recipieGroups.getEintragAnzahl()
+        && visibleGroupIndex > possibleDisplayedIcons / 2)
+    {
+        x = (visibleGroupIndex - possibleDisplayedIcons / 2) * -31;
+        if (recipieGroups.getEintragAnzahl() * 31 + 1 + x < getBreite())
+        {
+            x += getBreite() - (recipieGroups.getEintragAnzahl() * 31 + 1 + x);
+        }
+    }
+    index = 0;
+    for (RecipieGroup* group : recipieGroups)
+    {
+        rObj.fillRegion(x, 0, 30, 30, 0xFF000000);
+        rObj.alphaBildSkall(x, 0, 30, 30, *group->zIcon());
+        rObj.drawLinieH(x - 1, 0, 32, 0xFFFFFFFF);
+        if (index != visibleGroupIndex)
+        {
+            rObj.drawLinieH(x - 1, 30, 32, 0xFFFFFFFF);
+        }
+        rObj.drawLinieV(x + 30, 0, 30, 0xFFFFFFFF);
+    }
+    Framework::TextRenderer tr(dynamic_cast<Framework::Schrift*>(
+        uiFactory.initParam.schrift->getThis()));
+    tr.setSchriftSize(12);
+    Text t = Text("Machine page ") + Text(visibleGroupIndex + 1) + Text(" of ")
+           + Text(recipieGroups.getEintragAnzahl());
+    int tbr = tr.getTextBreite(t);
+    tr.renderText(getBreite() / 2 - tbr / 2, 34, t, rObj, 0xFFFFFFFF);
+    previousPage->render(rObj);
+    nextPage->render(rObj);
+    rObj.releaseDrawOptions();
+}
+
+void CraftingRecipies::doMausEreignis(Framework::MausEreignis& me, bool userRet)
+{
+    previousPage->doPublicMausEreignis(me);
+    nextPage->doPublicMausEreignis(me);
+    for (RecipieGroup* group : recipieGroups)
+    {
+        group->doPublicMausEreignis(me);
+    }
+}

+ 40 - 0
FactoryCraft/CraftingRecipies.h

@@ -0,0 +1,40 @@
+#pragma once
+
+#include <UIMLView.h>
+
+#include "RecipieGroup.h"
+
+class CraftingRecipiesElement : public Framework::UIMLElement
+{
+public:
+    CraftingRecipiesElement();
+    //! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
+    //! ist
+    bool isApplicableFor(Framework::XML::Element& element) override;
+    //! erstellt eine neue Zeichnung zu einem gegebenen xml Element
+    Framework::Zeichnung* parseElement(Framework::XML::Element& element,
+        Framework::UIMLContainer& generalFactory) override;
+    //! wendet die layout parameter zu einer Zeichnung an
+    void layout(Framework::XML::Element& element,
+        Framework::Zeichnung& z,
+        int pWidth,
+        int pHeight,
+        Framework::UIMLContainer& generalLayouter) override;
+};
+
+class CraftingRecipies : public Framework::ZeichnungHintergrund
+{
+private:
+    Framework::RCArray<RecipieGroup> recipieGroups;
+    Framework::Knopf* previousPage;
+    Framework::Knopf* nextPage;
+    
+public:
+    CraftingRecipies();
+    
+    void addRecipieGroup(RecipieGroup* recipieGroup);
+    
+    bool tick(double tickVal) override;
+    void render(Framework::Bild& rObj) override;
+    void doMausEreignis(Framework::MausEreignis& me, bool userRet) override;
+};

+ 23 - 23
FactoryCraft/CustomUIDX11PixelShader.h

@@ -257,10 +257,10 @@ ret
 
 
 const BYTE CustomUIDX11PixelShader[] =
 const BYTE CustomUIDX11PixelShader[] =
 {
 {
-     68,  88,  66,  67, 197,   6, 
-    239,  11,  53,  97,  41, 209, 
-     55, 209, 192, 158, 235, 232, 
-    171,   2,   1,   0,   0,   0, 
+     68,  88,  66,  67,  46, 150, 
+    195,  67, 173,  54, 189,  35, 
+     37,  33, 101,  50,  98, 127, 
+    243, 161,   1,   0,   0,   0, 
     164, 118,   0,   0,   6,   0, 
     164, 118,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
       0,   0,  56,   0,   0,   0, 
     252,   4,   0,   0, 164,   5, 
     252,   4,   0,   0, 164,   5, 
@@ -1394,11 +1394,11 @@ const BYTE CustomUIDX11PixelShader[] =
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0, 148,  46, 
       0,   0,   0,   0, 148,  46, 
-     49,   1, 105, 229,  58,  99, 
-      1,   0,   0,   0, 225, 180, 
-     79, 168, 156, 248,  50,  73, 
-    160, 210,  69,  43,  25,  10, 
-      5,  21,   0,   0,   0,   0, 
+     49,   1, 112,  48, 195,  99, 
+      1,   0,   0,   0,  24,  13, 
+    110,  22,  12, 161,  27,  70, 
+    128, 231,  85, 108, 215,  61, 
+    170,  44,   0,   0,   0,   0, 
       0,   0,   0,   0,   1,   0, 
       0,   0,   0,   0,   1,   0, 
       0,   0,   1,   0,   0,   0, 
       0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -1569,10 +1569,10 @@ const BYTE CustomUIDX11PixelShader[] =
       3,   0, 194,  82,   1,   0, 
       3,   0, 194,  82,   1,   0, 
      43, 236,   3,   0,  28,  19, 
      43, 236,   3,   0,  28,  19, 
       2,   0,  65,  36,   1,   0, 
       2,   0,  65,  36,   1,   0, 
-    236, 179,   1,   0, 121, 222, 
-      0,   0, 125,  10,   2,   0, 
-    125, 181,   2,   0, 255,  82, 
-      1,   0, 193,  33,   3,   0, 
+    236, 179,   1,   0,  82, 162, 
+      1,   0, 125,  10,   2,   0, 
+    125, 181,   2,   0,  72, 145, 
+      0,   0, 193,  33,   3,   0, 
      65, 185,   2,   0, 146, 230, 
      65, 185,   2,   0, 146, 230, 
       3,   0,  53, 174,   3,   0, 
       3,   0,  53, 174,   3,   0, 
     118,  19,   1,   0,  98, 163, 
     118,  19,   1,   0,  98, 163, 
@@ -2589,8 +2589,8 @@ const BYTE CustomUIDX11PixelShader[] =
      32,  32,  32,  32,  32,  32, 
      32,  32,  32,  32,  32,  32, 
      32,  32,  32,  32,  32,  32, 
      32,  32,  32,  32,  32,  32, 
      32,  32,  27, 226,  48,   1, 
      32,  32,  27, 226,  48,   1, 
-    128,   0,   0,   0, 249, 123, 
-    244,  43,  45, 215, 216,   1, 
+    128,   0,   0,   0, 232,   1, 
+     45, 216, 105,  40, 217,   1, 
       1,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -3579,14 +3579,14 @@ const BYTE CustomUIDX11PixelShader[] =
       0,   0,  23,   0,   1,   0, 
       0,   0,  23,   0,   1,   0, 
       5,  16,   0,   0,  14,   0, 
       5,  16,   0,   0,  14,   0, 
      23,  21,   0,  16,   0,   0, 
      23,  21,   0,  16,   0,   0, 
-      3,   2, 128, 164,   0,   0, 
+      3,   2, 224,  96,   0,   0, 
     242, 241,  10,   0,  24,  21, 
     242, 241,  10,   0,  24,  21, 
       8,  16,   0,   0,   1,   0, 
       8,  16,   0,   0,   1,   0, 
       1,   0,  10,   0,  24,  21, 
       1,   0,  10,   0,  24,  21, 
       9,  16,   0,   0,   1,   0, 
       9,  16,   0,   0,   1,   0, 
       0,   2,  14,   0,  23,  21, 
       0,   2,  14,   0,  23,  21, 
       0,   0,   0,   0,  10,   2, 
       0,   0,   0,   0,  10,   2, 
-    128, 164,   0,   0, 242, 241, 
+    224,  96,   0,   0, 242, 241, 
      10,   0,  24,  21,  11,  16, 
      10,   0,  24,  21,  11,  16, 
       0,   0,   1,   0,   1,   0, 
       0,   0,   1,   0,   1,   0, 
      10,   0,  24,  21,  12,  16, 
      10,   0,  24,  21,  12,  16, 
@@ -4807,11 +4807,11 @@ const BYTE CustomUIDX11PixelShader[] =
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-    148,  46,  49,   1, 105, 229, 
-     58,  99,   1,   0,   0,   0, 
-    225, 180,  79, 168, 156, 248, 
-     50,  73, 160, 210,  69,  43, 
-     25,  10,   5,  21, 174,   0, 
+    148,  46,  49,   1, 112,  48, 
+    195,  99,   1,   0,   0,   0, 
+     24,  13, 110,  22,  12, 161, 
+     27,  70, 128, 231,  85, 108, 
+    215,  61, 170,  44, 174,   0, 
       0,   0,  47,  76, 105, 110, 
       0,   0,  47,  76, 105, 110, 
     107,  73, 110, 102, 111,   0, 
     107,  73, 110, 102, 111,   0, 
      47, 110,  97, 109, 101, 115, 
      47, 110,  97, 109, 101, 115, 
@@ -4911,7 +4911,7 @@ const BYTE CustomUIDX11PixelShader[] =
       0,   0,   2,   0,   9,   0, 
       0,   0,   2,   0,   9,   0, 
      76,   7,   0,   0,   0,   0, 
      76,   7,   0,   0,   0,   0, 
       0,   0, 100,   9,   0,   0, 
       0,   0, 100,   9,   0,   0, 
-      1,   0, 234,  33,   0,   0, 
+      1,   0, 137,  59,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,  84, 101, 
       0,   0,   0,   0,  84, 101, 
     120, 116, 117, 114, 101,  80, 
     120, 116, 117, 114, 101,  80, 

+ 17 - 17
FactoryCraft/CustomUIDX11VertexShader.h

@@ -237,10 +237,10 @@ ret
 
 
 const BYTE CustomUIDX11VertexShader[] =
 const BYTE CustomUIDX11VertexShader[] =
 {
 {
-     68,  88,  66,  67, 245, 162, 
-    230,  45, 253, 180, 101, 119, 
-    241, 152, 124,  55,  96, 243, 
-    158,  36,   1,   0,   0,   0, 
+     68,  88,  66,  67, 220,  11, 
+    186, 195, 246,  42, 226, 245, 
+    142, 170,  21, 102,  89,  42, 
+     84, 181,   1,   0,   0,   0, 
     216,  93,   0,   0,   6,   0, 
     216,  93,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
       0,   0,  56,   0,   0,   0, 
      84,   3,   0,   0,  12,   4, 
      84,   3,   0,   0,  12,   4, 
@@ -1340,11 +1340,11 @@ const BYTE CustomUIDX11VertexShader[] =
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0, 148,  46, 
       0,   0,   0,   0, 148,  46, 
-     49,   1, 106, 229,  58,  99, 
-      1,   0,   0,   0, 233,  51, 
-    103, 241, 206, 208, 140,  64, 
-    157, 247, 151, 110, 136,  72, 
-     83, 186,   0,   0,   0,   0, 
+     49,   1, 112,  48, 195,  99, 
+      1,   0,   0,   0, 217, 208, 
+    202, 191, 222, 174,  30,  73, 
+    175, 163, 237, 211, 252, 179, 
+     65, 165,   0,   0,   0,   0, 
       0,   0,   0,   0,   1,   0, 
       0,   0,   0,   0,   1,   0, 
       0,   0,   1,   0,   0,   0, 
       0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -2109,8 +2109,8 @@ const BYTE CustomUIDX11VertexShader[] =
     105, 111, 110,  59,  13,  10, 
     105, 111, 110,  59,  13,  10, 
     125,  13,  10,  13,  27, 226, 
     125,  13,  10,  13,  27, 226, 
      48,   1, 128,   0,   0,   0, 
      48,   1, 128,   0,   0,   0, 
-    159, 232,  38,  44,  45, 215, 
-    216,   1,   1,   0,   0,   0, 
+    152, 117,  73, 216, 105,  40, 
+    217,   1,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -3900,11 +3900,11 @@ const BYTE CustomUIDX11VertexShader[] =
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0, 148,  46, 
       0,   0,   0,   0, 148,  46, 
-     49,   1, 106, 229,  58,  99, 
-      1,   0,   0,   0, 233,  51, 
-    103, 241, 206, 208, 140,  64, 
-    157, 247, 151, 110, 136,  72, 
-     83, 186, 175,   0,   0,   0, 
+     49,   1, 112,  48, 195,  99, 
+      1,   0,   0,   0, 217, 208, 
+    202, 191, 222, 174,  30,  73, 
+    175, 163, 237, 211, 252, 179, 
+     65, 165, 175,   0,   0,   0, 
      47,  76, 105, 110, 107,  73, 
      47,  76, 105, 110, 107,  73, 
     110, 102, 111,   0,  47, 110, 
     110, 102, 111,   0,  47, 110, 
      97, 109, 101, 115,   0,  47, 
      97, 109, 101, 115,   0,  47, 
@@ -4004,7 +4004,7 @@ const BYTE CustomUIDX11VertexShader[] =
       2,   0,   9,   0,  64,   6, 
       2,   0,   9,   0,  64,   6, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
     236,   8,   0,   0,   1,   0, 
     236,   8,   0,   0,   1,   0, 
-    250, 238,   0,   0,   0,   0, 
+     29,  22,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,  84, 101, 120, 116, 
       0,   0,  84, 101, 120, 116, 
     117, 114, 101,  86, 101, 114, 
     117, 114, 101,  86, 101, 114, 

+ 18 - 0
FactoryCraft/Dialog.cpp

@@ -6,6 +6,11 @@
 #include "InventoryView.h"
 #include "InventoryView.h"
 #include "Equipment.h"
 #include "Equipment.h"
 #include "CraftingGrid.h"
 #include "CraftingGrid.h"
+#include "CraftingRecipies.h"
+#include "RecipieIngredient.h"
+#include "RecipieOutput.h"
+#include "ShapedRecipie.h"
+#include "UnshapedRecipie.h"
 #include "Globals.h"
 #include "Globals.h"
 
 
 using namespace Framework;
 using namespace Framework;
@@ -20,10 +25,23 @@ UIMLDialog::UIMLDialog(Framework::Text uiml, std::function<void(UIMLDialog* self
 	view->addKnownElement(new InventoryElement());
 	view->addKnownElement(new InventoryElement());
 	view->addKnownElement(new EquipmentElement());
 	view->addKnownElement(new EquipmentElement());
 	view->addKnownElement(new CraftingGridElement());
 	view->addKnownElement(new CraftingGridElement());
+    view->addKnownElement(new CraftingRecipiesElement());
+    view->addKnownElement(new RecipieIngredientElement());
+    view->addKnownElement(new RecipieOutputElement());
+    view->addKnownElement(new ShapedRecipieElement());
+    view->addKnownElement(new UnshapedRecipieElement());
 	view->setUIML(xml);
 	view->setUIML(xml);
 	view->setSize((int)xml->getAttributeValue("width"), (int)xml->getAttributeValue("height"));
 	view->setSize((int)xml->getAttributeValue("width"), (int)xml->getAttributeValue("height"));
 	name = xml->getAttributeValue("id");
 	name = xml->getAttributeValue("id");
 	view->layout();
 	view->layout();
+	if (!xml->hasAttribute("width"))
+	{
+        view->setSize(view->calculateContentSize().x, view->getHeight());
+    }
+    if (!xml->hasAttribute("height"))
+    {
+        view->setSize(view->getBreite(), view->calculateContentSize().y);
+    }
 	addMember(view);
 	addMember(view);
 
 
 	setStyle(Fenster::Style::Sichtbar | Fenster::Style::Erlaubt | Fenster::Style::Rahmen | Fenster::Style::BodyHAlpha | Fenster::Style::Beweglich | Fenster::Style::Titel | Fenster::Style::TitelHAlpha | Fenster::Style::Closable | Fenster::Style::ClosingHAlpha | Fenster::Style::ClosingKlickBuffer | Fenster::Style::TitelHintergrund | Fenster::Style::BodyHintergrund | Fenster::Style::ClosingHintergrund | Fenster::Style::MEIgnoreInside);
 	setStyle(Fenster::Style::Sichtbar | Fenster::Style::Erlaubt | Fenster::Style::Rahmen | Fenster::Style::BodyHAlpha | Fenster::Style::Beweglich | Fenster::Style::Titel | Fenster::Style::TitelHAlpha | Fenster::Style::Closable | Fenster::Style::ClosingHAlpha | Fenster::Style::ClosingKlickBuffer | Fenster::Style::TitelHintergrund | Fenster::Style::BodyHintergrund | Fenster::Style::ClosingHintergrund | Fenster::Style::MEIgnoreInside);

+ 26 - 1
FactoryCraft/FactoryClient.cpp

@@ -61,7 +61,20 @@ void FactoryClient::loadServerInfo()
     {
     {
         int id;
         int id;
         foregroundReader->lese((char*)&id, 4);
         foregroundReader->lese((char*)&id, 4);
-        itemTypes[i] = new ItemType(id, ModelInfo(foregroundReader));
+        char len;
+        foregroundReader->lese((char*)&len, 1);
+        char* name = new char[len + 1];
+        foregroundReader->lese(name, len);
+        name[len] = 0;
+        short tlen;
+        foregroundReader->lese((char*)&tlen, 2);
+        char* tooltipUIML = new char[tlen + 1];
+        foregroundReader->lese(tooltipUIML, tlen);
+        tooltipUIML[tlen] = 0;
+        itemTypes[i] = new ItemType(
+            id, ModelInfo(foregroundReader), Text(name), Text(tooltipUIML));
+        delete[] name;
+        delete[] tooltipUIML;
     }
     }
     foregroundReader->lese((char*)&entityTypeCount, 4);
     foregroundReader->lese((char*)&entityTypeCount, 4);
     entityTypes = new EntityType*[entityTypeCount];
     entityTypes = new EntityType*[entityTypeCount];
@@ -413,6 +426,18 @@ void FactoryClient::inventoryAPIRequest(
     cs.unlock();
     cs.unlock();
 }
 }
 
 
+void FactoryClient::craftingUIMLRequest(int itemTypeId)
+{
+    if (!foreground) return;
+    cs.lock();
+    short length = 5;
+    foreground->sende((char*)&length, 2);
+    char msgId = 5;
+    foreground->sende(&msgId, 1);
+    foreground->sende((char*)&itemTypeId, 4);
+    cs.unlock();
+}
+
 bool FactoryClient::isConnected()
 bool FactoryClient::isConnected()
 {
 {
     return foreground->isConnected() && background->isConnected();
     return foreground->isConnected() && background->isConnected();

+ 1 - 0
FactoryCraft/FactoryClient.h

@@ -49,5 +49,6 @@ public:
         Framework::Either<int, Framework::VecN<int, 4>> target,
         Framework::Either<int, Framework::VecN<int, 4>> target,
         char* message,
         char* message,
         unsigned short length);
         unsigned short length);
+    void craftingUIMLRequest(int itemTypeId);
     bool isConnected();
     bool isConnected();
 };
 };

+ 14 - 0
FactoryCraft/FactoryCraft.vcxproj

@@ -176,6 +176,7 @@ copy "..\..\..\..\..\Allgemein\Network\x64\Release\Network.dll" "network.dll"</C
     <ClCompile Include="BlockType.cpp" />
     <ClCompile Include="BlockType.cpp" />
     <ClCompile Include="Chunk.cpp" />
     <ClCompile Include="Chunk.cpp" />
     <ClCompile Include="CraftingGrid.cpp" />
     <ClCompile Include="CraftingGrid.cpp" />
+    <ClCompile Include="CraftingRecipies.cpp" />
     <ClCompile Include="CustomDX11API.cpp" />
     <ClCompile Include="CustomDX11API.cpp" />
     <ClCompile Include="Dialog.cpp" />
     <ClCompile Include="Dialog.cpp" />
     <ClCompile Include="Dimension.cpp" />
     <ClCompile Include="Dimension.cpp" />
@@ -191,16 +192,22 @@ copy "..\..\..\..\..\Allgemein\Network\x64\Release\Network.dll" "network.dll"</C
     <ClCompile Include="Initialisierung.cpp" />
     <ClCompile Include="Initialisierung.cpp" />
     <ClCompile Include="InventoryView.cpp" />
     <ClCompile Include="InventoryView.cpp" />
     <ClCompile Include="ItemBar.cpp" />
     <ClCompile Include="ItemBar.cpp" />
+    <ClCompile Include="ItemList.cpp" />
     <ClCompile Include="ItemType.cpp" />
     <ClCompile Include="ItemType.cpp" />
     <ClCompile Include="Load.cpp" />
     <ClCompile Include="Load.cpp" />
+    <ClCompile Include="RecipieGroup.cpp" />
+    <ClCompile Include="RecipieIngredient.cpp" />
+    <ClCompile Include="RecipieOutput.cpp" />
     <ClCompile Include="ServerSelection.cpp" />
     <ClCompile Include="ServerSelection.cpp" />
     <ClCompile Include="Main.cpp" />
     <ClCompile Include="Main.cpp" />
     <ClCompile Include="Menu.cpp" />
     <ClCompile Include="Menu.cpp" />
     <ClCompile Include="ModelInfo.cpp" />
     <ClCompile Include="ModelInfo.cpp" />
     <ClCompile Include="PlayerKam.cpp" />
     <ClCompile Include="PlayerKam.cpp" />
+    <ClCompile Include="ShapedRecipie.cpp" />
     <ClCompile Include="StaticInitializerOrder.cpp" />
     <ClCompile Include="StaticInitializerOrder.cpp" />
     <ClCompile Include="StatusBars.cpp" />
     <ClCompile Include="StatusBars.cpp" />
     <ClCompile Include="UIMLToolTip.cpp" />
     <ClCompile Include="UIMLToolTip.cpp" />
+    <ClCompile Include="UnshapedRecipie.cpp" />
     <ClCompile Include="World.cpp" />
     <ClCompile Include="World.cpp" />
     <ClCompile Include="WorldUpdate.cpp" />
     <ClCompile Include="WorldUpdate.cpp" />
   </ItemGroup>
   </ItemGroup>
@@ -212,6 +219,7 @@ copy "..\..\..\..\..\Allgemein\Network\x64\Release\Network.dll" "network.dll"</C
     <ClInclude Include="Chunk.h" />
     <ClInclude Include="Chunk.h" />
     <ClInclude Include="Constants.h" />
     <ClInclude Include="Constants.h" />
     <ClInclude Include="CraftingGrid.h" />
     <ClInclude Include="CraftingGrid.h" />
+    <ClInclude Include="CraftingRecipies.h" />
     <ClInclude Include="CustomDX11API.h" />
     <ClInclude Include="CustomDX11API.h" />
     <ClInclude Include="Dialog.h" />
     <ClInclude Include="Dialog.h" />
     <ClInclude Include="Dimension.h" />
     <ClInclude Include="Dimension.h" />
@@ -228,16 +236,22 @@ copy "..\..\..\..\..\Allgemein\Network\x64\Release\Network.dll" "network.dll"</C
     <ClInclude Include="Initialisierung.h" />
     <ClInclude Include="Initialisierung.h" />
     <ClInclude Include="InventoryView.h" />
     <ClInclude Include="InventoryView.h" />
     <ClInclude Include="ItemBar.h" />
     <ClInclude Include="ItemBar.h" />
+    <ClInclude Include="ItemList.h" />
     <ClInclude Include="ItemType.h" />
     <ClInclude Include="ItemType.h" />
     <ClInclude Include="Load.h" />
     <ClInclude Include="Load.h" />
+    <ClInclude Include="RecipieGroup.h" />
+    <ClInclude Include="RecipieIngredient.h" />
+    <ClInclude Include="RecipieOutput.h" />
     <ClInclude Include="ServerSelection.h" />
     <ClInclude Include="ServerSelection.h" />
     <ClInclude Include="Menu.h" />
     <ClInclude Include="Menu.h" />
     <ClInclude Include="ModelInfo.h" />
     <ClInclude Include="ModelInfo.h" />
     <ClInclude Include="PlayerKam.h" />
     <ClInclude Include="PlayerKam.h" />
     <ClInclude Include="Registries.h" />
     <ClInclude Include="Registries.h" />
+    <ClInclude Include="ShapedRecipie.h" />
     <ClInclude Include="StaticRegistry.h" />
     <ClInclude Include="StaticRegistry.h" />
     <ClInclude Include="StatusBars.h" />
     <ClInclude Include="StatusBars.h" />
     <ClInclude Include="UIMLToolTip.h" />
     <ClInclude Include="UIMLToolTip.h" />
+    <ClInclude Include="UnshapedRecipie.h" />
     <ClInclude Include="WorldUpdate.h" />
     <ClInclude Include="WorldUpdate.h" />
     <ClInclude Include="World.h" />
     <ClInclude Include="World.h" />
   </ItemGroup>
   </ItemGroup>

+ 45 - 0
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -50,6 +50,9 @@
     <Filter Include="Menu\uiml\ToolTip">
     <Filter Include="Menu\uiml\ToolTip">
       <UniqueIdentifier>{6b6b7dea-e3f2-4812-ae3f-24c8ea365780}</UniqueIdentifier>
       <UniqueIdentifier>{6b6b7dea-e3f2-4812-ae3f-24c8ea365780}</UniqueIdentifier>
     </Filter>
     </Filter>
+    <Filter Include="Menu\uiml\recipies">
+      <UniqueIdentifier>{68659053-193e-4113-8771-3df6b6a9c5c0}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Main.cpp">
     <ClCompile Include="Main.cpp">
@@ -151,6 +154,27 @@
     <ClCompile Include="StatusBars.cpp">
     <ClCompile Include="StatusBars.cpp">
       <Filter>Menu\uiml\playerGUI</Filter>
       <Filter>Menu\uiml\playerGUI</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="ItemList.cpp">
+      <Filter>Menu</Filter>
+    </ClCompile>
+    <ClCompile Include="CraftingRecipies.cpp">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClCompile>
+    <ClCompile Include="RecipieIngredient.cpp">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClCompile>
+    <ClCompile Include="RecipieOutput.cpp">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClCompile>
+    <ClCompile Include="ShapedRecipie.cpp">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClCompile>
+    <ClCompile Include="UnshapedRecipie.cpp">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClCompile>
+    <ClCompile Include="RecipieGroup.cpp">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="Area.h">
     <ClInclude Include="Area.h">
@@ -258,6 +282,27 @@
     <ClInclude Include="StatusBars.h">
     <ClInclude Include="StatusBars.h">
       <Filter>Menu\uiml\playerGUI</Filter>
       <Filter>Menu\uiml\playerGUI</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="ItemList.h">
+      <Filter>Menu</Filter>
+    </ClInclude>
+    <ClInclude Include="CraftingRecipies.h">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClInclude>
+    <ClInclude Include="RecipieGroup.h">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClInclude>
+    <ClInclude Include="ShapedRecipie.h">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClInclude>
+    <ClInclude Include="UnshapedRecipie.h">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClInclude>
+    <ClInclude Include="RecipieIngredient.h">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClInclude>
+    <ClInclude Include="RecipieOutput.h">
+      <Filter>Menu\uiml\recipies</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <FxCompile Include="DX11CustomVertexShader.hlsl">
     <FxCompile Include="DX11CustomVertexShader.hlsl">

+ 22 - 5
FactoryCraft/Game.cpp

@@ -49,23 +49,27 @@ Game::Game(Bildschirm* zScreen)
     guiView->setSize(window->zBildschirm()->getBackBufferSize());
     guiView->setSize(window->zBildschirm()->getBackBufferSize());
     elements.add(guiView);
     elements.add(guiView);
     targetUIMLView = new UIMLView("<v/>", uiFactory);
     targetUIMLView = new UIMLView("<v/>", uiFactory);
-    targetUIMLView->setStyle(UIMLView::Style::Hintergrund
-                             | UIMLView::Style::HAlpha);
+    targetUIMLView->setStyle(
+        UIMLView::Style::Hintergrund | UIMLView::Style::HAlpha);
     targetUIMLView->setHintergrundFarbe(0xA0000000);
     targetUIMLView->setHintergrundFarbe(0xA0000000);
     elements.add(targetUIMLView);
     elements.add(targetUIMLView);
-    
+
     filter = initTextFeld(zScreen->getBackBufferSize().x / 2 - 200,
     filter = initTextFeld(zScreen->getBackBufferSize().x / 2 - 200,
         zScreen->getBackBufferSize().y - 200,
         zScreen->getBackBufferSize().y - 200,
         400,
         400,
         20,
         20,
         Framework::TextFeld::Style::TextFeld,
         Framework::TextFeld::Style::TextFeld,
         "");
         "");
+    itemListContainer = new ItemListContainer();
+    window->zBildschirm()->addMember(
+        dynamic_cast<Zeichnung*>(itemListContainer->getThis()));
 }
 }
 
 
 Game::~Game()
 Game::~Game()
 {
 {
     inventoryDragController->release();
     inventoryDragController->release();
     filter->release();
     filter->release();
+    itemListContainer->release();
 }
 }
 
 
 void Game::updatePosition(
 void Game::updatePosition(
@@ -226,7 +230,8 @@ void Game::updateRecipieVisibility()
         if (dialogs.getEintragAnzahl() > 0)
         if (dialogs.getEintragAnzahl() > 0)
         {
         {
             recipieVisible = 1;
             recipieVisible = 1;
-            window->zBildschirm()->addMember(dynamic_cast<Zeichnung*>(filter->getThis()));
+            window->zBildschirm()->addMember(
+                dynamic_cast<Zeichnung*>(filter->getThis()));
         }
         }
     }
     }
     else
     else
@@ -235,10 +240,22 @@ void Game::updateRecipieVisibility()
         {
         {
             recipieVisible = 0;
             recipieVisible = 0;
             window->zBildschirm()->removeMember(filter);
             window->zBildschirm()->removeMember(filter);
+            itemListContainer->removeStyle(Fenster::Style::Sichtbar);
         }
         }
     }
     }
 }
 }
 
 
-const Text* Game::zFilterText() {
+void Game::showItemList()
+{
+    itemListContainer->addStyle(Fenster::Style::Sichtbar);
+}
+
+bool Game::isItemListVisible()
+{
+    return itemListContainer->hatStyle(Fenster::Style::Sichtbar);
+}
+
+const Text* Game::zFilterText()
+{
     return filter->zText();
     return filter->zText();
 }
 }

+ 4 - 0
FactoryCraft/Game.h

@@ -6,6 +6,7 @@
 #include "Dialog.h"
 #include "Dialog.h"
 #include "DragController.h"
 #include "DragController.h"
 #include "Menu.h"
 #include "Menu.h"
+#include "ItemList.h"
 
 
 class Player;
 class Player;
 class InventoryDragSource;
 class InventoryDragSource;
@@ -20,6 +21,7 @@ private:
     Framework::UIMLView* targetUIMLView;
     Framework::UIMLView* targetUIMLView;
     DragController<InventoryDragSource, int>* inventoryDragController;
     DragController<InventoryDragSource, int>* inventoryDragController;
     Framework::TextFeld* filter;
     Framework::TextFeld* filter;
+    ItemListContainer* itemListContainer;
     bool recipieVisible;
     bool recipieVisible;
 
 
 public:
 public:
@@ -34,5 +36,7 @@ public:
     void setTargetUIML(Framework::Text uiml);
     void setTargetUIML(Framework::Text uiml);
 
 
     void updateRecipieVisibility();
     void updateRecipieVisibility();
+    void showItemList();
+    bool isItemListVisible();
     const Text* zFilterText();
     const Text* zFilterText();
 };
 };

+ 4 - 3
FactoryCraft/InventoryView.cpp

@@ -102,9 +102,10 @@ void SlotInfo::render(
         }
         }
         const char* units[] = {"", "K", "M", "G", "T", "P"};
         const char* units[] = {"", "K", "M", "G", "T", "P"};
         int i = 0;
         int i = 0;
-        for (; i < 6 && itemCount > 1024; i++)
-            itemCount = itemCount / 1024;
-        Text count = itemCount;
+        int tmpCount = itemCount;
+        for (; i < 6 && tmpCount > 1024; i++)
+            tmpCount = tmpCount / 1024;
+        Text count = tmpCount;
         count += units[i];
         count += units[i];
         tr.renderText(x + 45 - tr.getTextBreite(count),
         tr.renderText(x + 45 - tr.getTextBreite(count),
             y + 45 - tr.getTextHeight(count),
             y + 45 - tr.getTextHeight(count),

+ 190 - 0
FactoryCraft/ItemList.cpp

@@ -0,0 +1,190 @@
+#include "ItemList.h"
+
+#include <Scroll.h>
+#include <TextFeld.h>
+
+#include "Globals.h"
+#include "Game.h"
+#include "UIMLToolTip.h"
+#include "World.h"
+
+ItemList::ItemList()
+    : ZeichnungHintergrund(),
+      currentTooltipSlot(-1)
+{
+    setStyle(ZeichnungHintergrund::Style::Sichtbar
+             | ZeichnungHintergrund::Style::Erlaubt);
+    slotList = new int[itemTypeCount];
+    memset(slotList, 0, sizeof(int) * itemTypeCount);
+    slotCount = 0;
+    setNeedToolTipEvent([this](Zeichnung* z, Punkt p) {
+        int slot = getSlotByLocalPos(p);
+        if (currentTooltipSlot != slot && currentTooltipSlot != -1)
+        {
+            std::cout << "closing tooltip\n";
+            this->setToolTipZ(0);
+            currentTooltipSlot = -1;
+        }
+        if (slot != -1)
+        {
+            std::cout << "requesting tooltip for slot " << slot << "\n";
+            UIMLToolTip* tip = new UIMLToolTip();
+            tip->setUIML(itemTypes[slot]->getTooltipUIML());
+            tip->setWarten(0);
+            tip->setPosition(mausPos.x, mausPos.y + 15);
+            setToolTipZ(tip);
+            currentTooltipSlot = slot;
+            return 1;
+        }
+        return 0;
+    });
+}
+
+ItemList::~ItemList()
+{
+    delete[] slotList;
+}
+
+int ItemList::getSlotByLocalPos(Framework::Punkt pos)
+{
+    int x = 0;
+    int y = 0;
+    for (int i = 0; i < slotCount; i++)
+    {
+        if (pos.x >= x && pos.x < x + 50 && pos.y >= y && pos.y < y + 50)
+            return slotList[i];
+        x += 60;
+        if (x >= getBreite())
+        {
+            y += 60;
+            x = 0;
+        }
+    }
+    return -1;
+}
+
+void ItemList::doMausEreignis(Framework::MausEreignis& me, bool userRet) {
+    mausPos.x = me.originalX;
+    mausPos.y = me.originalY;
+    if (me.id == ME_Bewegung)
+    {
+        if (getSlotByLocalPos(Punkt(me.mx, me.my)) != currentTooltipSlot)
+        {
+            if (currentTooltipSlot != -1)
+            {
+                std::cout << "closing tooltip\n";
+                setToolTipZ(0);
+            }
+            else
+                toolTipRequested = 0;
+            currentTooltipSlot = -1;
+        }
+    }
+    else if (me.id == ME_RLinks)
+    {
+        int pos = getSlotByLocalPos(Punkt(me.mx, me.my));
+        if (pos >= 0)
+        {
+            World::INSTANCE->zClient()->craftingUIMLRequest(
+                itemTypes[pos]->getId());
+        }
+    }
+    ZeichnungHintergrund::doMausEreignis(me, userRet);
+}
+
+bool ItemList::tick(double time)
+{
+    return ZeichnungHintergrund::tick(time);
+}
+
+void ItemList::adjustSize(int parentWidth, int parentHeight)
+{
+    int ipr = (parentWidth + 10) / 60;
+    if (ipr == 0)
+    {
+        ipr = 1;
+    }
+    setSize(ipr * 60 - 10,
+        (itemTypeCount / ipr + (itemTypeCount % ipr == 0 ? 0 : 1)) * 60
+            - 10);
+}
+
+void ItemList::render(Framework::Bild& rObj)
+{
+    const Text* filter
+        = dynamic_cast<Game*>((Menu*)menuRegister->get("game"))->zFilterText();
+    ZeichnungHintergrund::render(rObj);
+    if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return;
+    int x = 0;
+    int y = 0;
+    int index = 0;
+    for (int i = 0; i < itemTypeCount; i++)
+    {
+        if (filter->getLength() > 0
+            && !itemTypes[i]->getName().hat(filter->getText()))
+        {
+            continue;
+        }
+        slotList[index] = i;
+        rObj.fillRegion(x, y, 50, 50, 0xFF222222);
+        rObj.alphaBild(x, y, 50, 50, *itemTypes[i]->zIcon());
+        x += 60;
+        if (x >= getBreite())
+        {
+            x = 0;
+            y += 60;
+        }
+        index++;
+    }
+    slotCount = index;
+    rObj.releaseDrawOptions();
+}
+
+ItemListContainer::ItemListContainer()
+    : Fenster()
+{
+    setStyle(
+        Fenster::Style::Erlaubt | Fenster::Style::Rahmen
+        | Fenster::Style::BodyHAlpha | Fenster::Style::Beweglich
+        | Fenster::Style::Titel | Fenster::Style::TitelHAlpha
+        | Fenster::Style::TitelHintergrund | Fenster::Style::BodyHintergrund
+        | Fenster::Style::MEIgnoreInside | Fenster::Style::VScroll
+        | Fenster::Style::BreiteChangeable | Fenster::Style::BodyMinBr
+        | Fenster::Style::BodyMinHi | Fenster::Style::HeightChangeable
+        | Fenster::Style::Closable | Fenster::Style::ClosingHAlpha
+        | Fenster::Style::ClosingKlickBuffer | Fenster::Style::ClosingHAlpha
+        | Fenster::Style::ClosingHintergrund);
+    setKBgFarbe(0xA0000000);
+    setTBgFarbe(0xA0000000);
+    setSBgFarbe(0xA0000000);
+    setSize(329, window->zBildschirm()->getBackBufferSize().y - 20);
+    setPosition(
+        window->zBildschirm()->getBackBufferSize().x - getBreite() - 10, 10);
+    setRBreite(2);
+    setRFarbe(0xFF52525E);
+    setTitel("Recipies");
+    setTSchriftZ(
+        dynamic_cast<Schrift*>(uiFactory.initParam.schrift->getThis()));
+    zTTextFeld()->setSize(0, 20);
+    zTTextFeld()->addStyle(TextFeld::Style::Center);
+    setTastaturEreignis(_ret1TE);
+    setKMin(70, 70);
+    setVSBScroll(0);
+    zVScrollBar()->setBgFarbe(0xA0000000, 1);
+    setClosingMe([this](void* p, void* o, MausEreignis me) {
+        if (me.id == ME_RLinks) removeStyle(Style::Sichtbar);
+        return 1;
+    });
+
+    list = new ItemList();
+    list->setPosition(10, 10);
+    addMember(list);
+}
+
+bool ItemListContainer::tick(double time)
+{
+    list->adjustSize(getInnenBreite() - 35, getInnenHeight());
+    if (zVScrollBar()->getScrollData()->max != list->getHeight() + 20)
+        setVSBMax(list->getHeight() + 20);
+    return Fenster::tick(time);
+}

+ 33 - 0
FactoryCraft/ItemList.h

@@ -0,0 +1,33 @@
+#pragma once
+
+#include <Fenster.h>
+#include <Bild.h>
+
+class ItemList : public Framework::ZeichnungHintergrund
+{
+private:
+    Framework::Punkt mausPos;
+    int currentTooltipSlot;
+    int* slotList;
+    int slotCount;
+    
+    int ItemList::getSlotByLocalPos(Framework::Punkt pos);
+    void doMausEreignis(Framework::MausEreignis& me, bool userRet) override;
+
+public:
+    ItemList();
+    ~ItemList();
+    bool tick(double time) override;
+    void adjustSize(int parentWidth, int parentHeight);
+    void render(Framework::Bild& rObj) override;
+};
+
+class ItemListContainer : public Framework::Fenster
+{
+private:
+    ItemList* list;
+
+public:
+    ItemListContainer();
+    bool tick(double time) override;
+};

+ 15 - 2
FactoryCraft/ItemType.cpp

@@ -5,11 +5,14 @@
 
 
 #include "Registries.h"
 #include "Registries.h"
 
 
-ItemType::ItemType(int id, ModelInfo model)
+ItemType::ItemType(
+    int id, ModelInfo model, Framework::Text name, Framework::Text tooltipUIML)
     : ReferenceCounter(),
     : ReferenceCounter(),
       id(id),
       id(id),
       model(model),
       model(model),
-      icon(0)
+      icon(0),
+      name(name),
+      tooltipUIML(tooltipUIML)
 {}
 {}
 
 
 ItemType::~ItemType()
 ItemType::~ItemType()
@@ -41,4 +44,14 @@ Framework::Model3DData* ItemType::getItemModel() const
 Framework::Model3DTextur* ItemType::getItemTextur() const
 Framework::Model3DTextur* ItemType::getItemTextur() const
 {
 {
     return model.getTexture();
     return model.getTexture();
+}
+
+const Framework::Text& ItemType::getName() const
+{
+    return name;
+}
+
+const Framework::Text& ItemType::getTooltipUIML() const
+{
+    return tooltipUIML;
 }
 }

+ 8 - 1
FactoryCraft/ItemType.h

@@ -10,9 +10,14 @@ protected:
     const int id;
     const int id;
     const ModelInfo model;
     const ModelInfo model;
     Framework::Bild* icon;
     Framework::Bild* icon;
+    Framework::Text name;
+    Framework::Text tooltipUIML;
 
 
 public:
 public:
-    ItemType(int id, ModelInfo model);
+    ItemType(int id,
+        ModelInfo model,
+        Framework::Text name,
+        Framework::Text tooltipUIML);
     ~ItemType();
     ~ItemType();
 
 
     int getId() const;
     int getId() const;
@@ -20,4 +25,6 @@ public:
     Framework::Bild* zIcon() const;
     Framework::Bild* zIcon() const;
     Framework::Model3DData* getItemModel() const;
     Framework::Model3DData* getItemModel() const;
     Framework::Model3DTextur* getItemTextur() const;
     Framework::Model3DTextur* getItemTextur() const;
+    const Framework::Text& getName() const;
+    const Framework::Text& getTooltipUIML() const;
 };
 };

+ 138 - 0
FactoryCraft/RecipieGroup.cpp

@@ -0,0 +1,138 @@
+#include "RecipieGroup.h"
+
+#include <Bild.h>
+#include <Schrift.h>
+
+#include "Globals.h"
+
+RecipieGroup::RecipieGroup()
+    : Framework::ZeichnungHintergrund()
+{
+    setStyle(Framework::Zeichnung::Style::Erlaubt
+             | Framework::Zeichnung::Style::Sichtbar);
+    icon = 0;
+    previousPage = uiFactory.createKnopf(uiFactory.initParam);
+    previousPage->setText("<");
+    previousPage->setToolTipText("Previous Page",
+        uiFactory.initParam.bildschirm,
+        uiFactory.initParam.schrift);
+    previousPage->setSize(20, 20);
+    previousPage->setPosition(0, 0);
+    previousPage->setStyle(
+        Framework::Knopf::Style::Normal & ~Framework::Knopf::Style::Sichtbar);
+    previousPage->setMausEreignis([this](void* p, void* z, MausEreignis me) {
+        if (me.id == ME_RLinks)
+        {
+            currentPage--;
+        }
+        return 1;
+    });
+
+    nextPage = uiFactory.createKnopf(uiFactory.initParam);
+    nextPage->setText(">");
+    nextPage->setToolTipText("Next Page",
+        uiFactory.initParam.bildschirm,
+        uiFactory.initParam.schrift);
+    nextPage->setSize(20, 20);
+    nextPage->setPosition(0, 0);
+    nextPage->setStyle(
+        Framework::Knopf::Style::Normal & ~Framework::Knopf::Style::Sichtbar);
+    nextPage->setMausEreignis([this](void* p, void* z, MausEreignis me) {
+        if (me.id == ME_RLinks)
+        {
+            currentPage++;
+        }
+        return 1;
+    });
+}
+
+RecipieGroup::~RecipieGroup()
+{
+    if (icon) icon->release();
+    previousPage->release();
+    nextPage->release();
+}
+
+void RecipieGroup::addRecipie(Framework::Zeichnung* recipie)
+{
+    recipies.add(recipie);
+}
+
+void RecipieGroup::setIcon(Framework::Bild* icon)
+{
+    if (this->icon) this->icon->release();
+    this->icon = icon;
+}
+
+void RecipieGroup::setToolTip(Framework::Text toolTip)
+{
+    this->toolTip = toolTip;
+}
+
+bool RecipieGroup::tick(double tickVal)
+{
+    int pi = 1;
+    int y = 20;
+    bool first = 1;
+    for (Zeichnung* recipie : recipies)
+    {
+        if (recipie->getHeight() + y > getHeight() && !first)
+        {
+            pi++;
+            y = 20;
+        }
+        recipie->setStyle(Zeichnung::Style::Sichtbar, pi == currentPage);
+        recipie->setX(getBreite() / 2 - recipie->getBreite() / 2);
+        recipie->setY(y);
+        y += recipie->getHeight() + 50;
+        first = 0;
+        rend |= recipie->tick(tickVal);
+    }
+    nextPage->setX(getBreite() - 20);
+    maxPage = pi;
+    currentPage = MAX(1, MIN(pi, currentPage));
+    previousPage->setStyle(Knopf::Style::Sichtbar, currentPage > 1);
+    nextPage->setStyle(Knopf::Style::Sichtbar, currentPage < maxPage);
+    rend |= previousPage->tick(tickVal);
+    rend |= nextPage->tick(tickVal);
+    return ZeichnungHintergrund::tick(tickVal);
+}
+
+void RecipieGroup::render(Framework::Bild& rObj)
+{
+    if (!hatStyle(Zeichnung::Style::Sichtbar)) return;
+    ZeichnungHintergrund::render(rObj);
+    if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return;
+    Framework::TextRenderer tr(dynamic_cast<Framework::Schrift*>(uiFactory.initParam.schrift->getThis()));
+    tr.setSchriftSize(12);
+    Text t = Text("Recipie page ") + Text(currentPage) + Text(" of ") + Text(maxPage);
+    int tbr = tr.getTextBreite(t);
+    tr.renderText(getBreite() / 2 - tbr / 2, 4, t, rObj, 0xFFFFFFFF);
+    for (Framework::Zeichnung* recipie : recipies)
+    {
+        recipie->render(rObj);
+    }
+    previousPage->render(rObj);
+    nextPage->render(rObj);
+    rObj.releaseDrawOptions();
+}
+
+void RecipieGroup::doMausEreignis(Framework::MausEreignis& me, bool userRet)
+{
+    previousPage->doPublicMausEreignis(me);
+    nextPage->doPublicMausEreignis(me);
+    for (Zeichnung* recipie : recipies)
+    {
+        recipie->doPublicMausEreignis(me);
+    }
+}
+
+Framework::Bild* RecipieGroup::zIcon() const
+{
+    return icon;
+}
+
+Framework::Text RecipieGroup::getToolTip() const
+{
+    return toolTip;
+}

+ 32 - 0
FactoryCraft/RecipieGroup.h

@@ -0,0 +1,32 @@
+#pragma once
+
+#include <Array.h>
+#include <Zeichnung.h>
+#include <Knopf.h>
+
+class RecipieGroup : public Framework::ZeichnungHintergrund
+{
+private:
+    Framework::Bild* icon;
+    Framework::RCArray<Framework::Zeichnung> recipies;
+    Framework::Text toolTip;
+    Framework::Knopf* previousPage;
+    Framework::Knopf* nextPage;
+    int currentPage;
+    int maxPage;
+
+public:
+    RecipieGroup();
+    ~RecipieGroup();
+
+    void addRecipie(Framework::Zeichnung* recipie);
+    void setIcon(Framework::Bild* icon);
+    void setToolTip(Framework::Text toolTip);
+
+    bool tick(double tickVal) override;
+    void render(Framework::Bild& rObj) override;
+    void doMausEreignis(Framework::MausEreignis& me, bool userRet) override;
+
+    Framework::Bild* zIcon() const;
+    Framework::Text getToolTip() const;
+};

+ 1008 - 0
FactoryCraft/RecipieIngredient.cpp

@@ -0,0 +1,1008 @@
+#include "RecipieIngredient.h"
+
+#include <DateiSystem.h>
+#include <ToolTip.h>
+#include <XML.h>
+
+#include "Globals.h"
+
+RecipieIngredientElement::RecipieIngredientElement()
+    : Framework::UIMLElement()
+{}
+
+LogicTree* RecipieIngredientElement::parse(Framework::XML::Element* zElement)
+{
+    if (zElement->getName().istGleich("anyItem"))
+    {
+        return new LogicTree(LogicalOperator::OR, new RequirementSet());
+    }
+    else if (zElement->getName().istGleich("attribute"))
+    {
+        AttributeOperator op = AttributeOperator::Equals;
+        if (zElement->getAttributeValue("operator").istGleich("!="))
+        {
+            op = AttributeOperator::NotEquals;
+        }
+        else if (zElement->getAttributeValue("operator").istGleich(">"))
+        {
+            op = AttributeOperator::GreaterThan;
+        }
+        else if (zElement->getAttributeValue("operator").istGleich(">="))
+        {
+            op = AttributeOperator::GreaterThanOrEquals;
+        }
+        else if (zElement->getAttributeValue("operator").istGleich("<"))
+        {
+            op = AttributeOperator::LessThan;
+        }
+        else if (zElement->getAttributeValue("operator").istGleich("<="))
+        {
+            op = AttributeOperator::LessThanOrEquals;
+        }
+        Requirement* req = new Requirement(zElement->getAttributeValue("name"),
+            zElement->getAttributeValue("value"),
+            op);
+        RequirementSet* set = new RequirementSet();
+        set->addRequirement(req);
+        req->release();
+        return new LogicTree(LogicalOperator::OR, set);
+    }
+    else if (zElement->getName().istGleich("operator"))
+    {
+        bool result0_0 = (bool)(int)zElement->getAttributeValue("result_0_0");
+        bool result0_1 = (bool)(int)zElement->getAttributeValue("result_0_1");
+        bool result1_0 = (bool)(int)zElement->getAttributeValue("result_1_0");
+        bool result1_1 = (bool)(int)zElement->getAttributeValue("result_1_1");
+        if (!result0_0 && !result0_1 && !result1_0 && !result1_1)
+        { // none match
+            RequirementSet* set = new RequirementSet();
+            Requirement* req
+                = new Requirement("_x", "0", AttributeOperator::Equals);
+            set->addRequirement(req);
+            req->release();
+            req = new Requirement("_x", "1", AttributeOperator::Equals);
+            set->addRequirement(req);
+            req->release();
+            return new LogicTree(LogicalOperator::OR, set);
+        }
+        if (result0_0 && result0_1 && result1_0 && result1_1)
+        { // any match
+            return new LogicTree(LogicalOperator::OR, new RequirementSet());
+        }
+        auto iterator = zElement->getChilds();
+        LogicTree* left = parse(iterator.val());
+        if (!result0_0 && !result0_1 && result1_0 && result1_1)
+        {
+            return left;
+        }
+        if (result0_0 && result0_1 && !result1_0 && !result1_1)
+        {
+            left->negate();
+            return left;
+        }
+        LogicTree* right = 0;
+        iterator++;
+        right = parse(iterator.val());
+        if (!result0_0 && result0_1 && !result1_0 && result1_1)
+        {
+            left->release();
+            return right;
+        }
+        if (result0_0 && !result0_1 && result1_0 && !result1_1)
+        {
+            left->release();
+            right->negate();
+            return right;
+        }
+        if (!result0_0 && !result0_1 && !result1_0 && result1_1)
+        {
+            LogicTree* result = new LogicTree(LogicalOperator::AND, 0);
+            result->addChildren(left);
+            result->addChildren(right);
+            return result;
+        }
+        if (!result0_0 && result0_1 && result1_0 && result1_1)
+        {
+            LogicTree* result = new LogicTree(LogicalOperator::OR, 0);
+            result->addChildren(left);
+            result->addChildren(right);
+            return result;
+        }
+        if (result0_0 && result0_1 && result1_0 && !result1_1)
+        {
+            left->negate();
+            right->negate();
+            LogicTree* result = new LogicTree(LogicalOperator::OR, 0);
+            result->addChildren(left);
+            result->addChildren(right);
+            return result;
+        }
+        if (result0_0 && !result0_1 && !result1_0 && !result1_1)
+        {
+            left->negate();
+            right->negate();
+            LogicTree* result = new LogicTree(LogicalOperator::AND, 0);
+            result->addChildren(left);
+            result->addChildren(right);
+            return result;
+        }
+        if (!result0_0 && !result0_1 && result1_0 && !result1_1)
+        {
+            right->negate();
+            LogicTree* result = new LogicTree(LogicalOperator::AND, 0);
+            result->addChildren(left);
+            result->addChildren(right);
+            return result;
+        }
+        if (!result0_0 && result0_1 && !result1_0 && !result1_1)
+        {
+            left->negate();
+            LogicTree* result = new LogicTree(LogicalOperator::AND, 0);
+            result->addChildren(left);
+            result->addChildren(right);
+            return result;
+        }
+        if (!result0_0 && result0_1 && result1_0 && !result1_1)
+        {
+            LogicTree* or = new LogicTree(LogicalOperator::OR, 0);
+            or->addChildren(left);
+            or->addChildren(right);
+            LogicTree* notLeft = left->clone();
+            notLeft->negate();
+            LogicTree* notRight = right->clone();
+            notRight->negate();
+            LogicTree* notOr = new LogicTree(LogicalOperator::OR, 0);
+            notOr->addChildren(notLeft);
+            notOr->addChildren(notRight);
+            LogicTree* result = new LogicTree(LogicalOperator::AND, 0);
+            result->addChildren(or);
+            result->addChildren(notOr);
+            return result;
+        }
+        if (result0_0 && !result0_1 && !result1_0 && result1_1)
+        {
+            LogicTree*and = new LogicTree(LogicalOperator::AND, 0);
+            and->addChildren(left);
+            and->addChildren(right);
+            LogicTree* notLeft = left->clone();
+            notLeft->negate();
+            LogicTree* notRight = right->clone();
+            notRight->negate();
+            LogicTree* notAnd = new LogicTree(LogicalOperator::AND, 0);
+            notAnd->addChildren(notLeft);
+            notAnd->addChildren(notRight);
+            LogicTree* result = new LogicTree(LogicalOperator::OR, 0);
+            result->addChildren(and);
+            result->addChildren(notAnd);
+            return result;
+        }
+        if (result0_0 && !result0_1 && result1_0 && result1_1)
+        {
+            right->negate();
+            LogicTree* result = new LogicTree(LogicalOperator::OR, 0);
+            result->addChildren(left);
+            result->addChildren(right);
+            return result;
+        }
+        if (result0_0 && result0_1 && !result1_0 && result1_1)
+        {
+            left->negate();
+            LogicTree* result = new LogicTree(LogicalOperator::OR, 0);
+            result->addChildren(left);
+            result->addChildren(right);
+            return result;
+        }
+    }
+    return 0;
+}
+
+//! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
+//! ist
+bool RecipieIngredientElement::isApplicableFor(Framework::XML::Element& element)
+{
+    return element.getName().istGleich("ingredient");
+}
+
+//! erstellt eine neue Zeichnung zu einem gegebenen xml Element
+Framework::Zeichnung* RecipieIngredientElement::parseElement(
+    Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
+{
+    int amount = (int)element.getAttributeValue("amount");
+    RecipieIngredient* result = new RecipieIngredient(amount);
+    Framework::XML::Editor logicSelector = element.selectChildsByName("logic");
+    if (logicSelector.exists())
+    {
+        LogicTree* logic = new LogicTree(LogicalOperator::OR, 0);
+        logicSelector.selectChildren().forEach(
+            [this, logic](Framework::XML::Element* zElement) {
+                logic->addChildren(parse(zElement));
+            });
+        Framework::RCArray<RequirementSet>* requirements = logic->resolve();
+        logic->release();
+        for (RequirementSet* set : *requirements)
+        {
+            result->addPossibleItem(
+                set->getIcon(), new Text(set->renderToTooltip()), set->getItemType());
+        }
+        requirements->release();
+    }
+    return result;
+}
+
+//! wendet die layout parameter zu einer Zeichnung an
+void RecipieIngredientElement::layout(Framework::XML::Element& element,
+    Framework::Zeichnung& z,
+    int pWidth,
+    int pHeight,
+    Framework::UIMLContainer& generalLayouter)
+{
+    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
+    z.setWidth(50);
+    z.setHeight(50);
+}
+
+RecipieIngredient::RecipieIngredient(int amount)
+    : Framework::ZeichnungHintergrund(),
+      currentIconIndex(0),
+      timtUntilNextIcon(2.0),
+      amount(amount)
+{
+    setStyle(Framework::Zeichnung::Style::Erlaubt
+             | Framework::Zeichnung::Style::Sichtbar);
+    Framework::ToolTip* tip = new Framework::ToolTip(window->zBildschirm());
+    tip->addStyle(Framework::ZeichnungHintergrund::Style::Hintergrund
+                  | Framework::ZeichnungHintergrund::Style::HAlpha
+                  | Framework::ZeichnungHintergrund::Style::Rahmen
+                  | Framework::ZeichnungHintergrund::Style::Sichtbar);
+    tip->setHintergrundFarbe(0xA0000000);
+    tip->setRahmenFarbe(0xFFFFFFFF);
+    tip->setRahmenBreite(1);
+    toolTip = uiFactory.createTextFeld(uiFactory.initParam);
+    toolTip->setText("");
+    toolTip->setSize(0, 0);
+    toolTip->addStyle(Framework::TextFeld::Style::Mehrzeilig);
+    tip->addMember(toolTip);
+    tip->setWarten(0.5);
+    setToolTipZ(tip);
+}
+
+void RecipieIngredient::addPossibleItem(
+    Framework::Bild* icon, Framework::Text* toolTip, int typeId)
+{
+    icons.add(icon);
+    toolTips.add(toolTip);
+    itemTypes.add(typeId);
+    if (toolTips.getEintragAnzahl() == 1)
+    {
+        this->toolTip->setText(toolTips.z(0)->getText());
+        this->toolTip->setSize(
+            this->toolTip->getNeededWidth(), this->toolTip->getNeededHeight());
+    }
+}
+
+bool RecipieIngredient::tick(double tickVal)
+{
+    if (!zToolTip()->isVisible())
+    {
+        timtUntilNextIcon -= tickVal;
+        if (timtUntilNextIcon <= 0)
+        {
+            timtUntilNextIcon = 2.0;
+            currentIconIndex++;
+            if (currentIconIndex >= icons.getEintragAnzahl())
+            {
+                currentIconIndex = 0;
+            }
+            if (toolTips.getEintragAnzahl() > 0)
+            {
+                toolTip->setText(toolTips.z(currentIconIndex)->getText());
+                toolTip->setSize(
+                    toolTip->getNeededWidth(), toolTip->getNeededHeight());
+                rend = 1;
+            }
+        }
+    }
+    return ZeichnungHintergrund::tick(tickVal);
+}
+
+void RecipieIngredient::render(Framework::Bild& rObj)
+{
+    ZeichnungHintergrund::render(rObj);
+    if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return;
+    TextRenderer tr;
+    tr.setSchriftZ(
+        dynamic_cast<Schrift*>(uiFactory.initParam.schrift->getThis()));
+    tr.setSchriftSize(12);
+    rObj.fillRegion(0, 0, 50, 50, 0xFF222222);
+    if (icons.getEintragAnzahl() > 0)
+        rObj.alphaBild(0, 0, 50, 50, *icons.z(currentIconIndex));
+    const char* units[] = {"", "K", "M", "G", "T", "P"};
+    int i = 0;
+    int tmpCount = amount;
+    for (; i < 6 && tmpCount > 1024; i++)
+        tmpCount = tmpCount / 1024;
+    Text count = tmpCount;
+    count += units[i];
+    tr.renderText(45 - tr.getTextBreite(count),
+        45 - tr.getTextHeight(count),
+        count,
+        rObj,
+        0xFFFFFFFF);
+    rObj.releaseDrawOptions();
+}
+
+void RecipieIngredient::doMausEreignis(Framework::MausEreignis& me, bool userRet)
+{
+    if (me.id == ME_RLinks)
+    {
+        World::INSTANCE->zClient()->craftingUIMLRequest(
+            itemTypes.get(currentIconIndex));
+    }
+    ZeichnungHintergrund::doMausEreignis(me, userRet);
+}
+
+Requirement::Requirement(
+    Framework::Text attribute, Framework::Text value, AttributeOperator op)
+    : Framework::ReferenceCounter(),
+      attribute(attribute),
+      value(value),
+      op(op)
+{}
+
+void Requirement::negate()
+{
+    switch (op)
+    {
+    case AttributeOperator::Equals:
+        op = AttributeOperator::NotEquals;
+        break;
+    case AttributeOperator::NotEquals:
+        op = AttributeOperator::Equals;
+        break;
+    case AttributeOperator::GreaterThan:
+        op = AttributeOperator::LessThanOrEquals;
+        break;
+    case AttributeOperator::GreaterThanOrEquals:
+        op = AttributeOperator::LessThan;
+        break;
+    case AttributeOperator::LessThan:
+        op = AttributeOperator::GreaterThanOrEquals;
+        break;
+    case AttributeOperator::LessThanOrEquals:
+        op = AttributeOperator::GreaterThan;
+        break;
+    }
+}
+
+Requirement* Requirement::clone()
+{
+    return new Requirement(attribute, value, op);
+}
+
+bool Requirement::contradicts(Requirement* zOther)
+{
+    if (zOther->attribute.istGleich(attribute.getText()))
+    {
+        if (zOther->value.istGleich(value))
+        {
+            if (op == AttributeOperator::Equals
+                && zOther->op == AttributeOperator::NotEquals)
+            {
+                return 1;
+            }
+            if (op == AttributeOperator::NotEquals
+                && zOther->op == AttributeOperator::Equals)
+            {
+                return 1;
+            }
+            if (op == AttributeOperator::GreaterThan
+                && zOther->op == AttributeOperator::LessThan)
+            {
+                return 1;
+            }
+            if (op == AttributeOperator::LessThan
+                && zOther->op == AttributeOperator::GreaterThan)
+            {
+                return 1;
+            }
+        }
+        if (op == AttributeOperator::LessThan
+            || op == AttributeOperator::LessThanOrEquals
+            || op == AttributeOperator::GreaterThan
+            || op == AttributeOperator::GreaterThanOrEquals)
+        {
+            double v1 = (double)value;
+            double v2 = (double)zOther->value;
+            if (op == AttributeOperator::LessThan
+                || op == AttributeOperator::LessThanOrEquals)
+            {
+                if (v1 < v2)
+                {
+                    if (zOther->op == AttributeOperator::GreaterThan
+                        || zOther->op == AttributeOperator::GreaterThanOrEquals
+                        || zOther->op == AttributeOperator::Equals)
+                    {
+                        return 1;
+                    }
+                }
+            }
+            else if (op == AttributeOperator::GreaterThan
+                     || op == AttributeOperator::GreaterThanOrEquals)
+            {
+                if (v1 > v2)
+                {
+                    if (zOther->op == AttributeOperator::LessThan
+                        || zOther->op == AttributeOperator::LessThanOrEquals
+                        || zOther->op == AttributeOperator::Equals)
+                    {
+                        return 1;
+                    }
+                }
+            }
+        }
+        if (zOther->op == AttributeOperator::LessThan
+            || zOther->op == AttributeOperator::LessThanOrEquals
+            || zOther->op == AttributeOperator::GreaterThan
+            || zOther->op == AttributeOperator::GreaterThanOrEquals)
+        {
+            double v1 = (double)zOther->value;
+            double v2 = (double)value;
+            if (zOther->op == AttributeOperator::LessThan
+                || zOther->op == AttributeOperator::LessThanOrEquals)
+            {
+                if (v1 < v2)
+                {
+                    if (op == AttributeOperator::GreaterThan
+                        || op == AttributeOperator::GreaterThanOrEquals
+                        || op == AttributeOperator::Equals)
+                    {
+                        return 1;
+                    }
+                }
+            }
+            else if (zOther->op == AttributeOperator::GreaterThan
+                     || zOther->op == AttributeOperator::GreaterThanOrEquals)
+            {
+                if (v1 > v2)
+                {
+                    if (op == AttributeOperator::LessThan
+                        || op == AttributeOperator::LessThanOrEquals
+                        || op == AttributeOperator::Equals)
+                    {
+                        return 1;
+                    }
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+bool Requirement::merge(Requirement* zOther)
+{
+    if (zOther->attribute.istGleich(attribute.getText()))
+    {
+        if (zOther->value.istGleich(value))
+        {
+            if (op == zOther->op)
+            {
+                return 1;
+            }
+        }
+        else
+        {
+            if (op == AttributeOperator::Equals
+                && zOther->op == AttributeOperator::NotEquals)
+            {
+                return 1;
+            }
+            if (op == AttributeOperator::NotEquals
+                && zOther->op == AttributeOperator::Equals)
+            {
+                op = AttributeOperator::Equals;
+                value = zOther->value;
+                return 1;
+            }
+        }
+        if (op == AttributeOperator::LessThan
+            || op == AttributeOperator::LessThanOrEquals
+            || op == AttributeOperator::GreaterThan
+            || op == AttributeOperator::GreaterThanOrEquals)
+        {
+            double v1 = (double)value;
+            double v2 = (double)zOther->value;
+            if (op == AttributeOperator::LessThan
+                || op == AttributeOperator::LessThanOrEquals)
+            {
+                if (zOther->op == AttributeOperator::LessThan
+                    || zOther->op == AttributeOperator::LessThanOrEquals)
+                {
+                    if (v1 > v2
+                        || (v1 == v2
+                            && op == AttributeOperator::LessThanOrEquals))
+                    {
+                        op = zOther->op;
+                        value = zOther->value;
+                    }
+                    return 1;
+                }
+                if (zOther->op == AttributeOperator::Equals)
+                {
+                    if (v2 < v1
+                        || (v2 == v1
+                            && op == AttributeOperator::LessThanOrEquals))
+                    {
+                        op = zOther->op;
+                        value = zOther->value;
+                        return 1;
+                    }
+                }
+                if (zOther->op == AttributeOperator::NotEquals)
+                {
+                    if (v2 > v1
+                        || (v2 == v1 && op == AttributeOperator::LessThan))
+                    {
+                        return 1;
+                    }
+                }
+            }
+            else if (op == AttributeOperator::GreaterThan
+                     || op == AttributeOperator::GreaterThanOrEquals)
+            {
+                if (zOther->op == AttributeOperator::GreaterThan
+                    || zOther->op == AttributeOperator::GreaterThanOrEquals)
+                {
+                    if (v1 < v2
+                        || (v1 == v2
+                            && op == AttributeOperator::GreaterThanOrEquals))
+                    {
+                        op = zOther->op;
+                        value = zOther->value;
+                    }
+                    return 1;
+                }
+                if (zOther->op == AttributeOperator::Equals)
+                {
+                    if (v2 > v1
+                        || (v2 == v1
+                            && op == AttributeOperator::GreaterThanOrEquals))
+                    {
+                        op = zOther->op;
+                        value = zOther->value;
+                        return 1;
+                    }
+                }
+                if (zOther->op == AttributeOperator::NotEquals)
+                {
+                    if (v2 < v1
+                        || (v2 == v1 && op == AttributeOperator::GreaterThan))
+                    {
+                        return 1;
+                    }
+                }
+            }
+        }
+        if (zOther->op == AttributeOperator::LessThan
+            || zOther->op == AttributeOperator::LessThanOrEquals
+            || zOther->op == AttributeOperator::GreaterThan
+            || zOther->op == AttributeOperator::GreaterThanOrEquals)
+        {
+            double v1 = (double)zOther->value;
+            double v2 = (double)value;
+            if (zOther->op == AttributeOperator::LessThan
+                || zOther->op == AttributeOperator::LessThanOrEquals)
+            {
+                if (op == AttributeOperator::Equals)
+                {
+                    if (v2 < v1
+                        || (v2 == v1
+                            && zOther->op
+                                   == AttributeOperator::LessThanOrEquals))
+                    {
+                        return 1;
+                    }
+                }
+                if (op == AttributeOperator::NotEquals)
+                {
+                    if (v2 > v1
+                        || (v2 == v1
+                            && zOther->op == AttributeOperator::LessThan))
+                    {
+                        op = zOther->op;
+                        value = zOther->value;
+                        return 1;
+                    }
+                }
+            }
+            else if (zOther->op == AttributeOperator::GreaterThan
+                     || zOther->op == AttributeOperator::GreaterThanOrEquals)
+            {
+                if (op == AttributeOperator::Equals)
+                {
+                    if (v2 > v1
+                        || (v2 == v1
+                            && zOther->op
+                                   == AttributeOperator::GreaterThanOrEquals))
+                    {
+                        return 1;
+                    }
+                }
+                if (op == AttributeOperator::NotEquals)
+                {
+                    if (v2 < v1
+                        || (v2 == v1
+                            && zOther->op == AttributeOperator::GreaterThan))
+                    {
+                        op = zOther->op;
+                        value = zOther->value;
+                        return 1;
+                    }
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+int Requirement::getItemType()
+{
+    if (attribute.istGleich("Type") && op == AttributeOperator::Equals)
+    {
+        return (int)value;
+    }
+    return -1;
+}
+
+Framework::Text Requirement::getDescription()
+{
+    Framework::Text result = attribute;
+    result += " ";
+    switch (op)
+    {
+    case AttributeOperator::Equals:
+        result += "is";
+        break;
+    case AttributeOperator::NotEquals:
+        result += "is not";
+        break;
+    case AttributeOperator::LessThan:
+        result += "is less than";
+        break;
+    case AttributeOperator::LessThanOrEquals:
+        result += "is less than or equal to";
+        break;
+    case AttributeOperator::GreaterThan:
+        result += "is greater than";
+        break;
+    case AttributeOperator::GreaterThanOrEquals:
+        result += "is greater than or equal to";
+        break;
+    }
+    result += " ";
+    result += value;
+    return result;
+}
+
+RequirementSet::RequirementSet()
+    : Framework::ReferenceCounter()
+{}
+
+void RequirementSet::addRequirement(Requirement* zReq)
+{
+    for (Requirement* req : requirements)
+    {
+        if (req->merge(zReq)) return;
+    }
+    requirements.add(zReq->clone());
+}
+
+RequirementSet* RequirementSet::clone()
+{
+    RequirementSet* result = new RequirementSet();
+    for (Requirement* req : requirements)
+    {
+        result->requirements.add(req->clone());
+    }
+    return result;
+}
+
+void RequirementSet::addRequirements(RequirementSet* zOther)
+{
+    for (Requirement* req : zOther->requirements)
+    {
+        addRequirement(req);
+    }
+}
+
+void RequirementSet::negate(LogicTree* zNode)
+{
+    for (Requirement* req : requirements)
+    {
+        Requirement* negate = req->clone();
+        negate->negate();
+        RequirementSet* set = new RequirementSet();
+        set->addRequirement(negate);
+        negate->release();
+        zNode->addChildren(new LogicTree(LogicalOperator::OR, set));
+    }
+}
+
+bool RequirementSet::isNoneMatch() const
+{
+    for (Requirement* req : requirements)
+    {
+        for (Requirement* req2 : requirements)
+        {
+            if (req != req2)
+            {
+                if (req->contradicts(req2))
+                {
+                    return 1;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+bool RequirementSet::isAnyMatch() const
+{
+    return requirements.getEintragAnzahl() == 0;
+}
+
+Framework::Text RequirementSet::renderToTooltip() const
+{
+    int itemType = -1;
+    for (Requirement* req : requirements)
+    {
+        int rT = req->getItemType();
+        if (rT != -1)
+        {
+            if (itemType == -1)
+            {
+                itemType = rT;
+            }
+            else if (itemType != rT)
+            {
+                itemType = -2;
+            }
+        }
+    }
+    Framework::Text result = "";
+    if (itemType == -2)
+    {
+        return "No Item matches this filter";
+    }
+    else if (itemType == -1)
+    {
+        result += "Any Item";
+    }
+    else
+    {
+        result += zItemType(itemType)->getName();
+    }
+    if (requirements.getEintragAnzahl() > 0)
+    {
+        bool first = 1;
+        for (Requirement* req : requirements)
+        {
+            if (req->getItemType() == -1)
+            {
+                if (first)
+                {
+                    result += ":\n";
+                    first = 0;
+                }
+                result += "  ";
+                result += req->getDescription();
+                result += "\n";
+            }
+        }
+    }
+    return result;
+}
+
+Framework::Bild* RequirementSet::getIcon() const
+{
+    int itemType = -1;
+    for (Requirement* req : requirements)
+    {
+        int rT = req->getItemType();
+        if (rT != -1)
+        {
+            if (itemType == -1)
+            {
+                itemType = rT;
+            }
+            else if (itemType != rT)
+            {
+                itemType = -2;
+            }
+        }
+    }
+    if (itemType == -2)
+    {
+        LTDBDatei dat;
+        dat.setDatei(new Text("data/bilder/gui_icons.ltdb"));
+        dat.leseDaten(0);
+        return dat.laden(0, new Text("noitem.png"));
+    }
+    else if (itemType == -1)
+    {
+        LTDBDatei dat;
+        dat.setDatei(new Text("data/images/gui_icons.ltdb"));
+        dat.leseDaten(0);
+        return dat.laden(0, new Text("anyitem.png"));
+    }
+    else
+    {
+        return dynamic_cast<Framework::Bild*>(
+            zItemType(itemType)->zIcon()->getThis());
+    }
+}
+
+int RequirementSet::getItemType() const
+{
+    int itemType = -1;
+    for (Requirement* req : requirements)
+    {
+        int rT = req->getItemType();
+        if (rT != -1)
+        {
+            if (itemType == -1)
+            {
+                itemType = rT;
+            }
+            else if (itemType != rT)
+            {
+                itemType = -2;
+            }
+        }
+    }
+    return itemType;
+}
+
+LogicTree::LogicTree(LogicalOperator op, RequirementSet* set)
+    : Framework::ReferenceCounter(),
+      op(op),
+      requirementSet(set)
+{}
+
+LogicTree::~LogicTree()
+{
+    if (requirementSet) requirementSet->release();
+}
+
+Framework::RCArray<RequirementSet>* LogicTree::multiply(
+    Framework::RCArray<RequirementSet>* a,
+    Framework::RCArray<RequirementSet>* b)
+{
+    Framework::RCArray<RequirementSet>* result
+        = new Framework::RCArray<RequirementSet>();
+    for (RequirementSet* aSet : *a)
+    {
+        for (RequirementSet* bSet : *b)
+        {
+            RequirementSet* set = aSet->clone();
+            set->addRequirements(bSet);
+            if (!set->isNoneMatch())
+            {
+                if (set->isAnyMatch())
+                {
+                    result->leeren();
+                    result->add(set);
+                    a->release();
+                    b->release();
+                    return result;
+                }
+                else
+                {
+                    result->add(set);
+                }
+            }
+            else
+            {
+                set->release();
+            }
+        }
+    }
+    return result;
+}
+
+void LogicTree::addChildren(LogicTree* tree)
+{
+    children.add(tree);
+}
+
+LogicTree* LogicTree::clone()
+{
+    LogicTree* result = new LogicTree(op, requirementSet->clone());
+    for (LogicTree* child : children)
+    {
+        result->children.add(child->clone());
+    }
+    return result;
+}
+
+void LogicTree::negate()
+{
+    if (requirementSet != 0)
+    {
+        requirementSet->negate(this);
+        requirementSet->release();
+        requirementSet = 0;
+    }
+    else
+    {
+        if (op == LogicalOperator::AND)
+        {
+            op = LogicalOperator::OR;
+        }
+        else if (op == LogicalOperator::OR)
+        {
+            op = LogicalOperator::AND;
+        }
+        for (LogicTree* child : children)
+        {
+            child->negate();
+        }
+    }
+}
+
+Framework::RCArray<RequirementSet>* LogicTree::resolve()
+{
+    if (requirementSet != 0)
+    {
+        Framework::RCArray<RequirementSet>* result
+            = new Framework::RCArray<RequirementSet>();
+        result->add(dynamic_cast<RequirementSet*>(requirementSet->getThis()));
+        return result;
+    }
+    else
+    {
+        Framework::RCArray<RequirementSet>* result = 0;
+        if (op == LogicalOperator::OR)
+        {
+            result = new Framework::RCArray<RequirementSet>();
+            for (LogicTree* child : children)
+            {
+                Framework::RCArray<RequirementSet>* childSet = child->resolve();
+                for (RequirementSet* set : *childSet)
+                {
+                    result->add(dynamic_cast<RequirementSet*>(set->getThis()));
+                }
+                childSet->release();
+            }
+        }
+        else if (op == LogicalOperator::AND)
+        {
+            result = children.z(0)->resolve();
+            for (int i = 1; i < children.getEintragAnzahl(); i++)
+            {
+                Framework::RCArray<RequirementSet>* childSet
+                    = children.z(i)->resolve();
+                result = multiply(result, childSet);
+            }
+        }
+        if (result != 0)
+        {
+            for (int i = 0; i < result->getEintragAnzahl(); i++)
+            {
+                if (result->z(i)->isNoneMatch())
+                {
+                    result->remove(i);
+                    i--;
+                }
+                else if (result->z(i)->isAnyMatch())
+                {
+                    Framework::RCArray<RequirementSet>* anyMatch
+                        = new Framework::RCArray<RequirementSet>();
+                    anyMatch->add(result->get(i));
+                    result->release();
+                    return anyMatch;
+                }
+            }
+        }
+        return result;
+    }
+}

+ 126 - 0
FactoryCraft/RecipieIngredient.h

@@ -0,0 +1,126 @@
+#pragma once
+
+#include <UIMLView.h>
+#include <TextFeld.h> 
+
+class LogicTree;
+
+class RecipieIngredientElement : public Framework::UIMLElement
+{
+private:
+    LogicTree* parse(Framework::XML::Element* zElement);
+
+public:
+    RecipieIngredientElement();
+    //! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
+    //! ist
+    bool isApplicableFor(Framework::XML::Element& element) override;
+    //! erstellt eine neue Zeichnung zu einem gegebenen xml Element
+    Framework::Zeichnung* parseElement(Framework::XML::Element& element,
+        Framework::UIMLContainer& generalFactory) override;
+    //! wendet die layout parameter zu einer Zeichnung an
+    void layout(Framework::XML::Element& element,
+        Framework::Zeichnung& z,
+        int pWidth,
+        int pHeight,
+        Framework::UIMLContainer& generalLayouter) override;
+};
+
+class RecipieIngredient : public Framework::ZeichnungHintergrund
+{
+private:
+    Framework::RCArray<Framework::Bild> icons;
+    Framework::RCArray<Framework::Text> toolTips;
+    Framework::Array<int> itemTypes;
+    Framework::TextFeld* toolTip;
+    int currentIconIndex;
+    double timtUntilNextIcon;
+    int amount;
+
+public:
+    RecipieIngredient(int amount);
+
+    void addPossibleItem(Framework::Bild* icon, Framework::Text* toolTip, int itemType);
+
+    bool tick(double tickVal) override;
+    void render(Framework::Bild& rObj) override;
+    void doMausEreignis(Framework::MausEreignis& me, bool userRet) override;
+};
+
+enum class AttributeOperator
+{
+    Equals,
+    NotEquals,
+    GreaterThan,
+    GreaterThanOrEquals,
+    LessThan,
+    LessThanOrEquals
+};
+
+class Requirement : public Framework::ReferenceCounter
+{
+private:
+    Framework::Text attribute;
+    Framework::Text value;
+    AttributeOperator op;
+
+public:
+    Requirement(
+        Framework::Text attribute, Framework::Text value, AttributeOperator op);
+    
+    void negate();
+    Requirement* clone();
+    bool contradicts(Requirement* zOther);
+    bool merge(Requirement* zOther);
+    int getItemType();
+    Framework::Text getDescription();
+};
+
+class RequirementSet : public Framework::ReferenceCounter
+{
+private:
+    Framework::RCArray<Requirement> requirements;
+
+public:
+    RequirementSet();
+    
+    void addRequirement(Requirement* zReq);
+    RequirementSet* clone();
+    void addRequirements(RequirementSet* zOther);
+
+    void negate(LogicTree* zNode);
+
+    bool isNoneMatch() const;
+    bool isAnyMatch() const;
+    Framework::Text renderToTooltip() const;
+    Framework::Bild* getIcon() const;
+    int getItemType() const;
+};
+
+enum class LogicalOperator
+{
+    AND,
+    OR
+};
+
+class LogicTree : public Framework::ReferenceCounter
+{
+private:
+    LogicalOperator op;
+    RequirementSet *requirementSet;
+    Framework::RCArray<LogicTree> children;
+
+    Framework::RCArray<RequirementSet>* multiply(
+        Framework::RCArray<RequirementSet>* a,
+        Framework::RCArray<RequirementSet>* b);
+
+public:
+    LogicTree(LogicalOperator op, RequirementSet *set);
+    ~LogicTree();
+
+    void addChildren(LogicTree* tree);
+
+    LogicTree* clone();
+    void negate();
+    Framework::RCArray<RequirementSet> *resolve();
+};

+ 64 - 0
FactoryCraft/RecipieOutput.cpp

@@ -0,0 +1,64 @@
+#include "RecipieOutput.h"
+
+#include <XML.h>
+
+#include "Globals.h"
+#include "UIMLToolTip.h"
+
+RecipieOutputElement::RecipieOutputElement()
+    : Framework::UIMLElement()
+{}
+
+//! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
+//! ist
+bool RecipieOutputElement::isApplicableFor(Framework::XML::Element& element)
+{
+    return element.getName().istGleich("output");
+}
+
+//! erstellt eine neue Zeichnung zu einem gegebenen xml Element
+Framework::Zeichnung* RecipieOutputElement::parseElement(
+    Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
+{
+    SlotInfo info;
+    info.itemCount = (int)element.getAttributeValue("amount");
+    int itemType = (int)element.getAttributeValue("itemType");
+    info.hp = (float)(double)element.getAttributeValue("hp");
+    info.maxHp = (float)(double)element.getAttributeValue("maxHp");
+    info.durability = (float)(double)element.getAttributeValue("durability");
+    info.maxDurability
+        = (float)(double)element.getAttributeValue("maxDurability");
+    info.zItem = zItemType(itemType)->zIcon();
+    return new RecipieOutput(info, element.zChild(0)->toString());
+}
+
+//! wendet die layout parameter zu einer Zeichnung an
+void RecipieOutputElement::layout(Framework::XML::Element& element,
+    Framework::Zeichnung& z,
+    int pWidth,
+    int pHeight,
+    Framework::UIMLContainer& generalLayouter)
+{
+    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
+    z.setWidth(50);
+    z.setHeight(50);
+}
+
+RecipieOutput::RecipieOutput(SlotInfo info, Framework::Text toolTipUIML)
+    : info(info)
+{
+    setStyle(Framework::Zeichnung::Style::Erlaubt
+             | Framework::Zeichnung::Style::Sichtbar);
+    UIMLToolTip* tip = new UIMLToolTip();
+    tip->setUIML(toolTipUIML);
+    tip->setWarten(0.5);
+    setToolTipZ(tip);
+}
+
+void RecipieOutput::render(Framework::Bild& rObj)
+{
+    ZeichnungHintergrund::render(rObj);
+    if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return;
+    info.render(-1, -1, rObj, 0, 0);
+    rObj.releaseDrawOptions();
+}

+ 33 - 0
FactoryCraft/RecipieOutput.h

@@ -0,0 +1,33 @@
+#pragma once
+
+#include <UIMLView.h>
+
+#include "InventoryView.h"
+
+class RecipieOutputElement : public Framework::UIMLElement
+{
+public:
+    RecipieOutputElement();
+    //! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
+    //! ist
+    bool isApplicableFor(Framework::XML::Element& element) override;
+    //! erstellt eine neue Zeichnung zu einem gegebenen xml Element
+    Framework::Zeichnung* parseElement(Framework::XML::Element& element,
+        Framework::UIMLContainer& generalFactory) override;
+    //! wendet die layout parameter zu einer Zeichnung an
+    void layout(Framework::XML::Element& element,
+        Framework::Zeichnung& z,
+        int pWidth,
+        int pHeight,
+        Framework::UIMLContainer& generalLayouter) override;
+};
+
+class RecipieOutput : public Framework::ZeichnungHintergrund
+{
+private:
+    SlotInfo info;
+
+public:
+    RecipieOutput(SlotInfo info, Framework::Text toolTipUIML);
+    void render(Framework::Bild& rObj) override;
+};

+ 164 - 0
FactoryCraft/ShapedRecipie.cpp

@@ -0,0 +1,164 @@
+#include "ShapedRecipie.h"
+
+#include <Bild.h>
+#include <XML.h>
+
+ShapedRecipieElement::ShapedRecipieElement()
+    : Framework::UIMLElement()
+{}
+
+//! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
+//! ist
+bool ShapedRecipieElement::isApplicableFor(Framework::XML::Element& element)
+{
+    return element.getName().istGleich("recipie")
+        && element.getAttributeValue("type").istGleich("shaped");
+}
+
+//! erstellt eine neue Zeichnung zu einem gegebenen xml Element
+Framework::Zeichnung* ShapedRecipieElement::parseElement(
+    Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
+{
+    int width = (int)element.getAttributeValue("width");
+    int height = (int)element.getAttributeValue("height");
+    ShapedRecipie* recipie = new ShapedRecipie(width, height);
+
+    element.selectChildsByName("ingredients")
+        .selectChildren()
+        .forEach([recipie, &generalFactory](Framework::XML::Element* zElement) {
+            recipie->addIngredient(
+                generalFactory.parseElement(*zElement, generalFactory));
+        });
+
+    element.selectChildsByName("outputs").selectChildren().forEach(
+        [recipie, &generalFactory](Framework::XML::Element* zElement) {
+            recipie->addOutput(
+                generalFactory.parseElement(*zElement, generalFactory));
+        });
+
+    return recipie;
+}
+
+//! wendet die layout parameter zu einer Zeichnung an
+void ShapedRecipieElement::layout(Framework::XML::Element& element,
+    Framework::Zeichnung& z,
+    int pWidth,
+    int pHeight,
+    Framework::UIMLContainer& generalLayouter)
+{
+    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
+    int width = (int)element.getAttributeValue("width");
+    int height = (int)element.getAttributeValue("height");
+    int outputs
+        = element.selectChildsByName("outputs").selectChildren().getSize();
+    int outputCols = outputs / height;
+    if (outputs % height != 0)
+    {
+        outputCols++;
+    }
+    if (outputCols == 0)
+    {
+        outputCols = 1;
+    }
+    z.setWidth(width * 60 + 50 + outputCols * 60 - 10);
+    z.setHeight(height * 60 - 10);
+    element.selectChildren()
+        .selectChildren()
+        .forEach([&z, &generalLayouter](Framework::XML::Element* zElement) {
+            Framework::Zeichnung* child = 0;
+            if (zElement->hasAttribute("id"))
+            {
+                child = generalLayouter.zZeichnungById(
+                    zElement->getAttributeValue("id"));
+            }
+            if (child)
+            {
+                generalLayouter.layout(*zElement,
+                    *child,
+                    z.getBreite(),
+                    z.getHeight(),
+                    generalLayouter);
+            }
+        });
+}
+
+ShapedRecipie::ShapedRecipie(int width, int height)
+    : Framework::ZeichnungHintergrund(),
+      width(width),
+      height(height)
+{
+    setStyle(Framework::Zeichnung::Style::Erlaubt
+             | Framework::Zeichnung::Style::Sichtbar);
+}
+
+void ShapedRecipie::addIngredient(Zeichnung* ingredient)
+{
+    ingredients.add(ingredient);
+}
+
+void ShapedRecipie::addOutput(Zeichnung* output)
+{
+    outputs.add(output);
+}
+
+bool ShapedRecipie::tick(double tickVal)
+{
+    bool ret = false;
+    for (Zeichnung* ingredient : ingredients)
+    {
+        ret |= ingredient->tick(tickVal);
+    }
+    for (Zeichnung* output : outputs)
+    {
+        ret |= output->tick(tickVal);
+    }
+    return ret;
+}
+
+void ShapedRecipie::render(Framework::Bild& rObj)
+{
+    if (!hatStyle(Zeichnung::Style::Sichtbar)) return;
+    ZeichnungHintergrund::render(rObj);
+    if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return;
+    int x = 0;
+    int y = 0;
+    for (Zeichnung* ingredient : ingredients)
+    {
+        ingredient->setX(x);
+        ingredient->setY(y);
+        ingredient->render(rObj);
+        x += 60;
+        if (x >= width * 60)
+        {
+            x = 0;
+            y += 60;
+        }
+    }
+    rObj.fillRegion(width * 60, gr.y / 2 - 5, 25, 10, 0xFF52525E);
+    rObj.drawDreieck(Framework::Punkt(width * 60 + 25, gr.y / 2 - 15),
+        Framework::Punkt(width * 60 + 40, gr.y / 2),
+        Framework::Punkt(width * 60 + 25, gr.y / 2 + 15),
+        0xFF52525E);
+    x = width * 60 + 50;
+    y = 0;
+    for (Zeichnung* output : outputs)
+    {
+        output->setX(x);
+        output->setY(y);
+        output->render(rObj);
+        y += 60;
+    }
+    rObj.releaseDrawOptions();
+}
+
+void ShapedRecipie::doMausEreignis(Framework::MausEreignis& me, bool userRet)
+{
+    for (Zeichnung* ingredient : ingredients)
+    {
+        ingredient->doPublicMausEreignis(me);
+    }
+    for (Zeichnung* output : outputs)
+    {
+        output->doPublicMausEreignis(me);
+    }
+}

+ 39 - 0
FactoryCraft/ShapedRecipie.h

@@ -0,0 +1,39 @@
+#pragma once
+
+#include <UIMLView.h>
+
+class ShapedRecipieElement : public Framework::UIMLElement
+{
+public:
+    ShapedRecipieElement();
+    //! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
+    //! ist
+    bool isApplicableFor(Framework::XML::Element& element) override;
+    //! erstellt eine neue Zeichnung zu einem gegebenen xml Element
+    Framework::Zeichnung* parseElement(Framework::XML::Element& element,
+        Framework::UIMLContainer& generalFactory) override;
+    //! wendet die layout parameter zu einer Zeichnung an
+    void layout(Framework::XML::Element& element,
+        Framework::Zeichnung& z,
+        int pWidth,
+        int pHeight,
+        Framework::UIMLContainer& generalLayouter) override;
+};
+
+
+class ShapedRecipie : public Framework::ZeichnungHintergrund
+{
+private:
+    Framework::RCArray<Zeichnung> ingredients;
+    Framework::RCArray<Zeichnung> outputs;
+    int width;
+    int height;
+
+public:
+    ShapedRecipie(int width, int height);
+    void addIngredient(Zeichnung* ingredient);
+    void addOutput(Zeichnung* output);
+    bool tick(double tickVal) override;
+    void render(Framework::Bild& rObj) override;
+    void doMausEreignis(Framework::MausEreignis& me, bool userRet) override;
+};

+ 151 - 0
FactoryCraft/UnshapedRecipie.cpp

@@ -0,0 +1,151 @@
+#include "UnshapedRecipie.h"
+
+#include <Bild.h>
+#include <XML.h>
+
+UnshapedRecipieElement::UnshapedRecipieElement()
+    : Framework::UIMLElement()
+{}
+
+//! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
+//! ist
+bool UnshapedRecipieElement::isApplicableFor(Framework::XML::Element& element)
+{
+    return element.getName().istGleich("recipie")
+        && element.getAttributeValue("type").istGleich("unshaped");
+}
+
+//! erstellt eine neue Zeichnung zu einem gegebenen xml Element
+Framework::Zeichnung* UnshapedRecipieElement::parseElement(
+    Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
+{
+    UnshapedRecipie* recipie = new UnshapedRecipie();
+
+    element.selectChildsByName("ingredients")
+        .selectChildren()
+        .forEach([recipie, &generalFactory](Framework::XML::Element* zElement) {
+            recipie->addIngredient(
+                generalFactory.parseElement(*zElement, generalFactory));
+        });
+
+    element.selectChildsByName("outputs").selectChildren().forEach(
+        [recipie, &generalFactory](Framework::XML::Element* zElement) {
+            recipie->addOutput(
+                generalFactory.parseElement(*zElement, generalFactory));
+        });
+
+    return recipie;
+}
+
+//! wendet die layout parameter zu einer Zeichnung an
+void UnshapedRecipieElement::layout(Framework::XML::Element& element,
+    Framework::Zeichnung& z,
+    int pWidth,
+    int pHeight,
+    Framework::UIMLContainer& generalLayouter)
+{
+    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
+    element.selectChildren().selectChildren().forEach(
+        [&z, &generalLayouter](Framework::XML::Element* zElement) {
+            Framework::Zeichnung* child = 0;
+            if (zElement->hasAttribute("id"))
+            {
+                child = generalLayouter.zZeichnungById(
+                    zElement->getAttributeValue("id"));
+            }
+            if (child)
+            {
+                generalLayouter.layout(*zElement,
+                    *child,
+                    z.getBreite(),
+                    z.getHeight(),
+                    generalLayouter);
+            }
+        });
+}
+
+UnshapedRecipie::UnshapedRecipie()
+    : Framework::ZeichnungHintergrund()
+{
+    setStyle(Framework::Zeichnung::Style::Erlaubt
+             | Framework::Zeichnung::Style::Sichtbar);
+}
+
+void UnshapedRecipie::addIngredient(Zeichnung* ingredient)
+{
+    ingredients.add(ingredient);
+}
+
+void UnshapedRecipie::addOutput(Zeichnung* output)
+{
+    outputs.add(output);
+}
+
+bool UnshapedRecipie::tick(double tickVal)
+{
+    bool ret = false;
+    for (Zeichnung* ingredient : ingredients)
+    {
+        ret |= ingredient->tick(tickVal);
+    }
+    for (Zeichnung* output : outputs)
+    {
+        ret |= output->tick(tickVal);
+    }
+    return ret;
+}
+
+void UnshapedRecipie::render(Framework::Bild& rObj)
+{
+    if (!hatStyle(Zeichnung::Style::Sichtbar)) return;
+    ZeichnungHintergrund::render(rObj);
+    if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return;
+    int x = 0;
+    int y = 0;
+    int width = MIN(3, ingredients.getEintragAnzahl());
+    for (Zeichnung* ingredient : ingredients)
+    {
+        ingredient->setX(x);
+        ingredient->setY(y);
+        ingredient->render(rObj);
+        x += 60;
+        if (x >= 3 * 60)
+        {
+            x = 0;
+            y += 60;
+        }
+    }
+    rObj.fillRegion(width * 60, gr.y / 2 - 5, 25, 10, 0xFF52525E);
+    rObj.drawDreieck(Framework::Punkt(3 * 60 + 25, gr.y / 2 - 15),
+        Framework::Punkt(width * 60 + 40, gr.y / 2),
+        Framework::Punkt(width * 60 + 25, gr.y / 2 + 15),
+        0xFF52525E);
+    x = width * 60 + 50;
+    int oldy = y;
+    y = 0;
+    for (Zeichnung* output : outputs)
+    {
+        output->setX(x);
+        output->setY(y);
+        output->render(rObj);
+        y += 60;
+    }
+    int height = MAX(3, outputs.getEintragAnzahl());
+    if (getBreite() != width * 60 + 50 + 50 && getHeight() != height)
+    {
+        setSize(width * 60 + 50 + 50, MAX(oldy + 50, y + 50));
+    }
+    rObj.releaseDrawOptions();
+}
+
+void UnshapedRecipie::doMausEreignis(Framework::MausEreignis& me, bool userRet)
+{
+    for (Zeichnung* ingredient : ingredients)
+    {
+        ingredient->doPublicMausEreignis(me);
+    }
+    for (Zeichnung* output : outputs)
+    {
+        output->doPublicMausEreignis(me);
+    }
+}

+ 37 - 0
FactoryCraft/UnshapedRecipie.h

@@ -0,0 +1,37 @@
+#pragma once
+
+#include <UIMLView.h>
+
+class UnshapedRecipieElement : public Framework::UIMLElement
+{
+public:
+    UnshapedRecipieElement();
+    //! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
+    //! ist
+    bool isApplicableFor(Framework::XML::Element& element) override;
+    //! erstellt eine neue Zeichnung zu einem gegebenen xml Element
+    Framework::Zeichnung* parseElement(Framework::XML::Element& element,
+        Framework::UIMLContainer& generalFactory) override;
+    //! wendet die layout parameter zu einer Zeichnung an
+    void layout(Framework::XML::Element& element,
+        Framework::Zeichnung& z,
+        int pWidth,
+        int pHeight,
+        Framework::UIMLContainer& generalLayouter) override;
+};
+
+
+class UnshapedRecipie : public Framework::ZeichnungHintergrund
+{
+private:
+    Framework::RCArray<Zeichnung> ingredients;
+    Framework::RCArray<Zeichnung> outputs;
+
+public:
+    UnshapedRecipie();
+    void addIngredient(Zeichnung* ingredient);
+    void addOutput(Zeichnung* output);
+    bool tick(double tickVal) override;
+    void render(Framework::Bild& rObj) override;
+    void doMausEreignis(Framework::MausEreignis& me, bool userRet) override;
+};