48 #define MenuDebugLogF(...) ((void)0) 
   54 float C4ScriptGuiWindow::Em2Pix(
float em)
 
   59 float C4ScriptGuiWindow::Pix2Em(
float pix)
 
   98         assert(
false && 
"trying to save C4ScriptGuiWindowAction without valid action");
 
  106     if (!first || !nextAction) 
return C4Value(array);
 
  121         container->
SetItem(size - 1, val);
 
  122         next = next->nextAction;
 
  131     if (targetObj == pObj)
 
  149         if (index+1 < array->
GetSize())
 
  152             nextAction->
Init(array, index + 1);
 
  156         if (!array) 
return false;
 
  169         if (array->
GetSize() < 3) 
return false;
 
  172         if (!target || !text) 
return false;
 
  187         if (array->
GetSize() < 4) 
return false;
 
  189         if (!text) 
return false;
 
  205     assert(parent && 
"C4ScriptGuiWindow::Execute must always be called with parent");
 
  206     MenuDebugLogF(
"Excuting action (nextAction: %x, subwID: %d, target: %x, text: %s, type: %d)", nextAction, subwindowID, target, text->
GetCStr(), actionType);
 
  214         while (!from->IsRoot())
 
  235             if (subwindowID == 0)
 
  237             else if (subwindowID > 0)
 
  240                 window = 
main->GetSubWindow(subwindowID, targetObj);
 
  248             assert(
false && 
"C4ScriptGuiWindowAction without valid or invalidated ID");
 
  261     MenuDebugLogF(
"checking action %d (==%d?)\t\tmy action: %d", 
id, actionID, action);
 
  263     if (
id == actionID && action)
 
  270         while (!from->IsRoot())
 
  290 void C4ScriptGuiWindowProperty::SetInt(int32_t to, 
C4String *tag)
 
  293     taggedProperties[tag] = Prop();
 
  294     current = &taggedProperties[tag];
 
  297 void C4ScriptGuiWindowProperty::SetFloat(
float to, 
C4String *tag)
 
  300     taggedProperties[tag] = Prop();
 
  301     current = &taggedProperties[tag];
 
  304 void C4ScriptGuiWindowProperty::SetNull(
C4String *tag)
 
  307     taggedProperties[tag] = Prop();
 
  308     current = &taggedProperties[tag];
 
  309     current->data = 
nullptr;
 
  312 void C4ScriptGuiWindowProperty::CleanUp(Prop &prop)
 
  317         if (prop.deco) 
delete prop.deco;
 
  323         if (prop.action) 
delete prop.action;
 
  328         if (prop.strBuf) 
delete prop.strBuf;
 
  335 void C4ScriptGuiWindowProperty::CleanUpAll()
 
  337     for (
auto & taggedProperty : taggedProperties)
 
  339         CleanUp(taggedProperty.second);
 
  341             taggedProperty.first->DecRef();
 
  349     bool onlyOneTag = taggedProperties.size() == 1;
 
  355     for(
auto & taggedProperty : taggedProperties)
 
  357         C4String *tagString = taggedProperty.first;
 
  358         const Prop &prop = taggedProperty.second;
 
  381             assert (
false && 
"Trying to get a single positional value from a GuiWindow for saving. Those should always be saved in pairs of two in a string.");
 
  401                 val = 
C4Value(prop.deco->pSourceDef);
 
  423                 val = prop.action->ToC4Value();
 
  427             assert(
false && 
"C4ScriptGuiWindowAction should never have undefined type");
 
  431         if (onlyOneTag) 
return val;
 
  442     bool isTaggedPropList = 
false;
 
  446     if (isTaggedPropList)
 
  448         std::unique_ptr<C4ValueArray> properties(proplist->
GetProperties());
 
  449         properties->SortStrings();
 
  450         for (int32_t i = 0; i < properties->GetSize(); ++i)
 
  452             const C4Value &entry = properties->GetItem(i);
 
  454             assert(key && 
"Proplist returns non-string as key");
 
  464     if (taggedProperties.count(tag))
 
  465         CleanUp(taggedProperties[tag]);
 
  470     taggedProperties[tag] = Prop();
 
  473     current = &taggedProperties[tag];
 
  496         assert (
false && 
"Trying to set positional properties directly. Those should always come parsed from a string.");
 
  502         current->d = value.
getInt();
 
  509             current->d = value.
getInt();
 
  517         else current->obj = 
nullptr;
 
  524             current->def = symbol->
GetDef();
 
  525         else current->def = 
nullptr;
 
  535             if (!current->deco->SetByDef(def))
 
  537                 delete current->deco;
 
  538                 current->deco = 
