From: terencehill Date: Thu, 17 Jun 2010 00:22:40 +0000 (+0200) Subject: Implemented new collisions check algorithm when resizing, it seems working well on... X-Git-Tag: xonotic-v0.1.0preview~541^2~22^2 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=69d729db751eb6f671e174ecc7307b8b682d8fb4;p=xonotic%2Fxonotic-data.pk3dir.git Implemented new collisions check algorithm when resizing, it seems working well on every situation. Modified the panel aspect ratio handling too, it was causing troubles. Added a temporary debug mode hud_configure_checkcollisions_debug only to highlight bad behavior during the execution, there could be minor bugs to fix. --- diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc index 4cc3fa66e..3ef20f6cf 100644 --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@ -682,8 +682,6 @@ vector HUD_Panel_GetMinSize(float id) mySize_y = 0.25; // 0.25 * width, trial and error... break; } - if(!mySize_x && mySize_y) - mySize_x = 1/mySize_y; return mySize; } @@ -1038,135 +1036,114 @@ void HUD_Panel_SetPos(float id, vector pos) cvar_set(strcat("hud_", HUD_Panel_GetName(id), "_pos"), s); } -float HUD_Panel_CheckValidity_of_ResizeSuggestion(float id, vector mySize) -{ - vector oldSize; - oldSize = mySize; - - // copy pasta from SetPosSize: - // minimum panel size cap - mySize_x = max(0.025 * vid_conwidth, mySize_x); - mySize_y = max(0.025 * vid_conheight, mySize_y); - - if(id == 12) // some panels have their own restrictions, like the chat panel (which actually only moves the engine chat print around). Looks bad if it's too small. - { - mySize_x = max(17 * cvar("con_chatsize"), mySize_x); - mySize_y = max(2 * cvar("con_chatsize") + 2 * HUD_Panel_GetPadding(id), mySize_y); - } - - // cap against panel's own limits - vector minSize; - minSize = HUD_Panel_GetMinSize(id); // mySize_x at least minSize_x * mySize_y, and vice versa - - mySize_x = max(minSize_x * mySize_y, mySize_x); - mySize_y = max(minSize_y * mySize_x, mySize_y); - - if(mySize == oldSize) - return 1; - else - return 0; -} - // check if resize will result in panel being moved into another panel. If so, return snapped vector, otherwise return the given vector -vector HUD_Panel_CheckResize(float id, vector myPos, vector mySize, vector resizeorigin) -{ +vector HUD_Panel_CheckResize(float id, vector mySize, vector resizeorigin, float ratio) { float i; + float targBorder; vector targPos; vector targSize; - vector myCenter; - vector targCenter; - myCenter = '0 0 0'; // shut up fteqcc, there IS a reference - targCenter = '0 0 0'; // shut up fteqcc, there IS a reference + vector targEndPos; + vector dist; for (i = 0; i < HUD_PANEL_NUM; ++i) { if(i == id || !HUD_Panel_CheckActive(i)) continue; - targPos = HUD_Panel_GetPos(i) - '1 1 0' * HUD_Panel_GetBorder(id); - targSize = HUD_Panel_GetSize(i) + '2 2 0' * HUD_Panel_GetBorder(id); - - if(myPos_y + mySize_y < targPos_y) - continue; - if(myPos_y > targPos_y + targSize_y) - continue; - - if(myPos_x + mySize_x < targPos_x) - continue; - if(myPos_x > targPos_x + targSize_x) - continue; + targBorder = HUD_Panel_GetBorder(i); + targPos = HUD_Panel_GetPos(i) - '1 1 0' * targBorder; + targSize = HUD_Panel_GetSize(i) + '2 2 0' * targBorder; + targEndPos = targPos + targSize; - // OK, there IS a collision. - // - - // Now check some special cases - // If the resizeorigin is too close to the target panel on either axis, we do not want to perform any collision avoidance on that axis - float Check_X, Check_Y; - Check_X = Check_Y = 1; - // check upper/left edges of targ panel - if(fabs(targPos_x - resizeorigin_x) < 0.025 * vid_conwidth) - Check_X = 0; - if(fabs(targPos_y - resizeorigin_y) < 0.025 * vid_conheight) - Check_Y = 0; - // check lower/right edges of targ panel - if(fabs(resizeorigin_x - (targPos_x + targSize_x)) < 0.025 * vid_conwidth) - Check_X = 0; - if(fabs(resizeorigin_y - (targPos_y + targSize_y)) < 0.025 * vid_conheight) - Check_Y = 0; - - myCenter_x = myPos_x + 0.5 * mySize_x; - myCenter_y = myPos_y + 0.5 * mySize_y; - - targCenter_x = targPos_x + 0.5 * targSize_x; - targCenter_y = targPos_y + 0.5 * targSize_y; - - if(myCenter_x < targCenter_x && myCenter_y < targCenter_y) // top left (of target panel) + if (resizeCorner == 1) { - //if(!HUD_Panel_CheckValidity_of_ResizeSuggestion(id, eX * (targPos_x - myPos_x) + eY * (targPos_y - resizeorigin_y))) - // continue; + // check if this panel is on our way + if (resizeorigin_x < targPos_x) + continue; + if (resizeorigin_y < targPos_y) + continue; + if (targEndPos_x < resizeorigin_x - mySize_x) + continue; + if (targEndPos_y < resizeorigin_y - mySize_y) + continue; - if(myPos_x + mySize_x - targPos_x < myPos_y + mySize_y - targPos_y && Check_X) // push it to the side - mySize_x = targPos_x - myPos_x; - else if(Check_Y) // push it upwards - mySize_y = targPos_y - resizeorigin_y; + // there is a collision: + // detect which side of the panel we are facing is actually limiting the resizing + // (which side the resize direction finds for first) and reduce the size up to there + // + // dist is the distance between resizeorigin and the "analogous" point of the panel + // in this case resizeorigin (bottom-right point) and the bottom-right point of the panel + dist_x = resizeorigin_x - targEndPos_x; + dist_y = resizeorigin_y - targEndPos_y; + if (dist_y < 0 || dist_x / dist_y > ratio) + mySize_x = min(mySize_x, dist_x); + else + mySize_y = min(mySize_y, dist_y); } - else if(myCenter_x > targCenter_x && myCenter_y < targCenter_y) // top right + else if (resizeCorner == 2) { - //if(!HUD_Panel_CheckValidity_of_ResizeSuggestion(id, eX * (resizeorigin_x - (targPos_x + targSize_x)) + eY * (targPos_y - resizeorigin_y))) - // continue; + if (resizeorigin_x > targEndPos_x) + continue; + if (resizeorigin_y < targPos_y) + continue; + if (targPos_x > resizeorigin_x + mySize_x) + continue; + if (targEndPos_y < resizeorigin_y - mySize_y) + continue; - if(targPos_x + targSize_x - myPos_x < myPos_y + mySize_y - targPos_y && Check_X) // push it to the side - mySize_x = resizeorigin_x - (targPos_x + targSize_x); - else if(Check_Y) // push it upwards - mySize_y = targPos_y - resizeorigin_y; + dist_x = targPos_x - resizeorigin_x; + dist_y = resizeorigin_y - targEndPos_y; + if (dist_y < 0 || dist_x / dist_y > ratio) + mySize_x = min(mySize_x, dist_x); + else + mySize_y = min(mySize_y, dist_y); } - else if(myCenter_x < targCenter_x && myCenter_y > targCenter_y) // bottom left + else if (resizeCorner == 3) { - //if(!HUD_Panel_CheckValidity_of_ResizeSuggestion(id, eX * (targPos_x - resizeorigin_x) + eY * (resizeorigin_y - (targPos_y + targSize_y)))) - // continue; + if (resizeorigin_x < targPos_x) + continue; + if (resizeorigin_y > targEndPos_y) + continue; + if (targEndPos_x < resizeorigin_x - mySize_x) + continue; + if (targPos_y > resizeorigin_y + mySize_y) + continue; - if(myPos_x + mySize_x - targPos_x < targPos_y + targSize_y - myPos_y && Check_X) // push it to the side - mySize_x = targPos_x - resizeorigin_x; - else if(Check_Y) // push it upwards - mySize_y = resizeorigin_y - (targPos_y + targSize_y); + dist_x = resizeorigin_x - targEndPos_x; + dist_y = targPos_y - resizeorigin_y; + if (dist_y < 0 || dist_x / dist_y > ratio) + mySize_x = min(mySize_x, dist_x); + else + mySize_y = min(mySize_y, dist_y); } - else if(myCenter_x > targCenter_x && myCenter_y > targCenter_y) // bottom right + else if (resizeCorner == 4) { - //if(!HUD_Panel_CheckValidity_of_ResizeSuggestion(id, eX * (resizeorigin_x - (targPos_x + targSize_x)) + eY * (resizeorigin_y - (targPos_y + targSize_y)))) - // continue; + if (resizeorigin_x > targEndPos_x) + continue; + if (resizeorigin_y > targEndPos_y) + continue; + if (targPos_x > resizeorigin_x + mySize_x) + continue; + if (targPos_y > resizeorigin_y + mySize_y) + continue; - if(targPos_x + targSize_x - myPos_x < targPos_y + targSize_y - myPos_y && Check_X) // push it to the side - mySize_x = resizeorigin_x - (targPos_x + targSize_x); - else if(Check_Y) // push it upwards - mySize_y = resizeorigin_y - (targPos_y + targSize_y); + dist_x = targPos_x - resizeorigin_x; + dist_y = targPos_y - resizeorigin_y; + if (dist_y < 0 || dist_x / dist_y > ratio) + mySize_x = min(mySize_x, dist_x); + else + mySize_y = min(mySize_y, dist_y); } + if(cvar("hud_configure_checkcollisions_debug")) + drawfill(targPos + '1 1 0' * targBorder, targSize - '2 2 0' * targBorder, '1 1 0', .3, DRAWFLAG_NORMAL); } - return mySize; } -void HUD_Panel_SetPosSize(float id, vector resizeorigin) +void HUD_Panel_SetPosSize(float id) { + vector resizeorigin; + resizeorigin = panel_click_resizeorigin; vector mySize, myPos; if(resizeCorner == 1) { @@ -1196,9 +1173,26 @@ void HUD_Panel_SetPosSize(float id, vector resizeorigin) // cap against panel's own limits vector minSize; minSize = HUD_Panel_GetMinSize(id); // mySize_x at least minSize_x * mySize_y, and vice versa - - mySize_x = max(minSize_x * mySize_y, mySize_x); - mySize_y = max(minSize_y * mySize_x, mySize_y); + float fixedRatio; + if(!minSize_x && minSize_y) + { + minSize_x = 1/minSize_y; + fixedRatio = minSize_x; + mySize_x = max(minSize_x * mySize_y, mySize_x); + mySize_y = max(minSize_y * mySize_x, mySize_y); + } + else if(minSize_x && !minSize_y) // hybrid aspect ratio, currently supported only in one dimension + { + if (mySize_x/mySize_y < minSize_x) // resizing in x direction allows free aspect ratio + { + fixedRatio = minSize_x; + minSize_y = 1/minSize_x; + mySize_y = max(minSize_y * mySize_x, mySize_y); + mySize_x = max(minSize_x * mySize_y, mySize_x); + } + else + fixedRatio = -minSize_x; //negative so that it will be used ONLY after checkResize + } // collision testing| // -----------------+ @@ -1226,15 +1220,49 @@ void HUD_Panel_SetPosSize(float id, vector resizeorigin) mySize_x = min(vid_conwidth - myPos_x, mySize_x); mySize_y = min(vid_conheight - myPos_y, mySize_y); - if(cvar("hud_configure_checkcollisions")) - mySize = HUD_Panel_CheckResize(id, myPos, mySize, resizeorigin); + if(cvar("hud_configure_checkcollisions_debug")) + drawfill(myPos, mySize, '1 1 1', .2, DRAWFLAG_NORMAL); + // before checkresize, otherwise panel can be snapped partially inside another panel or panel aspect ratio can be broken if(cvar("hud_configure_grid")) { mySize_x = floor(mySize_x/cvar("hud_configure_grid_x") + 0.5) * cvar("hud_configure_grid_x"); mySize_y = floor(mySize_y/cvar("hud_configure_grid_y") + 0.5) * cvar("hud_configure_grid_y"); } + if (fixedRatio > 0) + { + // keep aspect ratio _MAXIMIZING_ the size + if (mySize_x / mySize_y > fixedRatio) + mySize_y = mySize_x / fixedRatio; + else + mySize_x = mySize_y * fixedRatio; + } + + if(cvar("hud_configure_checkcollisions")) + { + if (fixedRatio > 0) + { + mySize = HUD_Panel_CheckResize(id, mySize, resizeorigin, fixedRatio); + // restore again aspect ratio, _minimizing_ the size + if (mySize_x / mySize_y < fixedRatio) + mySize_y = mySize_x / fixedRatio; + else + mySize_x = mySize_y * fixedRatio; + } + else + { + mySize = HUD_Panel_CheckResize(id, mySize, resizeorigin, mySize_x / mySize_y); + if (fixedRatio < 0) + { + fixedRatio = -fixedRatio; + // restore again aspect ratio, _minimizing_ the size + if (mySize_x / mySize_y < fixedRatio) + mySize_y = mySize_x / fixedRatio; + } + } + } + // do another pos check, as size might have changed by now if(resizeCorner == 1) { myPos_x = resizeorigin_x - mySize_x; @@ -1250,6 +1278,10 @@ void HUD_Panel_SetPosSize(float id, vector resizeorigin) myPos_y = resizeorigin_y; } + if(cvar("hud_configure_checkcollisions_debug")) + if(cvar("hud_configure_checkcollisions")) + drawfill(myPos, mySize, '0 1 0', .3, DRAWFLAG_NORMAL); + string s; s = strcat(ftos(mySize_x/vid_conwidth), " ", ftos(mySize_y/vid_conheight)); cvar_set(strcat("hud_", HUD_Panel_GetName(id), "_size"), s); @@ -1408,10 +1440,13 @@ void HUD_Panel_Mouse() } } + if(cvar("hud_configure_checkcollisions_debug")) + drawfill(panelPos, panelSize, '1 0 0', .3, DRAWFLAG_NORMAL); + if(highlightedAction == 1) HUD_Panel_SetPos(i, mousepos - panel_click_distance); else if(highlightedAction == 2) - HUD_Panel_SetPosSize(i, panel_click_resizeorigin); + HUD_Panel_SetPosSize(i); } }