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