nullptr;
 
  552         current->strBuf = buf;
 
  563             assert (!current->action && 
"Prop() contains action prior to assignment");
 
  565             current->action->Init(array);
 
  571         assert(
false && 
"C4ScriptGuiWindowAction should never have undefined type");
 
  580     for (
auto & taggedProperty : taggedProperties)
 
  585             if (taggedProperty.second.obj == pObj)
 
  586                 taggedProperty.second.obj = 
nullptr;
 
  593             if (taggedProperty.second.action)
 
  594                 taggedProperty.second.action->ClearPointers(pObj);
 
  604     if (!taggedProperties.count(tag)) 
return false; 
 
  605     if (current == &taggedProperties[tag]) 
return false; 
 
  606     current = &taggedProperties[tag];
 
  613     std::list<C4ScriptGuiWindowAction*> allActions;
 
  614     for (
auto & taggedProperty : taggedProperties)
 
  616         Prop &p = taggedProperty.second;
 
  618             allActions.push_back(p.action);
 
  629 void C4ScriptGuiWindow::Init()
 
  634     isMainWindow = 
false;
 
  635     mainWindowNeedsLayoutUpdate = 
false;
 
  678     wasRemovedFromParent = 
false;
 
  693     for (
auto & prop : props)
 
  703 void C4ScriptGuiWindow::SetMarginProperties(
const C4Value &property, 
C4String *tag)
 
  708         C4PropList *proplist = 
property.getPropList();
 
  711             SetMarginProperties(iter->Value, iter->Key);
 
  721     for (
int i = 0; i < 4; ++i)
 
  749             int realIndex = i % array->
GetSize();
 
  750             SetPositionStringProperties(array->
GetItem(realIndex), relative, absolute, tag);
 
  754             SetPositionStringProperties(property, relative, absolute, tag);
 
  758 C4Value C4ScriptGuiWindow::MarginsToC4Value()
 
  777         C4PropList *proplist = 
property.getPropList();
 
  780             SetPositionStringProperties(iter->Value, relative, absolute, iter->Key);
 
  787             LogF(
"Warning: Got %s instead of expected menu format string.", property.
GetTypeName());
 
  791     float relativeValue = 0.0;
 
  792     float absoluteValue = 0.0;
 
  794     std::locale c_locale(
"C");
 
  795     std::istringstream reader(std::string(property.
getStr()->
GetCStr()));
 
  796     reader.imbue(c_locale);
 
  797     if(!reader.good()) 
return;
 
  799     while (!reader.eof())
 
  809         std::stringstream floatss;
 
  810         floatss.imbue(c_locale);
 
  811         if(reader.peek() == 
'+' || reader.peek() == 
'-') floatss.put(reader.get());
 
  813         while(std::isdigit(reader.peek()) || reader.peek() == 
'.') floatss.put(reader.get());
 
  817         if (reader.peek() == 
'%')
 
  819             relativeValue += value;
 
  822         else if (reader.get() == 
'e' && reader.get() == 
'm')
 
  824             absoluteValue += value;
 
  828             LogF(R
"(Warning: Could not parse menu format string "%s"!)", property.getStr()->GetCStr()); 
  834     props[relative].SetFloat(relativeValue / 100.0f, tag);
 
  835     props[absolute].SetFloat(absoluteValue, tag);
 
  847     const bool onlyStdTag = relative.taggedProperties.size() == 1;
 
  848     for (
auto & taggedProperty : relative.taggedProperties)
 
  850         C4String *tag = taggedProperty.first;
 
  852         buf.
Format(
"%f%%%+fem", 100.0f * taggedProperty.second.f, absolute.taggedProperties[tag].f);
 
  859             if (proplist == 
nullptr)
 
  916     for (
int prop : toSave)
 
  927 #define PROPERTY_TUPLE(p, prop1, prop2) if (prop == p) { val = PositionToC4Value(prop1, prop2); } 
  932 #undef PROPERTY_TUPLE 
  935         case P_Margin: val = MarginsToC4Value(); 
break;
 
  964         if (val == 
C4Value()) 
continue;
 
  970     int32_t childIndex = 0;
 
  979             childNameBuf.
Format(
"_child_%03d", ++childIndex);
 
  990     if (!proplist) 
return false;
 
  992     assert((parent || isLoading) && 
"GuiWindow created from proplist without parent (fails for ID tag)");
 
  994     bool layoutUpdateRequired = 
