From 5c6faa1683efd3ca7a549a63b1c3b5bffc7526a3 Mon Sep 17 00:00:00 2001 From: nakst <> Date: Sat, 9 Oct 2021 14:59:58 +0100 Subject: [PATCH] refine container window design --- desktop/gui.cpp | 118 +++++++++++++++++++++---------------------- desktop/os.header | 2 +- kernel/syscall.cpp | 12 ++++- kernel/windows.cpp | 4 +- res/Theme Source.dat | Bin 556632 -> 558212 bytes res/Theme.dat | Bin 29368 -> 29428 bytes shared/math.cpp | 2 + util/designer2.cpp | 24 ++++++++- 8 files changed, 95 insertions(+), 67 deletions(-) diff --git a/desktop/gui.cpp b/desktop/gui.cpp index 5210cbb..8c0470d 100644 --- a/desktop/gui.cpp +++ b/desktop/gui.cpp @@ -18,11 +18,25 @@ // Behaviour of the scroll wheel with regards to focused/hovered elements --> Scroll the hovered element only. // TODO Get these from the theme file. -#define WINDOW_INSET ((int) (19 * theming.scale)) +#define CONTAINER_SOLID_T ((int) (25 * theming.scale)) +#define CONTAINER_SOLID_B ((int) (35 * theming.scale)) +#define CONTAINER_SOLID_C ((int) (30 * theming.scale)) +#define CONTAINER_EMBED_T ((int) (64 * theming.scale)) +#define CONTAINER_EMBED_B ((int) (44 * theming.scale)) +#define CONTAINER_EMBED_C ((int) (39 * theming.scale)) +#define CONTAINER_OPAQUE_T ((int) (30 * theming.scale)) +#define CONTAINER_OPAQUE_B ((int) (40 * theming.scale)) +#define CONTAINER_OPAQUE_C ((int) (35 * theming.scale)) +#define CONTAINER_MAXIMIZE_T ((int) (29 * theming.scale)) +#define CONTAINER_MAXIMIZE_B ((int) (44 * theming.scale)) +#define CONTAINER_MAXIMIZE_C ((int) (39 * theming.scale)) #define CONTAINER_TAB_BAND_HEIGHT ((int) (33 * theming.scale)) -#define BORDER_THICKNESS ((int) ( 9 * theming.scale)) - -// #define TRACE_LAYOUT +#define CONTAINER_RESIZE_BORDER ((int) (CONTAINER_EMBED_C - CONTAINER_SOLID_C)) +#define CONTAINER_RESIZE_OFFSET ((int) (CONTAINER_RESIZE_BORDER / 2)) +#define CONTAINER_SNAP_T ((int) (0 * theming.scale)) +#define CONTAINER_SNAP_B ((int) (-4 * theming.scale)) +#define CONTAINER_SNAP_OUTSIDE ((int) (-5 * theming.scale)) +#define CONTAINER_SNAP_INSIDE ((int) (17 * theming.scale)) struct AccessKeyEntry { char character; @@ -531,24 +545,24 @@ void WindowSnap(EsWindow *window, bool restored, bool dragging, uint8_t edge) { EsRectangle bounds; if (edge == SNAP_EDGE_MAXIMIZE) { - bounds.t = screen.t - 16 * theming.scale; - bounds.b = screen.b + WINDOW_INSET; - bounds.l = screen.l - WINDOW_INSET; - bounds.r = screen.r + WINDOW_INSET; + bounds.t = screen.t - CONTAINER_MAXIMIZE_T; + bounds.b = screen.b + CONTAINER_MAXIMIZE_B; + bounds.l = screen.l - CONTAINER_MAXIMIZE_C; + bounds.r = screen.r + CONTAINER_MAXIMIZE_C; } else if (edge == SNAP_EDGE_LEFT) { - bounds.t = screen.t; - bounds.b = screen.b; - bounds.l = screen.l; - bounds.r = (screen.r + screen.l) / 2 + BORDER_THICKNESS / 2; + bounds.t = screen.t + CONTAINER_SNAP_T; + bounds.b = screen.b - CONTAINER_SNAP_B; + bounds.l = screen.l + CONTAINER_SNAP_OUTSIDE; + bounds.r = (screen.r + screen.l) / 2 + CONTAINER_SNAP_INSIDE; } else if (edge == SNAP_EDGE_RIGHT) { - bounds.t = screen.t; - bounds.b = screen.b; - bounds.l = (screen.r + screen.l) / 2 - BORDER_THICKNESS / 2; - bounds.r = screen.r; + bounds.t = screen.t + CONTAINER_SNAP_T; + bounds.b = screen.b - CONTAINER_SNAP_B; + bounds.l = (screen.r + screen.l) / 2 - CONTAINER_SNAP_INSIDE; + bounds.r = screen.r - CONTAINER_SNAP_OUTSIDE; } EsSyscall(ES_SYSCALL_WINDOW_MOVE, window->handle, (uintptr_t) &bounds, 0, - ES_WINDOW_MOVE_DYNAMIC | (edge == SNAP_EDGE_MAXIMIZE ? ES_WINDOW_MOVE_MAXIMISED : 0)); + ES_WINDOW_MOVE_DYNAMIC | (edge == SNAP_EDGE_MAXIMIZE ? ES_WINDOW_MOVE_MAXIMIZED : 0)); if (!dragging) { window->resetPositionOnNextMove = true; @@ -580,13 +594,12 @@ void WindowChangeBounds(int direction, int newX, int newY, int *originalX, int * restored = true; } - int offset = BORDER_THICKNESS / 2 - WINDOW_INSET; EsRectangle bounds = previousBounds; - if (direction & RESIZE_LEFT) bounds.l = newX + offset; - if (direction & RESIZE_RIGHT) bounds.r = newX - offset; - if (direction & RESIZE_TOP) bounds.t = newY + offset; - if (direction & RESIZE_BOTTOM) bounds.b = newY - offset; + if (direction & RESIZE_LEFT) bounds.l = newX - CONTAINER_SOLID_C - CONTAINER_RESIZE_OFFSET; + if (direction & RESIZE_RIGHT) bounds.r = newX + CONTAINER_SOLID_C + CONTAINER_RESIZE_OFFSET; + if (direction & RESIZE_TOP) bounds.t = newY - CONTAINER_SOLID_T - CONTAINER_RESIZE_OFFSET; + if (direction & RESIZE_BOTTOM) bounds.b = newY + CONTAINER_SOLID_B + CONTAINER_RESIZE_OFFSET; if (startBounds && direction != RESIZE_MOVE) { if (direction & RESIZE_LEFT) bounds.r = gui.resizeStartBounds.r + (bothSides ? gui.resizeStartBounds.l - newX : 0); @@ -619,7 +632,7 @@ void WindowChangeBounds(int direction, int newX, int newY, int *originalX, int * return; } else { if (restored && window->resetPositionOnNextMove) { - // The user previously snapped/maximised the window in a previous operation. + // The user previously snapped/maximized the window in a previous operation. // Therefore, the movement anchor won't be what the user expects. // Try to put it in the center. int positionAlongWindow = *originalX - previousBounds.l; @@ -666,7 +679,7 @@ void WindowChangeBounds(int direction, int newX, int newY, int *originalX, int * EsSyscall(ES_SYSCALL_WINDOW_MOVE, window->handle, (uintptr_t) &bounds, 0, ES_WINDOW_MOVE_DYNAMIC); } -int ProcessWindowBorderMessage(EsWindow *window, EsMessage *message, EsRectangle bounds, int from, int to) { +int ProcessWindowBorderMessage(EsWindow *window, EsMessage *message, EsRectangle bounds, bool addSolidInsets) { if (message->type == ES_MSG_GET_CURSOR) { EsPoint position = EsMouseGetPosition(window); message->cursorStyle = ES_CURSOR_NORMAL; @@ -675,13 +688,18 @@ int ProcessWindowBorderMessage(EsWindow *window, EsMessage *message, EsRectangle window->resizeType = 0; window->resizeCursor = message->cursorStyle; } else { - bool left = position.x < to, right = position.x >= bounds.r - to, - top = position.y < to, bottom = position.y >= bounds.b - to; + int32_t solidC = addSolidInsets ? CONTAINER_SOLID_C : 0; + int32_t solidT = addSolidInsets ? CONTAINER_SOLID_T : 0; + int32_t solidB = addSolidInsets ? CONTAINER_SOLID_B : 0; + + bool left = position.x < solidC + CONTAINER_RESIZE_BORDER; + bool right = position.x >= bounds.r - solidC - CONTAINER_RESIZE_BORDER; + bool top = position.y < solidT + CONTAINER_RESIZE_BORDER; + bool bottom = position.y >= bounds.b - solidB - CONTAINER_RESIZE_BORDER; if (gui.resizing) { message->cursorStyle = window->resizeCursor; - } else if (position.x < from || position.y < from - || position.x >= bounds.r - from || position.y >= bounds.b - from) { + } else if (position.x < solidC || position.y < solidT || position.x >= bounds.r - solidC || position.y >= bounds.b - solidB) { } else if ((right && top) || (bottom && left)) { message->cursorStyle = ES_CURSOR_RESIZE_DIAGONAL_1; } else if ((left && top) || (bottom && right)) { @@ -791,17 +809,19 @@ int ProcessRootMessage(EsElement *element, EsMessage *message) { if (window->windowStyle == ES_WINDOW_CONTAINER) { if (message->type == ES_MSG_LAYOUT) { - EsElementMove(window->GetChild(0), WINDOW_INSET, WINDOW_INSET, bounds.r - WINDOW_INSET * 2, CONTAINER_TAB_BAND_HEIGHT); + EsElementMove(window->GetChild(0), CONTAINER_EMBED_C, CONTAINER_EMBED_T - CONTAINER_TAB_BAND_HEIGHT, + bounds.r - CONTAINER_EMBED_C * 2, CONTAINER_TAB_BAND_HEIGHT); } else if (message->type == ES_MSG_UI_SCALE_CHANGED) { // This message is also sent when the window is created. - EsRectangle solidInsets = ES_RECT_1(WINDOW_INSET - BORDER_THICKNESS); + EsRectangle solidInsets = ES_RECT_4(CONTAINER_SOLID_C, CONTAINER_SOLID_C, CONTAINER_SOLID_T, CONTAINER_SOLID_B); EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, window->handle, ES_WINDOW_SOLID_TRUE, (uintptr_t) &solidInsets, ES_WINDOW_PROPERTY_SOLID); - EsRectangle embedInsets = ES_RECT_4(WINDOW_INSET, WINDOW_INSET, WINDOW_INSET + CONTAINER_TAB_BAND_HEIGHT, WINDOW_INSET); + EsRectangle embedInsets = ES_RECT_4(CONTAINER_EMBED_C, CONTAINER_EMBED_C, CONTAINER_EMBED_T, CONTAINER_EMBED_B); EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, window->handle, (uintptr_t) &embedInsets, 0, ES_WINDOW_PROPERTY_EMBED_INSETS); - EsRectangle opaqueBounds = ES_RECT_4(WINDOW_INSET, window->windowWidth - WINDOW_INSET, WINDOW_INSET, window->windowHeight - WINDOW_INSET); + EsRectangle opaqueBounds = ES_RECT_4(CONTAINER_OPAQUE_C, window->windowWidth - CONTAINER_OPAQUE_C, + CONTAINER_OPAQUE_T, window->windowHeight - CONTAINER_OPAQUE_B); EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, window->handle, (uintptr_t) &opaqueBounds, 0, ES_WINDOW_PROPERTY_OPAQUE_BOUNDS); } else { - response = ProcessWindowBorderMessage(window, message, bounds, WINDOW_INSET - BORDER_THICKNESS, WINDOW_INSET); + response = ProcessWindowBorderMessage(window, message, bounds, true); } } else if (window->windowStyle == ES_WINDOW_MENU) { if (message->type == ES_MSG_PAINT_BACKGROUND) { @@ -818,11 +838,10 @@ int ProcessRootMessage(EsElement *element, EsMessage *message) { } else if (window->windowStyle == ES_WINDOW_INSPECTOR) { if (message->type == ES_MSG_LAYOUT) { if (window->GetChildCount()) { - EsElementMove(window->GetChild(0), BORDER_THICKNESS, BORDER_THICKNESS + 30, - bounds.r - BORDER_THICKNESS * 2, bounds.b - BORDER_THICKNESS * 2 - 30); + EsElementMove(window->GetChild(0), 9, 9 + 30, bounds.r - 9 * 2, bounds.b - 9 * 2 - 30); } } else { - response = ProcessWindowBorderMessage(window, message, bounds, 0, BORDER_THICKNESS); + response = ProcessWindowBorderMessage(window, message, bounds, false); } } else if (window->windowStyle == ES_WINDOW_NORMAL) { if (message->type == ES_MSG_LAYOUT) { @@ -2422,22 +2441,6 @@ int EsElement::GetHeight(int width) { } void EsElement::InternalMove(int _width, int _height, int _offsetX, int _offsetY) { -#ifdef TRACE_LAYOUT - if (parent) { - EsElement *parent = this->parent->parent; - while (parent) parent = parent->parent, EsPrint("\t"); - EsPrint("(move) %z\n", debugName); - } -#endif - -#ifdef TRACE_LAYOUT - if (parent) { - EsElement *parent = this->parent->parent; - while (parent) parent = parent->parent, EsPrint("\t"); - EsPrint("(move) %z :: in %d, %d; %d, %d :: ", debugName, _offsetX, _offsetY, _width, _height); - } -#endif - // Add the internal offset. if (parent) { @@ -2453,14 +2456,6 @@ void EsElement::InternalMove(int _width, int _height, int _offsetX, int _offsetY bool relayoutChild = state & UI_STATE_RELAYOUT_CHILD; int oldOffsetX = offsetX, oldOffsetY = offsetY; -#ifdef TRACE_LAYOUT - if (parent) { - EsPrint("align %d, %d; %d, %d ::%z%z%z%z\n", _offsetX, _offsetY, _width, _height, - hasPositionChanged ? " pos" : "", hasSizeChanged ? " size" : "", - relayoutRequested ? " rel" : "", relayoutChild ? " child" : ""); - } -#endif - // Update the variables. offsetX = _offsetX; @@ -7425,7 +7420,8 @@ void UIProcessWindowManagerMessage(EsWindow *window, EsMessage *message, Process window->height = window->windowHeight = message->windowResized.content.b; if (window->windowStyle == ES_WINDOW_CONTAINER) { - EsRectangle opaqueBounds = ES_RECT_4(WINDOW_INSET, window->windowWidth - WINDOW_INSET, WINDOW_INSET, window->windowHeight - WINDOW_INSET); + EsRectangle opaqueBounds = ES_RECT_4(CONTAINER_OPAQUE_C, window->windowWidth - CONTAINER_OPAQUE_C, + CONTAINER_OPAQUE_T, window->windowHeight - CONTAINER_OPAQUE_B); EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, window->handle, (uintptr_t) &opaqueBounds, 0, ES_WINDOW_PROPERTY_OPAQUE_BOUNDS); } else if (window->windowStyle == ES_WINDOW_INSPECTOR) { EsRectangle opaqueBounds = ES_RECT_2S(window->windowWidth, window->windowHeight); diff --git a/desktop/os.header b/desktop/os.header index 857782b..34b0d8a 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -627,7 +627,7 @@ define ES_THEME_METRICS_ICON_SIZE (1 << 21) define ES_THEME_METRICS_IS_ITALIC (1 << 22) define ES_THEME_METRICS_LAYOUT_VERTICAL (1 << 23) -define ES_WINDOW_MOVE_MAXIMISED (1 << 0) +define ES_WINDOW_MOVE_MAXIMIZED (1 << 0) define ES_WINDOW_MOVE_ADJUST_TO_FIT_SCREEN (1 << 1) define ES_WINDOW_MOVE_HIDDEN (1 << 2) define ES_WINDOW_MOVE_ALWAYS_ON_TOP (1 << 3) diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index 13e229f..e9e4e9f 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -569,7 +569,17 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_SET_BITS) { uintptr_t stride = Width(region) * 4; EsRectangle clippedRegion = EsRectangleIntersection(region, ES_RECT_2S(surface->width, surface->height)); - if (argument3 != WINDOW_SET_BITS_AFTER_RESIZE) { + EsRectangle directUpdateSubRegion; + + if (window->style == ES_WINDOW_CONTAINER && !isEmbed) { + directUpdateSubRegion = ES_RECT_4(0, window->width, 0, insets.t); + } else if (window->style == ES_WINDOW_CONTAINER && isEmbed) { + directUpdateSubRegion = ES_RECT_4(insets.l, window->width - insets.r, insets.t, window->height - insets.b); + } else { + directUpdateSubRegion = ES_RECT_4(0, window->width, 0, window->height); + } + + if (argument3 != WINDOW_SET_BITS_AFTER_RESIZE && EsRectangleEquals(region, EsRectangleIntersection(region, directUpdateSubRegion))) { skipUpdate = window->UpdateDirect((K_USER_BUFFER uint32_t *) argument2, stride, clippedRegion); } diff --git a/kernel/windows.cpp b/kernel/windows.cpp index b7d8bf1..a126058 100644 --- a/kernel/windows.cpp +++ b/kernel/windows.cpp @@ -775,7 +775,7 @@ bool Window::Move(EsRectangle rectangle, uint32_t flags) { } if ((flags & ES_WINDOW_MOVE_DYNAMIC) - && (isMaximised == !!(flags & ES_WINDOW_MOVE_MAXIMISED) /* cannot queue resize if changing isMaximised */) + && (isMaximised == !!(flags & ES_WINDOW_MOVE_MAXIMIZED) /* cannot queue resize if changing isMaximised */) && windowManager.resizeWindow == this && windowManager.resizeStartTimeStampMs + RESIZE_FLICKER_TIMEOUT_MS > KGetTimeInMs()) { windowManager.resizeQueued = true; @@ -785,7 +785,7 @@ bool Window::Move(EsRectangle rectangle, uint32_t flags) { bool result = true; - isMaximised = flags & ES_WINDOW_MOVE_MAXIMISED; + isMaximised = flags & ES_WINDOW_MOVE_MAXIMIZED; alwaysOnTop = flags & ES_WINDOW_MOVE_ALWAYS_ON_TOP; // TS("Move window\n"); diff --git a/res/Theme Source.dat b/res/Theme Source.dat index d78f6a23df0c75339ea18da78b156d84774f370f..fb9ed109dad2fa4d8e927649277844492e873337 100644 GIT binary patch delta 1596 zcmYjReN0nV6z{!#Z7;akM-i>8!b5R=I6t0>WKlEAW->G~aJt#eZk7m>PCg3j(yDB0 z6@xO7y3=uH#*zcZf5Yd$xulRAw`BxhtgrJ`c19%gqeH}rcXLQC>BW#>3PPGK7b}m@8kE99K{AM1-bQT{FS$7W(-dC4+fJ>- zG99~=XVCfiA2V)|c^K@bOkI17CMZfBS_~MmDd;`U?eR#`o(zUfe^O`G6NVe=-t|;g z>5>zUw$Z0i?4b;=^y(LJ^ZNQ#}CKzLOewsq1WjiwvP3F61e z&*|S;(=4}od^J@sR5a@NgqzQjY>f7DLgL9Jq10_?5ix#&DmZ+aiexo3Ji7qne2F%Z zrQ->aN%)hQ%|`K|AY!neTJgE$YCttHboX=I$TGbJkCu{&48vAp2v)b!UK$- zp(SJ?j+%*`+`x(+YUd|;BH#V24))MF1SLf;qW1!iHQCE!-T9r09WkCGm5tl2+@Ux| z?`w32A@snH14V@4cpr6ktRM;oyXbsaS~eRei@2Y%f><$lkOO=cW+h$NW?^;=9_9%m z7AE2~{u6$knwr8%3(H5xBASM)GFb-JWilDR$>i0ZurMRqGC6J{iTk#nRttX_bvkf- zvJg*Qr+y6nNYmlvmvV6NX#-OeXX*9*MAtI5RL_UNhk*~HI=0lb*^58 zxsRIv71GEQ9Hq~ocOR4K4FVHKX|3<)PHXG+kpNL0`vT#)(}`G%**M`2=0|p05Vube;JuINYk02Pq;Nu^?~IvP?Ix1uA|qKOI8zlOuTY}h0={*V6k&PDkO%Yr zFkv`klyKmHz(C2iCPk8l?{7Djp>&>dJJ$?cbcr(_*TrkYsTnMb^i7v0LPfhDO7j`G Vw##bls%ebi#dL$Bx=xw8$$wh#NcjK& delta 1312 zcmZuwZ){Ul6yLpV-@Vrw6>a5RaNb9R8^gH!mlH(Gr@w3=opBRCP;Qg;k=Y8hbR-qAuMT7 zV#_)5F?2~0P~DY;9|OZYlIySbw}AezACp@p4p#;=P`0GZ#L<_cx!z!D4W#e)qdLro zbAR{js{v&q3WdQr=sgn6t=>EBh0c(loW?*c-3CFY5B9`TR*J*gn#iGS+{ngB_AkiK z`RUYpe7r!%jN&Lw6ZCZu4}MUP>WN5)$QZdB13tP5eD!V^_cqx3W_!PE#WGGe(;%pC zxnc2U25MVf<*e6RXT!VXJV!t?EV1h%jxe6RN;tmpqtuA)G1`LqYYq?gT(eZqX2^b_ z`en7F3H1aGV=_(?D5pflxizewG{VHnhYSsAFM;g4ZoDlc3YF(*!V*}~h-L!}C+MHB z`^IKNf1WxWwt!8y#=^N5DL2|*pe1V2v_|}oukMqSV=+Y)oBPFGrnJ@D5Zo4GJ38{f zza6c%n|)pOpuB8*z@<|{towuzvzys0yjVlVP(LGdPi9T4-*+x#VMmU!0K=zLEZS&XT*)~e@a$afN}6u z(HV86(M#3!cyXP0o8STN#-C?d z16~>896Mg8Dyna@4LF&h68dsXHoqVo&oK{7eJ_*WFpy(6p(X&#z9VixnWFuuy0~Ao zgr~om#AL?Bjovf#+Yv%yZHhxIr&unrB%@7XU0QDYcbf?YHwboUQPQyUJr>4=$0XIr zkMPq36JBvcdn1k}V}6opw;E~>jT1~RN`5SU#N7DGhpZFtO_F8|E{S_6jPM65z4OdrTsyEE`yZ*~v>3H>#~&3r%Lb^aC|>AaE`id~=&_xZC>n|yEdxBg zqO4&SYfthNCi{e4{Z7u{1ofgaBs_Ku5e{`u@!d^`!=*z$?4F_=es5LHH!T0aSO1Xe OvCD97Gm`uHDESACz}DOV diff --git a/res/Theme.dat b/res/Theme.dat index 5f23f84bcb061297c712010178bd4e9bcd26f1f3..249e7c0f8cb79e511004183e609bf58ff7ec2071 100644 GIT binary patch delta 4771 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 JY+dLX_&>TFKLr2) delta 4687 zcmZ9QZBSI#8OP5#+>2l!S+g61DH<3MR`$ZOxG3T-EU@yryj~Cj$csP(0fVibnAQkP znThRS27FA%PHBTPc7{x;BLg33BpK2%Eop3v9X`-0$zVff_+SzoZHBbO^nW+SEax!4 z<=+4E+~+*!IWL#x;ir81QyyJgHS_ZyGsbpqRquUmlJ&yGLN)_z7&I z&^jdNF=+2A-v!`kH-=A}duL(zQ-Hw;GzaYiNt=iEp|Z831!#X!f|#NNshe3XL;G96 zvkKZOv^xQs(Z?FJ->N|kj0Lfv&4)K2euRKQXq#HdON_NhqcK6t3jS_1M!*PY&ju?9 z_g#ss)XdF^PFUVi6~pOq@x0I)Rl|2vR6h8ELFQyDv@bDzt6E9Fr5!?m>Kj!3TD-4($yLesjW% zWu^2m_DgBP!l3qML1uRZEMG~MC}{tcG%K{Pr8G4fMg%7;Kad8R2CYTXT+n`~ zZY_w1?jnL0meZ0Y9~zfNQ3mZL$*+OL% zv}&e#Md|%Wif|j=`y}sqXf{b(fR-q2q-AJk$!`VPGm_sLv}eEVxAyTKUx&C$N`{?g z?0Zr`1=?;&3xW28v{Ovf9E=4E%WG2kBB8|u^ki&WD zx!}ED%E1FI6$1@CUVX&3ncbDJ+>s*GLpvlzXo7ZF@@uDZMCgI#<$!55aySPqbBi}; z1JFL)s_{X(iU=dHWJwXmpuHd9ZPeigv>eHAhVE}O_s+rcYJj(q!#uQCB=03?zmZ0^ z4DE>IcMn<~G^1^vg6q)AB~AH0V+Cr^lUp23G#p}fN5b?IsjDbx#Zm|j+G~Ltj+HdJ ziwGWAN&_u;!TF%|s{TX&|A}$d3T;C2>mf&|*?kTcT`J1}w0?D4K*pSnLaUPe#;8Bk z%x_G-5&F$@$=lJ4C!RtJ_#2^3Whu|U?3 z{mbwa>e^c$^wj-u`fzWw@WfG4Y#jOGG~Pq6#M${RdMi#B598=jToTWx#CV;brT%z3 zzm4l%^ym0=zTv+wqltJkd15V8Z`JrY`l;2%=l$B8)gxl}`Qs+<(|8vh+t(--zZF&> zXtX0i=Y9B$r@;hGj3>~~tO;TX0a@r$!I~Ch?J~esO{sb3u$@F^39=e_EU0WYCW?MxKP{&&h}-*VkGqii+LTL9g-6lE{!ALu zLdfR~<7aSpm@Ydb_?-XBm1+ttP{WPMW#})}-(RYkn(R;0k5ZG=nbg3@^9TF|UOJ$O zjRSN(J)74|79Y&vd}MMsEr*M>L&o^YWQy>27?~a>yy6~uP2iPu%xf28 zUVn#EUQJ!}8mkGbBec7_+hf!itL%t>86LqhJfiUh+?%PdAejDsB%Lz~&$WrlTsl>d zLZjhPe1IT7{04akav(-m3`k=H5w%9>Ya`C0(z6+o*MwF6yhOwz@)$R~ecZI_e+f;8B-4 zd(?PzM~02okA{h;YQF(v;AQkewa!QBchxt=K#hOTU#!6l*3i2(4Lo^r_X{x`RnMxu zi52*Dt*#vjdE@A-*ZF1Yum6S*PWB(G<6^ym9@SQ$9FE31G1o}1H=Y;P zCcjom%}sS;y@}p!I*(!uH=C)f*@I;{+^nmM&5SA3pB_VD$DKGSvyS(QrQ`I6;}txN zo@ud%r?nW9%h)5#PAg@FKaaQZ>6T8h&_W-#RB#_TT04=-M=iR#(u$)UbN?(Qw_8P7 z8-3o<0Pi>2>|(u*{@8XBbL4oj4%2z@#ZD1nfrYyd0*ErGEO>0TKe!z&Na2g%~-Q116k0tza4$Cy>jBgupDY z6eAfBTY?V37+3(-QVa+T01r-#QBYG3f1D2Op!W(s)rx^PmN*N=J diff --git a/shared/math.cpp b/shared/math.cpp index 72f960d..3b4a8a8 100644 --- a/shared/math.cpp +++ b/shared/math.cpp @@ -314,6 +314,8 @@ float EsCRTfabsf(float x) { } float EsCRTceilf(float x) { + if (x == 0) return x; + ConvertFloatInteger convert = {x}; uint32_t sign = convert.i & 0x80000000; int exponent = (int) ((convert.i >> 23) & 0xFF) - 0x7F; diff --git a/util/designer2.cpp b/util/designer2.cpp index 829836b..a149069 100644 --- a/util/designer2.cpp +++ b/util/designer2.cpp @@ -263,6 +263,7 @@ void InspectorPopulate(); void InspectorPickTargetEnd(); void CanvasSelectObject(struct Object *object); void CanvasSwitchView(void *cp); +Rectangle8 ExportCalculatePaintOutsets(Object *object); ////////////////////////////////////////////////////////////// @@ -1865,6 +1866,11 @@ void InspectorPopulate() { InspectorAddPreviewStateBitsCheckbox(cStateBitStrings[8], 1 << 7); UIParentPop(); UIParentPop(); + + Rectangle8 paintOutsets = ExportCalculatePaintOutsets(PropertyFindOrInheritReadObject(style, "appearance")); + char paintOutsetsText[256]; + snprintf(paintOutsetsText, sizeof(paintOutsetsText), "Paint outsets: %d, %d, %d, %d.", UI_RECT_ALL(paintOutsets)); + UILabelCreate(0, 0, paintOutsetsText, -1); } else { UILabelCreate(0, 0, "Select an object to inspect.", -1); } @@ -3012,16 +3018,30 @@ void ObjectAddCommand(void *) { UIMenuShow(menu); } +int ObjectCompareNames(const void *left, const void *right) { + return strcmp(((*(Object **) left))->cName, ((*(Object **) right))->cName); +} + void ObjectAddInstanceCommand(void *) { - UIMenu *menu = UIMenuCreate(window->pressed, 0); + Array styles = {}; for (uintptr_t i = 0; i < objects.Length(); i++) { if (objects[i].type == OBJ_STYLE) { - UIMenuAddItem(menu, 0, objects[i].cName, -1, ObjectAddInstanceCommandInternal, (void *) (uintptr_t) &objects[i]); + styles.Add(&objects[i]); } } + qsort(styles.array, styles.Length(), sizeof(Object *), ObjectCompareNames); + + UIMenu *menu = UIMenuCreate(window->pressed, 0); + + for (uintptr_t i = 0; i < styles.Length(); i++) { + Object *object = styles[i]; + UIMenuAddItem(menu, 0, object->cName, -1, ObjectAddInstanceCommandInternal, (void *) (uintptr_t) object); + } + UIMenuShow(menu); + styles.Free(); } void ObjectDeleteCommand(void *) {