Honorable Member Mali 41634 Posted December 12, 2022 Honorable Member Share Posted December 12, 2022 (edited) This is the hidden content, please Sign In or Sign Up This is the hidden content, please Sign In or Sign Up You can do things like these with it: Spoiler Spoiler Spoiler Reversed from 22.2.7.0 Official Binary. Experimental: Contains the modifications that I added that are not in the official. Edited December 14, 2022 by Mali 319 2 1 1 1 62 1 6 227 Link to comment Share on other sites More sharing options...
Management AZICKO 7320 Posted December 12, 2022 Management Share Posted December 12, 2022 Whew, I almost canceled maintenance for you... 3 1 5 Scamming ? Reselling ? metin2.download | metin2.dev | fr.metin2.dev | metin2dev.org | metin2.top | top-metin2.org Link to comment Share on other sites More sharing options...
Forum Moderator VegaS™ 10242 Posted December 12, 2022 Forum Moderator Share Posted December 12, 2022 Whew, I stopped kissing my wife when I saw the Mali post notification... 2 3 1 2 Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
CastielL 3 Posted December 12, 2022 Share Posted December 12, 2022 I will make a maintenance for this system. Link to comment Share on other sites More sharing options...
Premium CORKY 252 Posted December 13, 2022 Premium Share Posted December 13, 2022 Very nice release, as always quality. Thank you for the time and the contribution you've done to the community, I appreciate you a lot! 1 Link to comment Share on other sites More sharing options...
Honorable Member Mali 41634 Posted December 13, 2022 Author Honorable Member Share Posted December 13, 2022 (edited) Thanks for comments Edited March 12, 2023 by Mali 1 Link to comment Share on other sites More sharing options...
Active Member Valki 521 Posted December 13, 2022 Active Member Share Posted December 13, 2022 Nice release! 1 Link to comment Share on other sites More sharing options...
Premium masodikbela 1358 Posted December 16, 2022 Premium Share Posted December 16, 2022 (edited) Here is a little collab for the clipping, this extends the ExpandedImageBox, so you can scale/rotate those images and still be able to clip them. The code contains very informative comments so if you want to learn a few tricks you might want to read them. Spoiler In GrpExpandedImageInstance.cpp replace the whole Render function with this: void CGraphicExpandedImageInstance::OnRender(RECT* rMask) { // Okay so first we are gonna rework the code to use transofrmation matrix. // To do that we just have to touch the xyzs. This means we have to setup // them to match the original rectangle (without scaling rotation translation). // Just like how we would want to render the image to the left top corner // of the screen as it is in the file. // // We will obviously need the UVs so I'm not gonna touch that part, it has // nothing to do with the transformation matrix. // // The only thing is that the rotation and scaling is virtual so other codes // will not see the rect of the scaled/rotated eximagebox correctly so if you // want to put another image on such eximageboxes you will need extra logic, // perhabs the current structure for clipping will not be enough for that anyway. // // With the DEBUG_CLIPMASK macro you can highlight the parent window's rect. CGraphicImage* pImage = m_roImage.GetPointer(); CGraphicTexture* pTexture = pImage->GetTexturePointer(); const RECT& c_rRect = pImage->GetRectReference(); float texReverseWidth = 1.0f / float(pTexture->GetWidth()); float texReverseHeight = 1.0f / float(pTexture->GetHeight()); float su = (c_rRect.left - m_RenderingRect.left) * texReverseWidth; float sv = (c_rRect.top - m_RenderingRect.top) * texReverseHeight; float eu = (c_rRect.left + m_RenderingRect.right + (c_rRect.right - c_rRect.left)) * texReverseWidth; float ev = (c_rRect.top + m_RenderingRect.bottom + (c_rRect.bottom - c_rRect.top)) * texReverseHeight; // set up the vertex position in screen coordinates // the rendering rect is usually 0, only used for stuff like hp bar, // normal window base and so on, where you want to replicate the texture // multiple times (aka. wrap texture address mode). Since it will count // as the "part of the basic image box" we will add it here as well. // // The only trick we will apply that we will shift the wrapping to the // end positions instead of substracting them from the start positions, // since we want to base the original box to 0,0. We will adjust it on // the translation. float sx = 0.f; float sy = 0.f; float ex = float(pImage->GetWidth()) + m_RenderingRect.right + m_RenderingRect.left; float ey = float(pImage->GetHeight()) + m_RenderingRect.bottom + m_RenderingRect.top; TPDTVertex vertices[4]; vertices[0].position.x = sx; vertices[0].position.y = sy; vertices[0].position.z = 0.0f; vertices[0].texCoord = TTextureCoordinate(su, sv); vertices[0].diffuse = m_DiffuseColor; vertices[1].position.x = ex; vertices[1].position.y = sy; vertices[1].position.z = 0.0f; vertices[1].texCoord = TTextureCoordinate(eu, sv); vertices[1].diffuse = m_DiffuseColor; vertices[2].position.x = sx; vertices[2].position.y = ey; vertices[2].position.z = 0.0f; vertices[2].texCoord = TTextureCoordinate(su, ev); vertices[2].diffuse = m_DiffuseColor; vertices[3].position.x = ex; vertices[3].position.y = ey; vertices[3].position.z = 0.0f; vertices[3].texCoord = TTextureCoordinate(eu, ev); vertices[3].diffuse = m_DiffuseColor; // Now we are going to apply a transformation matrix that will // rotate/scale/transpose the vertices to the correct position. // // We can do it 2 different ways, either set up a world transform // so the GPU will do this for us for every vertex we stream to it, // or we can directly apply it here CPU side. // Since we have very few (4) vertices its better to do it here // since changing device states comes with some overhead, so its // better to do that only when its absolutely necessary or when // we can spare some cpu cycles by sending the work to the GPU. D3DXMATRIX transform, mTemp; D3DXMatrixScaling(&transform, m_v2Scale.x, m_v2Scale.y, 1.f); D3DXMatrixTranslation(&mTemp, -(ex - sx) / 2.f, -(ey - sy) / 2.f, 0.f); transform *= mTemp; D3DXMatrixRotationZ(&mTemp, D3DXToRadian(m_fRotation)); transform *= mTemp; D3DXMatrixTranslation(&mTemp, (ex - sx) / 2.f, (ey - sy) / 2.f, 0.f); transform *= mTemp; D3DXMatrixTranslation(&mTemp, m_v2Position.x - m_RenderingRect.left, m_v2Position.y - m_RenderingRect.top, 0.f); transform *= mTemp; for (size_t i = 0; i < 4; ++i) { const D3DXVECTOR2 pos(vertices[i].position.x, vertices[i].position.y); D3DXVECTOR4 out; D3DXVec2Transform(&out, &pos, &transform); vertices[i].position.x = out.x - 0.5f; vertices[i].position.y = out.y - 0.5f; } switch (m_iRenderingMode) { case RENDERING_MODE_SCREEN: case RENDERING_MODE_COLOR_DODGE: STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR); STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); break; case RENDERING_MODE_MODULATE: STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR); break; } // Since dx8 doesn't have clipping, we have to apply a bit of trickery here. // We are going to use stenciling. This requires to have space for stencil // information in the depth buffer, so you will need to ask the game to // create an appropriate depth buffer, by changing m_dwMinStencilBits to 1 // in D3D_CDeviceInfo::FindDepthStencilFormat. // Stencil buffer will store a custom value on every position you render to // and you can later compare it when rendering something else to drop specific // pixels to achieve various effects. // With this method it is possible to later extend the functionality since // you can basically clip any shape not just rectangle like with dx9 clipping. // This can be useful when your parent window is a rotated exImageBox and you // want to clip inside it. if (rMask) { // First of all we will draw a rectangle equal to the size of the parent // window's size. We don't need any texture pos or colour, so SPVertex // struct would be enough but I cba creating funcs for it so just go with // this one. TPDTVertex maskVertices[4]; maskVertices[0].position.x = float(rMask->left) - 0.5f; maskVertices[0].position.y = float(rMask->top) - 0.5f; maskVertices[0].position.z = 0.0f; maskVertices[1].position.x = float(rMask->right) - 0.5f; maskVertices[1].position.y = float(rMask->top) - 0.5f; maskVertices[1].position.z = 0.0f; maskVertices[2].position.x = float(rMask->left) - 0.5f; maskVertices[2].position.y = float(rMask->bottom) - 0.5f; maskVertices[2].position.z = 0.0f; maskVertices[3].position.x = float(rMask->right) - 0.5f; maskVertices[3].position.y = float(rMask->bottom) - 0.5f; maskVertices[3].position.z = 0.0f; // Normally nothing else uses stencil in the base game, but we will have to // clear the other stuff we set up in previous renders. STATEMANAGER.GetDevice()->Clear(0, NULL, D3DCLEAR_STENCIL, 0, 0.f, 0); // Now enable stenciling, and make it to fail always (so this random rectangle // wont show up in our rendertarget). const DWORD zWrite = STATEMANAGER.GetRenderState(D3DRS_ZWRITEENABLE); STATEMANAGER.SetRenderState(D3DRS_ZWRITEENABLE, FALSE); STATEMANAGER.SaveRenderState(D3DRS_STENCILENABLE, TRUE); #ifdef DEBUG_CLIPMASK maskVertices[0].diffuse = maskVertices[1].diffuse = maskVertices[2].diffuse = maskVertices[3].diffuse = 0x5F00FF00; STATEMANAGER.SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); STATEMANAGER.SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); #else STATEMANAGER.SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); STATEMANAGER.SetRenderState(D3DRS_STENCILFUNC, D3DCMP_NEVER); #endif STATEMANAGER.SetRenderState(D3DRS_STENCILREF, 1); // And now just render it just as a normal image. CGraphicBase::SetPDTStream(maskVertices, 4); CGraphicBase::SetDefaultIndexBuffer(CGraphicBase::DEFAULT_IB_FILL_RECT); STATEMANAGER.SetTexture(0, NULL); STATEMANAGER.SetTexture(1, NULL); STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 4, 0, 2); // After the render set up the stencil to only succeed on pixels we wrote 1 to. #ifdef DEBUG_CLIPMASK STATEMANAGER.SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); #else STATEMANAGER.SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); #endif STATEMANAGER.SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); STATEMANAGER.SetRenderState(D3DRS_ZWRITEENABLE, zWrite); } // set up min/magfilter for scaling, instantly restore mipfilter, we don't need mips DWORD minF, magF, mipF; STATEMANAGER.GetTextureStageState(0, D3DTSS_MINFILTER, &minF); STATEMANAGER.GetTextureStageState(0, D3DTSS_MAGFILTER, &magF); STATEMANAGER.GetTextureStageState(0, D3DTSS_MIPFILTER, &mipF); STATEMANAGER.SetBestFiltering(0); STATEMANAGER.SetTextureStageState(0, D3DTSS_MIPFILTER, mipF); // 2004.11.18.myevan.ctrl+alt+del ąÝşą »çżë˝Ă ƨ±â´Â ą®Á¦ if (CGraphicBase::SetPDTStream(vertices, 4)) { CGraphicBase::SetDefaultIndexBuffer(CGraphicBase::DEFAULT_IB_FILL_RECT); STATEMANAGER.SetTexture(0, pTexture->GetD3DTexture()); STATEMANAGER.SetTexture(1, NULL); STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 4, 0, 2); } //STATEMANAGER.DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, c_FillRectIndices, D3DFMT_INDEX16, vertices, sizeof(TPDTVertex)); ///////////////////////////////////////////////////////////// // reset filters STATEMANAGER.SetTextureStageState(0, D3DTSS_MINFILTER, minF); STATEMANAGER.SetTextureStageState(0, D3DTSS_MAGFILTER, magF); // And finally disable stenciling again. if (rMask) STATEMANAGER.RestoreRenderState(D3DRS_STENCILENABLE); switch (m_iRenderingMode) { case RENDERING_MODE_SCREEN: case RENDERING_MODE_COLOR_DODGE: case RENDERING_MODE_MODULATE: STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND); STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND); break; } } In StateManager.h add this function as public to the CStateManager class: LPDIRECT3DDEVICE8 GetDevice() { return m_lpD3DDev; } And last in GrpDetector.cpp search for m_dwMinStencilBits and set it to 1. Edited December 18, 2022 by masodikbela fix vertex positions for masking 1 12 The one and only UI programming guideline Link to comment Share on other sites More sharing options...
Honorable Member Mali 41634 Posted December 19, 2022 Author Honorable Member Share Posted December 19, 2022 #UPDATE: Experimental: CTextLine Cursor 4 5 Link to comment Share on other sites More sharing options...
DDC 19 Posted December 21, 2022 Share Posted December 21, 2022 (edited) Hello! Will emoji render inside parent? Edited December 21, 2022 by parasogcata Core X - External 2 Internal 1 Link to comment Share on other sites More sharing options...
Honorable Member Mali 41634 Posted December 22, 2022 Author Honorable Member Share Posted December 22, 2022 10 hours ago, DDC said: Hello! Will emoji render inside parent? Supports CGraphicImageInstance, yes 1 1 Link to comment Share on other sites More sharing options...
Active Member Valki 521 Posted December 23, 2022 Active Member Share Posted December 23, 2022 (edited) @ DDC Search for: #ifdef ENABLE_EMOJI_SYSTEM if (m_emojiVector.empty() == false) { for(auto& rEmo : m_emojiVector) { if (rEmo.pInstance) { rEmo.pInstance->SetPosition(fStanX + rEmo.x, (fStanY + 7.0) - (rEmo.pInstance->GetHeight() / 2)); rEmo.pInstance->Render(); } } } #endif in GrpTextInstance.cpp's ::Render function and change it like that: #ifdef ENABLE_EMOJI_SYSTEM if (m_emojiVector.empty() == false) { for(auto& rEmo : m_emojiVector) { if (rEmo.pInstance) { rEmo.pInstance->SetPosition(fStanX + rEmo.x, (fStanY + 7.0) - (rEmo.pInstance->GetHeight() / 2)); #if defined(__BL_CLIP_MASK__) if (pClipRect) rEmo.pInstance->Render(pClipRect); else rEmo.pInstance->Render(); #else rEmo.pInstance->Render(); #endif } } } #endif Edited December 23, 2022 by Valki 1 1 1 Link to comment Share on other sites More sharing options...
DDC 19 Posted December 23, 2022 Share Posted December 23, 2022 41 minutes ago, Valki said: @ DDC Search for: #ifdef ENABLE_EMOJI_SYSTEM if (m_emojiVector.empty() == false) { for(auto& rEmo : m_emojiVector) { if (rEmo.pInstance) { rEmo.pInstance->SetPosition(fStanX + rEmo.x, (fStanY + 7.0) - (rEmo.pInstance->GetHeight() / 2)); rEmo.pInstance->Render(); } } } #endif in GrpTextInstance.cpp's ::Render function and change it like that: #ifdef ENABLE_EMOJI_SYSTEM if (m_emojiVector.empty() == false) { for(auto& rEmo : m_emojiVector) { if (rEmo.pInstance) { rEmo.pInstance->SetPosition(fStanX + rEmo.x, (fStanY + 7.0) - (rEmo.pInstance->GetHeight() / 2)); #if defined(__BL_CLIP_MASK__) if (pClipRect) rEmo.pInstance->Render(pClipRect); else rEmo.pInstance->Render(); #else rEmo.pInstance->Render(); #endif } } } #endif Thank you! 1 Link to comment Share on other sites More sharing options...
DDC 19 Posted December 24, 2022 Share Posted December 24, 2022 (edited) @ masodikbelacan you help us with to update code for CWikiRenderTarget(binary part) with @ Maliclip masking? Edited December 24, 2022 by DDC Link to comment Share on other sites More sharing options...
Premium masodikbela 1358 Posted December 24, 2022 Premium Share Posted December 24, 2022 1 minute ago, DDC said: @ masodikbelacan you help us with to update code for CWikiRenderTarget with @ Maliclip masking? If its from the leaked AE wiki no, otherwise post the code and will do that. The one and only UI programming guideline Link to comment Share on other sites More sharing options...
DDC 19 Posted December 24, 2022 Share Posted December 24, 2022 (edited) void CGraphicWikiRenderTargetTexture::Render() const { const float sx = static_cast<float>(m_renderRect.left) - 0.5f + static_cast<float>(m_renderBox.left); const float sy = static_cast<float>(m_renderRect.top) - 0.5f + static_cast<float>(m_renderBox.top); const float ex = static_cast<float>(m_renderRect.left) + (static_cast<float>(m_renderRect.right) - static_cast<float>(m_renderRect.left)) - 0.5f - static_cast<float>(m_renderBox.right); const float ey = static_cast<float>(m_renderRect.top) + (static_cast<float>(m_renderRect.bottom) - static_cast<float>(m_renderRect.top)) - 0.5f - static_cast<float>(m_renderBox.bottom); const float texReverseWidth = 1.0f / (static_cast<float>(m_renderRect.right) - static_cast<float>(m_renderRect.left)); const float texReverseHeight = 1.0f / (static_cast<float>(m_renderRect.bottom) - static_cast<float>(m_renderRect.top)); const float su = m_renderBox.left * texReverseWidth; const float sv = m_renderBox.top * texReverseHeight; const float eu = ((m_renderRect.right - m_renderRect.left) - m_renderBox.right) * texReverseWidth; const float ev = ((m_renderRect.bottom - m_renderRect.top) - m_renderBox.bottom) * texReverseHeight; TPDTVertex pVertices[4]; pVertices[0].position = TPosition(sx, sy, 0.0f); pVertices[0].texCoord = TTextureCoordinate(su, sv); pVertices[0].diffuse = 0xffffffff; pVertices[1].position = TPosition(ex, sy, 0.0f); pVertices[1].texCoord = TTextureCoordinate(eu, sv); pVertices[1].diffuse = 0xffffffff; pVertices[2].position = TPosition(sx, ey, 0.0f); pVertices[2].texCoord = TTextureCoordinate(su, ev); pVertices[2].diffuse = 0xffffffff; pVertices[3].position = TPosition(ex, ey, 0.0f); pVertices[3].texCoord = TTextureCoordinate(eu, ev); pVertices[3].diffuse = 0xffffffff; if (SetPDTStream(pVertices, 4)) { CGraphicBase::SetDefaultIndexBuffer(CGraphicBase::DEFAULT_IB_FILL_RECT); STATEMANAGER.SetTexture(0, GetD3DRenderTargetTexture()); STATEMANAGER.SetTexture(1, NULL); STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE); STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 4, 0, 2); } } I think it's wiki from AE... but only for this part, i just don't understand how to use rect,vertices and StateManager! If you're refusing to update, i'll understand! Edited December 24, 2022 by DDC Link to comment Share on other sites More sharing options...
Premium masodikbela 1358 Posted December 24, 2022 Premium Share Posted December 24, 2022 (edited) 1 hour ago, DDC said: void CGraphicWikiRenderTargetTexture::Render() const { const float sx = static_cast<float>(m_renderRect.left) - 0.5f + static_cast<float>(m_renderBox.left); const float sy = static_cast<float>(m_renderRect.top) - 0.5f + static_cast<float>(m_renderBox.top); const float ex = static_cast<float>(m_renderRect.left) + (static_cast<float>(m_renderRect.right) - static_cast<float>(m_renderRect.left)) - 0.5f - static_cast<float>(m_renderBox.right); const float ey = static_cast<float>(m_renderRect.top) + (static_cast<float>(m_renderRect.bottom) - static_cast<float>(m_renderRect.top)) - 0.5f - static_cast<float>(m_renderBox.bottom); const float texReverseWidth = 1.0f / (static_cast<float>(m_renderRect.right) - static_cast<float>(m_renderRect.left)); const float texReverseHeight = 1.0f / (static_cast<float>(m_renderRect.bottom) - static_cast<float>(m_renderRect.top)); const float su = m_renderBox.left * texReverseWidth; const float sv = m_renderBox.top * texReverseHeight; const float eu = ((m_renderRect.right - m_renderRect.left) - m_renderBox.right) * texReverseWidth; const float ev = ((m_renderRect.bottom - m_renderRect.top) - m_renderBox.bottom) * texReverseHeight; TPDTVertex pVertices[4]; pVertices[0].position = TPosition(sx, sy, 0.0f); pVertices[0].texCoord = TTextureCoordinate(su, sv); pVertices[0].diffuse = 0xffffffff; pVertices[1].position = TPosition(ex, sy, 0.0f); pVertices[1].texCoord = TTextureCoordinate(eu, sv); pVertices[1].diffuse = 0xffffffff; pVertices[2].position = TPosition(sx, ey, 0.0f); pVertices[2].texCoord = TTextureCoordinate(su, ev); pVertices[2].diffuse = 0xffffffff; pVertices[3].position = TPosition(ex, ey, 0.0f); pVertices[3].texCoord = TTextureCoordinate(eu, ev); pVertices[3].diffuse = 0xffffffff; if (SetPDTStream(pVertices, 4)) { CGraphicBase::SetDefaultIndexBuffer(CGraphicBase::DEFAULT_IB_FILL_RECT); STATEMANAGER.SetTexture(0, GetD3DRenderTargetTexture()); STATEMANAGER.SetTexture(1, NULL); STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE); STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 4, 0, 2); } } I think it's wiki from AE... but only for this part, i just don't understand how to use rect,vertices and StateManager! If you're refusing to update, i'll understand! It is, and its already have clipping inside it, you can control it with the m_renderBox. The values in left, top, right and bottom of that m_renderBox will determine how much space have to be clipped from each side in pixel positions. I made a small visual presentation about clipping, more specifically about text clipping, but the theory behind it applys to every kind of texture clipping. Some additional good read about texture positions and texture rendering: Texture Coordinates, Directly Mapping Texels to Pixels Edited December 24, 2022 by Metin2 Dev Core X - External 2 Internal 1 2 The one and only UI programming guideline Link to comment Share on other sites More sharing options...
DDC 19 Posted December 24, 2022 Share Posted December 24, 2022 11 hours ago, masodikbela said: It is, and its already have clipping inside it, you can control it with the m_renderBox. The values in left, top, right and bottom of that m_renderBox will determine how much space have to be clipped from each side in pixel positions. I made a small visual presentation about clipping, more specifically about text clipping, but the theory behind it applys to every kind of texture clipping./cdn-cgi/mirage/e4db53991da469b6fa1052b1a4756dd7bd30d12f98891bc4fbd5449b77b3370a/1280/https://metin2.download/picture/3R234sCALcAFi5iv17gBHni4vZ9dsnHj/.png?width=1437&height=740 Some additional good read about texture positions and texture rendering: Texture Coordinates, Directly Mapping Texels to Pixels Nice tutorial! Thank you for your time! Link to comment Share on other sites More sharing options...
Premium filipw1 1920 Posted December 28, 2022 Premium Share Posted December 28, 2022 To get smooth scrolling like this in music, guild symbol selection (and maybe some custom systems you already have idk), just replace ListBoxEx class. Spoiler https://pastebin.com/MwRS82jG class ListBoxEx(Window): class Item(Window): def __init__(self): Window.__init__(self) def __del__(self): Window.__del__(self) def SetParent(self, parent): Window.SetParent(self, parent) self.parent = proxy(parent) def OnMouseLeftButtonDown(self): self.parent.SelectItem(self) def OnRender(self): if self.parent.GetSelectedItem() == self: self.OnSelectedRender() def OnSelectedRender(self): x, y = self.GetGlobalPosition() grp.SetColor(grp.GenerateColor(0.0, 0.0, 0.7, 0.7)) grp.RenderBar(x, y, self.GetWidth(), self.GetHeight()) def __init__(self): Window.__init__(self) self.viewItemCount = 10 self.basePos = 0 self.itemHeight = 16 self.itemStep = 20 self.selItem = 0 self.itemList = [] self.onSelectItemEvent = lambda *arg: None if localeInfo.IsARABIC(): self.itemWidth = 130 else: self.itemWidth = 100 self.scrollBar = None self.__UpdateSize() def __del__(self): Window.__del__(self) def __UpdateSize(self): height = self.itemStep * self.__GetViewItemCount() self.SetSize(self.itemWidth, height) def IsEmpty(self): if len(self.itemList) == 0: return 1 return 0 def SetItemStep(self, itemStep): self.itemStep = itemStep self.__UpdateSize() def SetItemSize(self, itemWidth, itemHeight): self.itemWidth = itemWidth self.itemHeight = itemHeight self.__UpdateSize() def SetViewItemCount(self, viewItemCount): self.viewItemCount = viewItemCount def SetSelectEvent(self, event): self.onSelectItemEvent = event def SetBasePos(self, basePos): if app.__BL_CLIP_MASK__: self.basePos = basePos curbp = self.basePos itemheight = self.itemStep * len(self.itemList) myheight = self.GetHeight() if itemheight < myheight: curbp = 0 fromPos = curbp curPos = 0 toPos = curbp + self.GetHeight() for item in self.itemList: if curPos + self.itemStep < fromPos or curPos > toPos: item.Hide() else: item.Show() item.SetPosition(0, curPos - fromPos) curPos += self.itemStep else: for oldItem in self.itemList[self.basePos:self.basePos + self.viewItemCount]: oldItem.Hide() self.basePos = basePos pos = basePos for newItem in self.itemList[self.basePos:self.basePos + self.viewItemCount]: (x, y) = self.GetItemViewCoord(pos, newItem.GetWidth()) newItem.SetPosition(x, y) newItem.Show() pos += 1 def GetItemIndex(self, argItem): return self.itemList.index(argItem) def GetSelectedItem(self): return self.selItem def SelectIndex(self, index): if index >= len(self.itemList) or index < 0: self.selItem = None return try: self.selItem = self.itemList[index] except: pass def SelectItem(self, selItem): self.selItem = selItem self.onSelectItemEvent(selItem) def RemoveAllItems(self): for item in self.itemList: item.Hide() self.selItem = None self.itemList = [] if self.scrollBar: self.scrollBar.SetPos(0) def RemoveItem(self, delItem): if delItem == self.selItem: self.selItem = None self.itemList.remove(delItem) def AppendItem(self, newItem): newItem.SetParent(self) newItem.SetSize(self.itemWidth, self.itemHeight) if app.__BL_CLIP_MASK__: newItem.SetClippingMaskWindow(self) pos = len(self.itemList) if self.__IsInViewRange(pos): (x, y) = self.GetItemViewCoord(pos, newItem.GetWidth()) newItem.SetPosition(x, y) newItem.Show() else: newItem.Hide() self.itemList.append(newItem) def SetScrollBar(self, scrollBar): scrollBar.SetScrollEvent(__mem_func__(self.__OnScroll)) self.scrollBar = scrollBar def __OnScroll(self): if app.__BL_CLIP_MASK__: self.SetBasePos(int(self.scrollBar.GetPos() * (self.__GetItemCount() - 1) * self.itemStep)) else: self.SetBasePos(int(self.scrollBar.GetPos() * self.__GetScrollLen())) def __GetScrollLen(self): scrollLen = self.__GetItemCount() - self.__GetViewItemCount() if scrollLen < 0: return 0 return scrollLen def __GetViewItemCount(self): return self.viewItemCount def __GetItemCount(self): return len(self.itemList) def GetItemViewCoord(self, pos, itemWidth): if localeInfo.IsARABIC(): return (self.GetWidth() - itemWidth - 10, (pos - self.basePos) * self.itemStep) else: return (0, (pos - self.basePos) * self.itemStep) def __IsInViewRange(self, pos): if pos < self.basePos: return 0 if pos >= self.basePos + self.viewItemCount: return 0 return 1 2 4 5 Link to comment Share on other sites More sharing options...
Honorable Member Mali 41634 Posted January 9, 2023 Author Honorable Member Share Posted January 9, 2023 (edited) #UPDATE: Experimental: Render Target Edited January 11, 2023 by Metin2 Dev Core X - External 2 Internal 3 1 1 Link to comment Share on other sites More sharing options...
m2mandi 2 Posted February 14, 2023 Share Posted February 14, 2023 (edited) Thanks for release, as always a wonderful work I have this problem, i don t know how to explain it, but here is a gif https://metin2.download/picture/iXaXaBjXVcEa69kbPqlmOnGA3d1KV8ZP/.gif Is there any way to make the small window inside the main window work with clipping mask? If a cancel the clipping mask for the main window, the small window work with no problem, here is a another gif https://metin2.download/picture/Lha1RPc5nAbgGnl6wU9GYJ26uE09HP73/.gif So.. this is how it should work? Or am I using it wrong? Edited February 14, 2023 by Metin2 Dev Core X - External 2 Internal 2 Link to comment Share on other sites More sharing options...
Honorable Member Mali 41634 Posted February 15, 2023 Author Honorable Member Share Posted February 15, 2023 10 hours ago, m2mandi said: Thanks for release, as always a wonderful work I have this problem, i don t know how to explain it, but here is a gif https://metin2.download/picture/iXaXaBjXVcEa69kbPqlmOnGA3d1KV8ZP/.gif Is there any way to make the small window inside the main window work with clipping mask? If a cancel the clipping mask for the main window, the small window work with no problem, here is a another gif https://metin2.download/picture/Lha1RPc5nAbgGnl6wU9GYJ26uE09HP73/.gif So.. this is how it should work? Or am I using it wrong? This system do not support what you are trying to do. You need to make some changes 1 Link to comment Share on other sites More sharing options...
bl1nd3r 42 Posted February 21, 2023 Share Posted February 21, 2023 Thank you. Will try it. Link to comment Share on other sites More sharing options...
Lima 1 Posted February 25, 2023 Share Posted February 25, 2023 dumb question here, how do you @ Mali get to have the client open and the live editing on vstudio? i cant find the option to get the proccess [10804] Metin2Debug.exe I am new to this, if there is a guide on this already, could you point it? I must admit this is a bit overwhelming to start Link to comment Share on other sites More sharing options...
Honorable Member Mali 41634 Posted April 8, 2023 Author Honorable Member Share Posted April 8, 2023 #UPDATE: Experimental: CBar3D Spoiler CODE: @ masodikbela GIF: @ Gurgarath 4 1 2 Link to comment Share on other sites More sharing options...
Recommended Posts