false; 
 
  998     std::unique_ptr<C4ValueArray> properties(proplist->
GetProperties());
 
  999     properties->SortStrings();
 
 1001     const int32_t propertySize = properties->GetSize();
 
 1002     for (int32_t i = 0; i < propertySize; ++i)
 
 1004         const C4Value &entry = properties->GetItem(i);
 
 1006         assert(key && 
"PropList returns non-string as key");
 
 1014             layoutUpdateRequired = 
true;
 
 1019             layoutUpdateRequired = 
true;
 
 1024             layoutUpdateRequired = 
true;
 
 1029             layoutUpdateRequired = 
true;
 
 1033             SetMarginProperties(property, stdTag);
 
 1034             layoutUpdateRequired = 
true;
 
 1039             target = 
property.getObj();
 
 1052             layoutUpdateRequired = 
true;
 
 1072             if (parent && !isMainWindow)
 
 1075                     parent->ChildWithIDRemoved(
this);
 
 1076                 id = 
property.getInt();
 
 1078                     parent->ChildGotID(
this);
 
 1082                     id = 
property.getInt();
 
 1098             layoutUpdateRequired = 
true;
 
 1103             layoutUpdateRequired = 
true;
 
 1106                 parent->ChildChangedPriority(
this);
 
 1113             C4PropList *subwindow = 
property.getPropList();
 
 1123                 bool freshlyAdded = 
false;
 
 1129                     if (childName != 
nullptr)
 
 1131                         child->name = childName;
 
 1135                     freshlyAdded = 
true;
 
 1145                     layoutUpdateRequired = 
true;
 
 1150     if (!isLoading && layoutUpdateRequired)
 
 1153     if (resetStdTag || isLoading)
 
 1163     if (wasRemovedFromParent) 
return;
 
 1172     for (
auto iter = 
begin(); iter != 
end();)
 
 1182         MenuDebugLogF(
"Closing window (%d, %s, @%p, target: %p) due to target removal.", 
id, name, 
this, this->target);
 
 1191         child->SetID(GenerateMenuID());
 
 1192         child->isMainWindow = 
true;
 
 1194         mainWindowNeedsLayoutUpdate = 
true;
 
 1199     ChildChangedPriority(child);
 
 1213         insertBefore = element;
 
 1217     assert(child != insertBefore);
 
 1225     if (IsRoot()) 
return;
 
 1228     std::pair<std::multimap<int32_t, C4ScriptGuiWindow*>::iterator, std::multimap<int32_t, C4ScriptGuiWindow*>::iterator> range;
 
 1229     range = childrenIDMap.equal_range(child->
GetID());
 
 1231     for (std::multimap<int32_t, C4ScriptGuiWindow*>::iterator iter = range.first; iter != range.second; ++iter)
 
 1233         if (iter->second != child) 
continue;
 
 1234         childrenIDMap.erase(iter);
 
 1235         MenuDebugLogF(
"child-map-size: %d, remove %d [I am %d]", childrenIDMap.size(), child->
GetID(), 
id);
 
 1242     assert(!IsRoot() && 
"ChildGotID called on window root, should not propagate over main windows!");
 
 1245     childrenIDMap.insert(std::make_pair(child->
GetID(), child));
 
 1246     MenuDebugLogF(
"child+map+size: %d, added %d [I am %d]", childrenIDMap.size(), child->
GetID(), 
id);
 
 1251     for (
Element * element : *
this)
 
 1254         if (child->id != childID) 
continue;
 
 1263     if (childName == 
nullptr) 
return nullptr;
 
 1265     for (
Element * element : *
this)
 
 1269         if (child->name != childName) 
continue;
 
 1277     std::pair<std::multimap<int32_t, C4ScriptGuiWindow*>::iterator, std::multimap<int32_t, C4ScriptGuiWindow*>::iterator> range;
 
 1278     range = childrenIDMap.equal_range(childID);
 
 1280     for (std::multimap<int32_t, C4ScriptGuiWindow*>::iterator iter = range.first; iter != range.second; ++iter)
 
 1283         if (subwindow->GetTarget() != childTarget) 
continue;
 
 1291     if (isRemovalLockedForClosingCallback())
 
 1296         throw C4AulExecError(
"Trying to remove script GUI window (or window target) from within window closing callback.");
 
 1300     if (!all && !IsRoot())
 
 1305         child->wasRemovedFromParent = 
true;
 
 1306         if (close) child->
Close();
 
 1307         if (child->
GetID() != 0)
 
 1308             ChildWithIDRemoved(child);
 
 1310         MenuDebugLogF(
"Deleting child (%d, %s, @%p, target: %p) from parent (%d, %s, @%p, target: %p).",
 
 1311             child->id, child->name, child, child->target,
 
 1312             id, name, 
this, target);
 
 1319         for (
Element * element : *
this)
 
 1322             assert(child != 
nullptr);
 
 1323             MenuDebugLogF(
"Closing child (%d, %s, @%p, target: %p) due to parent (%d, %s, @%p, target: %p) removal.",
 
 1324                 child->id, child->name, child, child->target,
 
 1325                 id, name, 
this, target);
 
 1326             child->wasRemovedFromParent = 
