diff --git a/source/terrax/mainWindow.cpp b/source/terrax/mainWindow.cpp index 2b9b8270d6d0ea98f04ab754583d675e0cc27b04..ab6b568737a1f8b14722bf9d522b926ad95de81d 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 Binary files a/source/terrax/resource.h and b/source/terrax/resource.h differ diff --git a/source/terrax/resource/toolbar1.bmp b/source/terrax/resource/toolbar1.bmp index dbb1f0b437a3419ade41cafc9834107c00921d22..eb7529bf301a6746730ae4c975acc9601860c34a 100644 Binary files a/source/terrax/resource/toolbar1.bmp and b/source/terrax/resource/toolbar1.bmp differ diff --git a/source/terrax/resource/toolbar2.bmp b/source/terrax/resource/toolbar2.bmp index 5051572bc72dbbd0c0b1a1af2b48dcd827182f2d..e581a1f306259eb0cd1bb90037e55cad7a7a2a8e 100644 Binary files a/source/terrax/resource/toolbar2.bmp and b/source/terrax/resource/toolbar2.bmp differ diff --git a/source/terrax/terrax.cpp b/source/terrax/terrax.cpp index 3b1fa6d3fb060191c6c4b9660eeef39427c26d72..fe5e84feea376064c905a7c4a976e976873275ab 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 5b96dbd418c38ab00ac785374378010235d37cec..0185bbc4a1dc142404940dce31f3b53946d79143 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;