From 3f81a8a3d48ba0131fc7914cb37dcaf3977b2973 Mon Sep 17 00:00:00 2001 From: D-AIRY <admin@ds-servers.com> Date: Thu, 16 Jan 2025 20:44:19 +0300 Subject: [PATCH] Allow using pivot to transform --- source/terrax/mainWindow.cpp | 21 ++++++++++-- source/terrax/resource.h | Bin 24580 -> 24580 bytes source/terrax/resource/toolbar1.bmp | Bin 1080 -> 1300 bytes source/terrax/resource/toolbar2.bmp | Bin 1080 -> 1320 bytes source/terrax/terrax.cpp | 51 ++++++++++++++++++++++++++++ source/terrax/terrax.h | 3 ++ 6 files changed, 72 insertions(+), 3 deletions(-) diff --git a/source/terrax/mainWindow.cpp b/source/terrax/mainWindow.cpp index 2b9b8270d..ab6b56873 100644 --- a/source/terrax/mainWindow.cpp +++ b/source/terrax/mainWindow.cpp @@ -2085,6 +2085,18 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) XSetXformType(X2DXF_ROTATE); break; + case ID_XFORM_MODE_CENTER: + g_xConfig.m_bUsePivot = false; + CheckToolbarButton(ID_XFORM_MODE_PIVOT, g_xConfig.m_bUsePivot); + CheckToolbarButton(ID_XFORM_MODE_CENTER, !g_xConfig.m_bUsePivot); + + break; + case ID_XFORM_MODE_PIVOT: + g_xConfig.m_bUsePivot = true; + CheckToolbarButton(ID_XFORM_MODE_PIVOT, g_xConfig.m_bUsePivot); + CheckToolbarButton(ID_XFORM_MODE_CENTER, !g_xConfig.m_bUsePivot); + break; + case IDC_TIE_TO_OBJECT: if(IsWindowEnabled(g_hButtonToEntityWnd)) { @@ -3418,7 +3430,7 @@ LRESULT CALLBACK RenderWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP { // create rotate command s_pRotateCmd = new CCommandRotate(GetKeyState(VK_SHIFT) < 0); - s_pRotateCmd->setStartOrigin((g_xState.vSelectionBoundMax + g_xState.vSelectionBoundMin) * 0.5f * vMask, float3(1.0f) - vMask); + s_pRotateCmd->setStartOrigin((g_xConfig.m_bUsePivot ? g_xState.vSelectionPivot : (g_xState.vSelectionBoundMax + g_xState.vSelectionBoundMin) * 0.5f) * vMask, float3(1.0f) - vMask); s_pRotateCmd->setStartPos(vStartPos); XEnumerateObjects([&](IXEditorObject *pObj, bool isProxy, ICompoundObject *pParent){ if(pObj->isSelected()/* && (g_xConfig.m_bIgnoreGroups ? !isProxy : !pParent)*/) @@ -4729,7 +4741,7 @@ void XUpdateGizmos() { if(Button_GetCheck(g_hABArrowButton) && g_xState.bHasSelection) { - float3 vPos = (g_xState.vSelectionBoundMin + g_xState.vSelectionBoundMax) * 0.5f; + float3 vPos = g_xConfig.m_bUsePivot ? g_xState.vSelectionPivot : (g_xState.vSelectionBoundMin + g_xState.vSelectionBoundMax) * 0.5f; g_pGizmoMove->setPos(vPos); if(!g_gizmoRotateCallback.isActive()) { @@ -4849,7 +4861,7 @@ HWND CreateToolbar(HWND hWndParent) { // Declare and initialize local constants. const int ImageListID = 0; - const int numButtons = 8; + const int numButtons = 10; const int bitmapSize = 16; const DWORD buttonStyles = BTNS_AUTOSIZE; @@ -4909,6 +4921,9 @@ HWND CreateToolbar(HWND hWndParent) {MAKELONG(1, ImageListID), ID_XFORM_TRANSLATE, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)"Move [W]"}, {MAKELONG(2, ImageListID), ID_XFORM_ROTATE, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)"Rotate [R]"}, {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, + {MAKELONG(8, ImageListID), ID_XFORM_MODE_CENTER, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)"Use center"}, + {MAKELONG(9, ImageListID), ID_XFORM_MODE_PIVOT, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)"Use pivot"}, + {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, {MAKELONG(6, ImageListID), ID_TOOLS_GROUP, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)"Group selected [Ctrl+G]"}, {MAKELONG(7, ImageListID), ID_TOOLS_UNGROUP, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)"Ungroup selected [Ctrl+U]"}, {MAKELONG(5, ImageListID), ID_IGNORE_GROUPS, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)"Toggle group ignore [Ctrl+W]"}, diff --git a/source/terrax/resource.h b/source/terrax/resource.h index bdbd2937659c1c2521c71074b5341ca191f4b3a6..8b0c2331f8a92e4071aab850ebda31aae84af055 100644 GIT binary patch delta 78 zcmZoUz}Rwtaf4mVWPxBFL0<-c1{VfbhIobm22X}C2LH()g=Hr@__Ix}i;+W9;mqL5 S;KvX$`Mv~L#pXLP8q5GcJ`}eA delta 50 zcmZoUz}Rwtaf4mV<PQ-d?CuQy3_%Q`lOI~iPj>KUn_L$o2NIub<f#VYZ@v?w!3+S^ CR}tv| diff --git a/source/terrax/resource/toolbar1.bmp b/source/terrax/resource/toolbar1.bmp index dbb1f0b437a3419ade41cafc9834107c00921d22..eb7529bf301a6746730ae4c975acc9601860c34a 100644 GIT binary patch literal 1300 zcmZ?r6=7ungCqt91`P%Vh6M}^4EziX42%pcVDU{X3=Bft5X{ZMzyQJ^iU0rqGyG>@ zU}ykg5CP-N|IcvXzyXGah6V<ZnhpeLhA^8Am@ObIbdrIAqoXY&4U9TEIvN-lIyyjh zF)%Q2Fq9X7m>eKI4Pdgv7;H?lWk<(k5UUj=1=hv^QP9BA!O)Qb5pC<}@Mus{=IDTE z?ciYVXa~uFxlrXG>pD7&LBb%SH3G!y=wRsRfG7Z&&5;3dS6fF%OM{ZKK?euegbt31 zii(Pk4v6s#V2z#4ogf<Iv<{HhTSGxyxOrf|fei+`s|99W16UPDMSBO-JdiKIVjx30 znrDF6ofaJ(t)UPHLfyvzawP-UeM-s(Z5=Kh5chR(lvi{hyN>~EX$NOVb4Mo!*kv6Z z9boey4uqQrW@IohFo4bL=xFHZFzDduXa|KHQuu*lt)rtE91hGNMIZ-qfZPXhAlMj? zw;>EBB?C~nfg+cqqoISN0~~T39OV@t6F49--qB&qY~0*z%xnP(4p6wZhK7P22r;IE z0TMA8OiBhF9R_WnK!lhH4mnV?fV4u)<3P9%9EdRgf&&o4JY$ZI29S9M5RX9J2Z>yW zc_0Z`_{{(XAtXM)&TC*`0H;5w`#PAEj2RdhAd%7G;sFakkY^jf=>-yg9UUNZIzZ`f z0)&YpemTHF4RN0b*Z@$-f&2^NfZYdjUPlKs{Y|!H1{n&94~RJ2za0z=4ICK|N3?+> z7h)bLrXl8mqNjra<Wx}FhvbhA17m1@1BV_cVnHbnVm63``Ue!bEg&a>#5f@4fpZHa zcYu5f&KjM}#-P~k=z!&4kX0aWfb?}B@-HZIA#nhbfSL!=33VPM&^kH{j6s<fqy`m3 Vt%VjZX)sApp#m;nAPf!$1^`%q@Av=! literal 1080 zcmZ?rwP0ZYgE9sN1`P%Vh6V-(27U$x21W*m#35z|1|e<;1}lUU4G_f*4PZSWvY~;2 z;lP0d3=JR#!+!=4V)*|bLNWXYF&X~<|Ibj403{G+i35u}goRErFtC>wsVjj|d3kvO z15|ebJ6NR)SX+rld3g(nRRtCVDPxByC}1yVC|8Gw7L}K$7o0f)(Fm1>80P{~03xcE zgIML|4CUnz1t2Tg)j<X_loyqkmld2j;s90xaYjW+1&9Z-x*X({s#PE^Tt7p3IRgXO zAh5k<aQz@xfmMPum6x=G*cI;O<yEU74uIOv0CEKb*#0v|9E!@*%Axi{3@zs<FDb8J z2isg;UJlj|aR6LDn4!+VzyQ`?US3dM4st&zRLjdtz(K(R5(GJb9b`Ym0bp$)Z$KD4 zXB<HO1_eGlST!gSl$X1(xRjK*u(%h1beESy^n)D$(N@j?2}pIGGY;kD4n?3q0GR;_ z6$W;M{op`=xgQ(=82Vk<%L_pIL5?p6>j&8h^M5-i2q57Hw!VOY0UZBO`^$OGxG*p< zKm#u=9i$)Z^>UED^73+*@&*VKNBFaYg9>7QI>=&3vMDcz#(#?k3&;>q_<>|W0SAgX zknch9uU-HSoFZ`GL-a$fhlECXxq}Nd{epcD*AFoa>|d}3P~ew=1R<#p<Z^J*t6*^f tg?@QCEd7I%E!Y^4YIypGSqD)Jl7a-ig9|9}gZQWzY7I2|DZwNe7yyqTjnDu9 diff --git a/source/terrax/resource/toolbar2.bmp b/source/terrax/resource/toolbar2.bmp index 5051572bc72dbbd0c0b1a1af2b48dcd827182f2d..e581a1f306259eb0cd1bb90037e55cad7a7a2a8e 100644 GIT binary patch delta 352 zcmdnNv4Ts*$ybAw0Sw9*7#K7d7#J2XFfi~lFfcGOuz<xku}oB%BmibYBtT65iQ60m z`2T|eKg0hIAO`=$Zw><d5J7$r`2YVu|70^p2LXPt{C|G_5C1{Z{FBQ-g8%s$`2YV0 zDTD}a0}Flt83s3U@;9&`NYQ_Oeg?4V{FBX?K$e3|1Brl4=bu~#5#;CR{|^!b*~CA2 z8<PV+|9^;?AX`5C|3CRFlOxFKAj7~4|MP>K$qX{`|Ns9VAi6>H<T98b$dw>3{^#eP YybUf0RSELtH)bbD5P?Dt96$^V0Q(M`WB>pF delta 99 zcmZ3%wSz;&$=8B~0Sw9*7#K7d7#JED7#R2&7#J8CAQFd|C#p=Ec+6q47^B1FG)9NX x+ZY`tvoSeL4r6kdyo||V@;4@j$!^RJlczB|On%1fFxia7VR9Rb!{lo$P5{l57>)n{ diff --git a/source/terrax/terrax.cpp b/source/terrax/terrax.cpp index 3b1fa6d3f..fe5e84fee 100644 --- a/source/terrax/terrax.cpp +++ b/source/terrax/terrax.cpp @@ -736,6 +736,8 @@ int main(int argc, char **argv) g_pXformEventChannel = pEngine->getCore()->getEventChannel<XEventEditorXformType>(EVENT_EDITOR_XFORM_TYPE_GUID); XSetXformType(X2DXF_SCALE); + CheckToolbarButton(ID_XFORM_MODE_PIVOT, g_xConfig.m_bUsePivot); + CheckToolbarButton(ID_XFORM_MODE_CENTER, !g_xConfig.m_bUsePivot); RECT rcTopLeft; GetClientRect(g_hTopLeftWnd, &rcTopLeft); @@ -945,6 +947,20 @@ int main(int argc, char **argv) } } + szVal = pCfg->getKey("terrax", "xform_use_pivot"); + if(szVal) + { + int iVal = 0; + if(sscanf(szVal, "%d", &iVal)) + { + g_xConfig.m_bUsePivot = iVal != 0; + CheckToolbarButton(ID_XFORM_MODE_PIVOT, g_xConfig.m_bUsePivot); + CheckToolbarButton(ID_XFORM_MODE_CENTER, !g_xConfig.m_bUsePivot); + } + } + + + for(UINT i = 0; i < 4; ++i) { float3 vec; @@ -1094,6 +1110,9 @@ int main(int argc, char **argv) sprintf_s(szVal, "%d", g_xConfig.m_bIgnoreGroups ? 1 : 0); pCfg->set("terrax", "ignore_groups", szVal); + + sprintf_s(szVal, "%d", g_xConfig.m_bUsePivot ? 1 : 0); + pCfg->set("terrax", "xform_use_pivot", szVal); pCfg->save(); mem_release(pCfg); @@ -2633,21 +2652,53 @@ void XUpdateSelectionBound() g_xState.bHasSelection = false; float3 vMin, vMax; + extern HWND g_hABArrowButton; + bool bTrackPivotObject = g_xConfig.m_bUsePivot && g_xState.activeWindow == XWP_TOP_LEFT && Button_GetCheck(g_hABArrowButton); + float fBestDist = FLT_MAX; + XEnumerateObjects([&](IXEditorObject *pObj, bool isProxy, ICompoundObject *pParent){ if(pObj->isSelected()/* && !(g_xConfig.m_bIgnoreGroups && isProxy)*/) { pObj->getBound(&vMin, &vMax); + + if(bTrackPivotObject) + { + // raytest + g_xState.vWorldRayStart; + g_xState.vWorldRayDir; + if(pObj->hasVisualModel()) + { + float3 vPos; + if(pObj->rayTest(g_xState.vWorldRayStart, g_xState.vWorldRayStart + g_xState.vWorldRayDir * 1000.0f, &vPos)) + { + float fDist2 = SMVector3Length2(g_xState.vWorldRayStart - vPos); + if(fDist2 < fBestDist) + { + fBestDist = fDist2; + g_xState.pPivotSource = pObj; + } + } + } + } + if(!g_xState.bHasSelection) { g_xState.bHasSelection = true; g_xState.vSelectionBoundMax = vMax; g_xState.vSelectionBoundMin = vMin; + g_xState.vSelectionPivot = pObj->getPos(); } else { g_xState.vSelectionBoundMax = (float3)SMVectorMax(g_xState.vSelectionBoundMax, vMax); g_xState.vSelectionBoundMin = (float3)SMVectorMin(g_xState.vSelectionBoundMin, vMin); } + + if(g_xState.pPivotSource == pObj) + { + g_xState.vSelectionPivot = pObj->getPos(); + } + return(XEOR_SKIP_CHILDREN); } return(XEOR_CONTINUE); diff --git a/source/terrax/terrax.h b/source/terrax/terrax.h index 5b96dbd41..0185bbc4a 100644 --- a/source/terrax/terrax.h +++ b/source/terrax/terrax.h @@ -92,6 +92,7 @@ struct CTerraXConfig bool m_bDottedGrid = false; float m_fGridOpacity = 0.5f; bool m_bIgnoreGroups = false; + bool m_bUsePivot = false; X_VIEWPORT_LAYOUT m_xViewportLayout = XVIEW_2X2; }; @@ -108,6 +109,8 @@ struct CTerraXState: public TerraXState bool bHasSelection = false; float3_t vSelectionBoundMin; float3_t vSelectionBoundMax; + float3_t vSelectionPivot; + IXEditorObject *pPivotSource = NULL; X_2DXFORM_TYPE xformType = X2DXF_SCALE; -- GitLab