true;
 
 1328             if (child->
GetID() != 0)
 
 1329                 ChildWithIDRemoved(child);
 
 1358         lockRemovalForClosingCallback();
 
 1360         unlockRemovalForClosingCallback();
 
 1365     if (!wasRemovedFromParent)
 
 1367         assert(
GetParent() && 
"Close()ing GUIWindow without parent");
 
 1372 void C4ScriptGuiWindow::EnableScrollBar(
bool enable, 
float childrenHeight)
 
 1381         float adjustment = childrenHeight - height;
 
 1387         if (adjustment != 0.0)
 
 1400     const float widthOrHeight = Em2Pix(props[absoluteProperty].GetFloat())
 
 1401         + float(parentWidthOrHeight) * props[relativeProperty].
GetFloat();
 
 1402     return widthOrHeight;
 
 1411     const int32_t borderX(0), borderY(0);
 
 1412     int32_t currentX = borderX;
 
 1413     int32_t currentY = borderY;
 
 1414     int32_t lowestChildRelY = 0;
 
 1415     int32_t maxChildHeight = 0;
 
 1427         const float childWdtF = float(child->
rcBounds.
Wdt) + childLeftMargin + childRightMargin;
 
 1428         const float childHgtF = float(child->
rcBounds.
Hgt) + childTopMargin + childBottomMargin;
 
 1430         auto doLineBreak = [&]()
 
 1433             currentY += maxChildHeight + borderY;
 
 1438         const auto childWdt = (int32_t)(childWdtF + 0.5f);
 
 1439         const auto childHgt = (int32_t)(childHgtF + 0.5f);
 
 1442         const bool fitsInRow = (width - currentX) >= childWdt;
 
 1443         if (!fitsInRow) doLineBreak();
 
 1446         if (!maxChildHeight || (childHgt > maxChildHeight))
 
 1448             maxChildHeight = childHgt;
 
 1449             lowestChildRelY = currentY + childHgt;
 
 1451         child->
rcBounds.
x = currentX + 
static_cast<int32_t
>(childLeftMargin);
 
 1452         child->
rcBounds.
y = currentY + 
static_cast<int32_t
>(childTopMargin);
 
 1454         currentX += childWdt + borderX;
 
 1458     EnableScrollBar(lowestChildRelY > height, lowestChildRelY);
 
 1467     const int32_t borderX(0), borderY(0);
 
 1468     int32_t lowestChildRelY = 0;
 
 1470     std::list<C4ScriptGuiWindow*> alreadyPlacedChildren;
 
 1482         const float childWdtF = float(child->
rcBounds.
Wdt) + childLeftMargin + childRightMargin;
 
 1483         const float childHgtF = float(child->
rcBounds.
Hgt) + childTopMargin + childBottomMargin;
 
 1486         const auto childWdt = (int32_t)(childWdtF + 0.5f);
 
 1487         const auto childHgt = (int32_t)(childHgtF + 0.5f);
 
 1490         int32_t currentX = borderX;
 
 1491         int32_t currentY = borderY;
 
 1493         bool hadOverlap = 
false;
 
 1494         int overlapRepeats = 0;
 
 1497             auto overlapsWithOther = [¤tX, ¤tY, &childWdt, &childHgt](
C4ScriptGuiWindow *other)
 
 1499                 if (currentX + childWdt <= other->
rcBounds.
x) 
return false;
 
 1500                 if (currentY + childHgt <= other->
rcBounds.
y) 
return false;
 
 1501                 if (currentX >= other->rcBounds.GetRight()) 
return false;
 
 1502                 if (currentY >= other->rcBounds.GetBottom()) 
return false;
 
 1506             int32_t currentMinY = 0;
 
 1508             for (
auto &other : alreadyPlacedChildren)
 
 1511                 if ((other->rcBounds.GetBottom() > currentY) && other->rcBounds.Hgt > 0)
 
 1513                     if (currentMinY == 0 || (other->rcBounds.GetBottom() < currentMinY))
 
 1514                         currentMinY = other->rcBounds.GetBottom();
 
 1517                 if (overlapsWithOther(other))
 
 1520                     currentX = other->rcBounds.GetRight();
 
 1522                     if (currentX + childWdt > width)
 
 1528                         const int32_t forcedMinimalChange = (overlapRepeats > alreadyPlacedChildren.size()) ? 1 : 0;
 
 1529                         currentY = std::max(currentY + forcedMinimalChange, currentMinY);
 
 1533             overlapRepeats += 1;
 
 1534         } 
while (hadOverlap);
 
 1536         alreadyPlacedChildren.push_back(child);
 
 1538         lowestChildRelY = std::max(lowestChildRelY, currentY + childHgt);
 
 1539         child->
rcBounds.
x = currentX + 
static_cast<int32_t
>(childLeftMargin);
 
 1540         child->
rcBounds.
y = currentY + 
static_cast<int32_t
>(childTopMargin);
 
 1544     EnableScrollBar(lowestChildRelY > height, lowestChildRelY);
 
 1549     const int32_t borderY(0);
 
 1550     int32_t currentY = borderY;
 
 1562         const float childHgtF = float(child->
rcBounds.
Hgt) + childTopMargin + childBottomMargin;
 
 1563         const int32_t childHgt = (int32_t)(childHgtF + 0.5f);
 
 1565         child->
rcBounds.
y = currentY + childTopMargin;
 
 1566         currentY += childHgt + borderY;
 
 1570     EnableScrollBar(currentY > 
rcBounds.
Hgt, currentY);
 
 1576     float oldTargetX = cgo.
TargetX;
 
 1577     float oldTargetY = cgo.
TargetY;
 
 1586         currentClippingRect = &myClippingRect;
 
 1590     int32_t clipX1(0), clipX2(0), clipY1(0), clipY2(0);
 
 1593     const int32_t targetClipX1 = cgo.
X + cgo.
TargetX + clipX1;
 
 1594     const int32_t targetClipY1 = cgo.
Y + cgo.
TargetY + clipY1;
 
 1595     const int32_t targetClipX2 = cgo.
X + cgo.
TargetX + clipX2;
 
 1596     const int32_t targetClipY2 = cgo.
Y + cgo.
TargetY + clipY2;
 
 1602             std::max(currentClippingRect->
x, targetClipX1),
 
 1603             std::max(currentClippingRect->
y, targetClipY1),
 
 1604             std::min(currentClippingRect->
Wdt, targetClipX2),
 
 1605             std::min(currentClippingRect->
Hgt, targetClipY2));
 
 1606         currentClippingRect = &myClippingRect;
 
 1609     if (withMultipleFlag != 1)
 
 1617         assert(withMultipleFlag == 1);
 
 1622     bool oneDrawn = 
false; 
 
 1624     for (
auto element : *
this)
 
 1628         if (withMultipleFlag != -1)
 
 1637         if (child->
Draw(cgo, 
player, currentClippingRect))
 
 1640         if (oneDrawn && (withMultipleFlag == 0)) 
break;
 
 1669         mainWindowNeedsLayoutUpdate = 
true;
 
 1680             mainWindowNeedsLayoutUpdate = 
true;
 
 1692     for (
Element * element : *
this)
 
 1705     const float fullWidth = cgo.
Wdt * cgo.
Zoom - cgo.
X;
 
 1706     const float fullHeight = cgo.
Hgt * cgo.
Zoom - cgo.
Y;
 
 1713     const float minMarginPx = 50.0f;
 
 1714     const float targetWidthPx = std::min(Em2Pix(targetWidthEm), fullWidth - 2.0f * minMarginPx);
 
 1715     const float targetHeightPx = std::min(Em2Pix(targetHeightEm), fullHeight - 2.0f * minMarginPx);
 
 1718     const float marginLeftRight = (fullWidth - targetWidthPx) / 2.0f;
 
 1719     const float marginTopBottom = (fullHeight- targetHeightPx) / 2.0f;
 
 1722     const float &
left = marginLeftRight;
 
 1723     const float right = -marginLeftRight;
 
 1724     const float &
top = marginTopBottom;
 
 1725     const float bottom = -marginTopBottom;
 
 1728     const float wdt = fullWidth - 
left + 
right;
 
 1729     const float hgt = fullHeight - 
top + 
bottom;
 
 1731     const bool needUpdate = mainWindowNeedsLayoutUpdate || (
rcBounds.
Wdt != int32_t(wdt)) || (
rcBounds.
Hgt != int32_t(hgt));
 
 1735         mainWindowNeedsLayoutUpdate = 
false;
 
 1744         for (
Element * element : *
this)
 
 1753         for (
Element * element : *
this)
 
 1797     float width = rightDrawX - leftDrawX;
 
 1798     float height = bottomDrawY - topDrawY;
 
 1808     int minRequiredTextHeight = 0;
 
 1822             minRequiredTextHeight = actualTextHeight;
 
 1828             minRequiredTextHeight = rawTextHeight;
 
 1846     int32_t topMostChild = 0;
 
 1847     int32_t bottomMostChild = minRequiredTextHeight;
 
 1848     for (
Element * element : *
this)
 
 1851         const int32_t &childTop = child->
rcBounds.
y;
 
 1852         const int32_t childBottom = childTop + child->
rcBounds.
Hgt;
 
 1853         if (childTop < topMostChild) topMostChild = childTop;
 
 1854         if (childBottom > bottomMostChild) bottomMostChild = childBottom;
 
 1863     bottomMostChild = std::max(bottomMostChild, 
rcBounds.
Hgt);
 
 1878     mainWindowNeedsLayoutUpdate = 
false;
 
 1887     const int oldTargetX = cgo.
TargetX;
 
 1888     const int oldTargetY = cgo.
TargetY;
 
 1913     if (mainWindowNeedsLayoutUpdate)
 
 1916         assert(isMainWindow);
 
 1920         assert(!mainWindowNeedsLayoutUpdate);
 
 1927     const int32_t outDrawRight = outDrawX + 
rcBounds.
Wdt;
 
 1928     const int32_t outDrawBottom = outDrawY + 
rcBounds.
Hgt;
 
 1930     C4Facet cgoOut(cgo.
Surface, outDrawX, outDrawY, outDrawWdt, outDrawHgt);
 
 1960             symbolDef->Draw(cgoOut, 
false, 0UL, 
nullptr, 0, 0, 
nullptr, graphicsName ? graphicsName->
getData() : 
nullptr);
 
 1969         int alignment = 
ALeft;
 
 1973         const int actualDrawingWidth = outDrawWdt - scrollbarXOffset;
 
 1976         int allowedTextWidth = actualDrawingWidth;
 
 1979             allowedTextWidth = std::numeric_limits<int>::max();
 
 1981         float textYOffset = 
static_cast<float>(-scrollbarScroll), textXOffset = 0.0f;
 
 1983             textYOffset = float(outDrawHgt) / 2.0f - float(textHgt) / 2.0f;
 
 1985             textYOffset = float(outDrawHgt) - float(textHgt);
 
 1990             textXOffset = float(actualDrawingWidth) / 2.0f;
 
 1998             textXOffset = float(actualDrawingWidth);
 
 2042         if (props[i].SwitchTag(tag))
 
 2061     assert(!
HasMouseFocus() && 
"custom menu window properly loaded incorrectly!");
 
 2073             const float guiZoom = viewport->
GetGUIZoom();
 
 2074             const int32_t x = int32_t((parentOffsetX + 
rcBounds.
x) / guiZoom);
 
 2075             const int32_t y = int32_t((parentOffsetY + 
rcBounds.
y) / guiZoom);
 
 2076             const int32_t wdt = int32_t(
rcBounds.
Wdt / guiZoom);
 
 2077             const int32_t hgt = int32_t(
rcBounds.
Hgt / guiZoom);
 
 2085     if (!action) 
return;
 
 2096     assert(
HasMouseFocus() && 
"custom menu window probably loaded incorrectly!");
 
 2110     if (!action) 
return;
 
 2123     bool oneActionAlreadyExecuted = 
false;
 
 2126     for (
int withMultipleFlag = 0; withMultipleFlag <= 1; ++withMultipleFlag)
 
 2128         for (
auto iter = 
rbegin(); iter != 
rend(); ++iter)
 
 2140             int32_t adjustedMouseX = 0, adjustedMouseY = mouseY;
 
 2141             int32_t offsetX = 0, offsetY = 0;
 
 2142             if (withMultipleFlag == 0)
 
 2148             adjustedMouseX = mouseX + offsetX;
 
 2149             adjustedMouseY = mouseY + offsetY;
 
 2157             if ((adjustedMouseX < childLeft) || (adjustedMouseX > childRight)) inArea = 
false;
 
 2158             else if ((adjustedMouseY < childTop) || (adjustedMouseY > childBottom)) inArea = 
false;
 
 2167             if (oneActionAlreadyExecuted) 
continue;
 
 2171             if (child->
ProcessMouseInput(button, adjustedMouseX - childLeft, adjustedMouseY - childTop - 
iScrollY, dwKeyParam, childLeft - offsetX, childTop + 
iScrollY - offsetY))
 
 2173                 oneActionAlreadyExecuted = 
true;
 
 2178     return oneActionAlreadyExecuted;
 
 2204     bool oneActionAlreadyExecuted = 
false;
 
 2206     const int32_t scrollAdjustedMouseY = mouseY + 
iScrollY;
 
 2209     bool overChild = 
false; 
 
 2211     for (
auto iter = 
rbegin(); iter != 
rend(); ++iter)
 
 2218         const int32_t childLeft = child->
rcBounds.
x;
 
 2220         const int32_t childTop = child->
rcBounds.
y;
 
 2224         if ((mouseX <= childLeft) || (mouseX > childRight)) inArea = 
false;
 
 2225         else if ((scrollAdjustedMouseY <= childTop) || (scrollAdjustedMouseY > childBottom)) inArea = 
false;
 
 2234         if (oneActionAlreadyExecuted) 
continue;
 
 2240             oneActionAlreadyExecuted = 
true;
 
 2244     if (oneActionAlreadyExecuted) 
return true;
 
 2267         short delta = (short)(dwKeyParam >> 16);
 
 2297     if (isMainWindow && subwindowID) 
 
 2299         MenuDebugLogF(
"passing command... instance:%d, plr:%d, subwin:%d, type:%d [I am %d, MW]", actionID, 
player, subwindowID, actionType, 
id);
 
 2302         MenuDebugLogF(
"children ID map:\t%d", childrenIDMap.size());
 
 2305         std::pair<std::multimap<int32_t, C4ScriptGuiWindow*>::iterator, std::multimap<int32_t, C4ScriptGuiWindow*>::iterator> range;
 
 2306         range = childrenIDMap.equal_range(subwindowID);
 
 2308         for (std::multimap<int32_t, C4ScriptGuiWindow*>::iterator iter = range.first; iter != range.second; ++iter)
 
 2310             if (iter->second->ExecuteCommand(actionID, 
player, subwindowID, actionType, target))
 
 2317         MenuDebugLogF(
"shortcutting command failed.. no appropriate window");
 
 2321     if ((
id == subwindowID) && (this->target == target))
 
 2325         MenuDebugLogF(
"all actions:\t%d", props[actionType].GetAllActions().size());
 
 2326         std::list<C4ScriptGuiWindowAction*> allActions = props[actionType].
GetAllActions();
 
 2327         for (
auto action : allActions)
 
 2329             assert(action && 
"C4ScriptGuiWindowProperty::GetAllActions returned list with null-pointer");
 
 2331             if (action->ExecuteCommand(actionID, 
this, 
player))
 
 2344     if (isMainWindow && subwindowID)
 
 2356             MenuDebugLogF(
"passing command sucessful! (I am %d - &p)", 
id, this->target);
 
 2363 bool C4ScriptGuiWindow::IsRoot()
 
 2381 void C4ScriptGuiWindow::lockRemovalForClosingCallback()
 
 2383     lockRemovalForClosingCallbackCounter += 1;
 
 2388 void C4ScriptGuiWindow::unlockRemovalForClosingCallback()
 
 2390     assert(lockRemovalForClosingCallbackCounter > 0);
 
 2391     lockRemovalForClosingCallbackCounter -= 1;
 
C4MouseControl MouseControl
C4GraphicsSystem GraphicsSystem
C4GraphicsResource GraphicsResource
int main(int argc, char *argv[])
#define C4GUI_ScrollBarWdt
bool LogF(const char *strMessage,...)
const int32_t C4MC_Button_LeftUp
const int32_t C4MC_Button_LeftDown
const int32_t C4MC_Button_LeftDouble
const int32_t C4MC_Button_Wheel
#define MenuDebugLogF(...)
#define PROPERTY_TUPLE(p, prop1, prop2)
C4Value C4VObj(C4Object *pObj)
C4Value C4VInt(int32_t i)
StdStrBuf FormatString(const char *szFmt,...)
void Add(C4PacketType eType, C4ControlPacket *pCtrl)
void DrawFrameDw(C4Surface *sfcDest, int x1, int y1, int x2, int y2, DWORD dwClr, float width=1.0f)
bool RestorePrimaryClipper()
void DrawBoxDw(C4Surface *sfcDest, int iX1, int iY1, int iX2, int iY2, DWORD dwClr)
bool StorePrimaryClipper()
bool SetPrimaryClipper(int iX1, int iY1, int iX2, int iY2)
bool TextOut(const char *szText, CStdFont &rFont, float fZoom, C4Surface *sfcDest, float iTx, float iTy, DWORD dwFCol=0xffffffff, BYTE byForm=ALeft, bool fDoMarkup=true)
void RemoveElement(Element *pChild) override
int32_t GetElementCount()
void InsertElement(Element *pChild, Element *pInsertBefore)
virtual void SetVisibility(bool fToValue)
std::unique_ptr< C4ScriptGuiWindow > ScriptGuiRoot
void SetTooltipText(const StdStrBuf &text)
void SetTooltipRectangle(const C4Rect &rectangle)
bool IsVisible(int32_t iForPlr, bool fAsOverlay) const
virtual C4Object * GetObject()
virtual const char * GetName() const
virtual C4ValueArray * GetProperties() const
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
virtual C4Def const  * GetDef() const
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
virtual void SetPropertyByS(C4String *k, const C4Value &to)
static C4PropList * New(C4PropList *prototype=nullptr)
void SetProperty(C4PropertyName k, const C4Value &to)
bool Init(C4ValueArray *array, int32_t index=0)
const C4Value ToC4Value(bool first=true)
void Execute(C4ScriptGuiWindow *parent, int32_t player, int32_t actionType)
bool ExecuteCommand(int32_t actionID, C4ScriptGuiWindow *parent, int32_t player)
C4ScriptGuiWindowAction()
~C4ScriptGuiWindowAction()
void ClearPointers(C4Object *pObj)
bool UpdateChildLayout(C4TargetFacet &cgo, float parentWidth, float parentHeight)
void UpdateLayoutVertical()
C4ScriptGuiWindow * GetChildByName(C4String *childName)
void RemoveChild(C4ScriptGuiWindow *child, bool close=true, bool all=false)
bool DrawChildren(C4TargetFacet &cgo, int32_t player, int32_t withMultipleFlag=-1, C4Rect *currentClippingRect=nullptr)
float CalculateRelativeSize(float parentWidthOrHeight, C4ScriptGuiWindowPropertyName::type absoluteProperty, C4ScriptGuiWindowPropertyName::type relativeProperty)
bool CreateFromPropList(C4PropList *proplist, bool resetStdTag=false, bool isUpdate=false, bool isLoading=false)
C4ScriptGuiWindow * GetChildByID(int32_t child)
C4ScriptGuiWindow * GetSubWindow(int32_t childID, C4Object *childTarget)
bool IsVisibleTo(int32_t player)
bool ExecuteCommand(int32_t actionID, int32_t player, int32_t subwindowID, int32_t actionType, C4Object *target)
void Draw(C4TargetFacet &cgo) override
const C4Value ToC4Value()
virtual bool ProcessMouseInput(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam, int32_t parentOffsetX, int32_t parentOffsetY)
bool DrawAll(C4TargetFacet &cgo, int32_t player)
~C4ScriptGuiWindow() override
void RequestLayoutUpdate()
int32_t currentMouseState
bool GetClippingRect(int32_t &left, int32_t &top, int32_t &right, int32_t &bottom)
static const float standardHeight
void OnMouseIn(int32_t player, int32_t parentOffsetX, int32_t parentOffsetY)
virtual bool MouseInput(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
C4ScriptGuiWindow * AddChild()
static const float standardWidth
void Denumerate(C4ValueNumbers *numbers)
void SetTag(C4String *tag)
void MouseEnter(C4GUI::CMouse &rMouse) override
void UpdateLayoutTightGrid()
bool UpdateLayout(C4TargetFacet &cgo)
void MouseLeave(C4GUI::CMouse &rMouse) override
void ClearPointers(C4Object *pObj)
void OnMouseOut(int32_t player)
C4ScriptGuiWindowAction * GetAction()
const C4Value ToC4Value()
~C4ScriptGuiWindowProperty()
void ClearPointers(C4Object *pObj)
std::list< C4ScriptGuiWindowAction * > GetAllActions()
void Set(const C4Value &value, C4String *tag)
bool SwitchTag(C4String *tag)
StdCopyStrBuf * GetStrBuf()
C4GUI::FrameDecoration * GetFrameDecoration()
const char * GetCStr() const
C4String * FindString(const char *strString) const
C4String * RegString(StdStrBuf String)
const C4Value & GetItem(int32_t iElem) const
void SetSize(int32_t inSize)
void SetItem(int32_t iElemNr, const C4Value &Value)
C4ValueArray * getArray() const
C4Object * getObj() const
C4String * getStr() const
C4PropList * getPropList() const
const char * GetTypeName() const
const C4Value & GetValue(uint32_t)
C4Viewport * GetViewport(int32_t player_nr, C4Viewport *prev=nullptr)
int GetLineHeight() const
std::tuple< std::string, int > BreakMessage(const char *szMsg, int iWdt, bool fCheckMarkup, float fZoom=1.0f)
bool GetTextExtent(const char *szText, int32_t &rsx, int32_t &rsy, bool fCheckMarkup=true)
int GetFontHeight() const
const char * getData() const
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O