Derma Kullanımına Giriş

Giriş

Bu, sizi Derma hakkında sıfır bilgiden alıp, tüm temel konular üzerinden geçirerek ilk kullanıcı arayüzü (UI) projenizi oluşturmak için sağlam bir temel atmayı amaçlayan bir dizi eğitimin ilkidir.

Garry's Mod'a özel Kullanıcı Arayüzleri (UI) dünyasına hoş geldiniz. Başlamadan önce net bir kelime dağarcığı tanımlayalım. Source motoru, varsayılan olarak kullanıcı arayüzünü VGUI (Valves Graphical User Interface) ve CPP kullanarak çizer. Garry's Mod'da ise Lua ve Derma kullanırız. Derma, Garry ve TAD2020 tarafından UI çizmeyi kolaylaştırmak için oluşturulmuştur. Arka planda, Lua kodumuz VGUI koduna erişerek UI elemanları oluşturmamızı, özelleştirmemizi ve yok etmemizi sağlar.

Bölüm 1: Panel (DPanel)

Paneller her şeyin köküdür, kullandığınız ve oluşturduğunuz diğer elemanların çoğu (hepsi değil) bu panellerden oluşacaktır. Motor, varsayılan olarak neredeyse hiçbir varsayılan özelliği olmayan "Panel" adında bir VGUI kontrolü sağlar. Derma, motor panelinden miras alırken işlevselliğini daha esnek olacak şekilde genişleten "DPanel" adlı bir kontrol sunar. Çoğu zaman DPanel kullanmak daha iyi olacaktır, bu yüzden odak noktamız bu olacak.

Panel Oluşturma

Bir paneli kullanmak için bir tane oluşturmanız gerekir. En yaygın yöntem vgui.Create'tir, şu şekilde:

local myFirstPanel = vgui.Create( "DPanel" )

Bu kod parçacığı Lua'da bir DPanel nesnesi oluşturur ve ona erişebilmemiz için myFirstPanel değişkeninde saklar. Daha sonra bu değişkeni fonksiyonları çalıştırmak veya aşağıdaki gibi özellikleri ayarlamak için kullanabiliriz:

  • Boyut - Panelin Genişliği ve Yüksekliği
  • Konum - Sol-üst köşenin nerede olduğu
  • Çizim Ayarları - Renk ve benzeri özellikler

Özellikleri Ayarlama

Paneller kendi başlarına pek bir anlam ifade etmezler, bunun yerine Lego tuğlaları gibi davranarak daha büyük bileşenler oluşturmak için birden fazla örneğini birleştirmenize ve bağlamanıza olanak tanırlar.

Daha önce de belirtildiği gibi, Panellerin Boyut, Konum ve Çizim Ayarları (daha sonra ele alacağımız Paint fonksiyonu olarak daha iyi bilinir) gibi özellikleri vardır. Derma'nın yaptığı şeylerden biri de bize bu özellikleri ayarlamak için Lua fonksiyonları sağlamaktır.

İşte onlarla deneme yapabilmeniz için daha yaygın fonksiyonlardan bazılarına bir örnek.

myFirstPanel:SetSize( 200, 100 ) -- Genişliği 200 piksel ve yüksekliği 100 piksel yapar myFirstPanel:SetPos( 50, 50 ) -- Paneli soldan 50 piksel, sonra üstten 50 piksel konumlandırır. myFirstPanel:Center() -- Paneli ebeveyninin merkezine taşır (konumlandırma için kullanışlıdır)

Bunlar oldukça açıklayıcı olmalı, ancak bu fonksiyonların sayıları nasıl kullandığını akılda tutmak önemlidir. Paneller sol üstten sağ alta doğru çizilir. Bu, :SetSize() kullandığınızda, sol üst pikselin konumunun aynı noktada kalacağı, sağ alt pikselin ise dışarı doğru fırlayacağı anlamına gelir. Aynı şey :SetPos() için de geçerlidir, bu fonksiyon sol üst pikseli ekrandaki yerel koordinatlara taşıyacaktır (ekranınızın sol üstü 0,0 olacak şekilde).

Bu fonksiyonlar okundukça yorumlanır. Eğer :Center() kullanıp ardından :SetSize( w, h ) kullanırsam, panel önce ortalanıp sonra boyutu değiştiği için ortalanmış görünmeyecektir.

Görünürlüğü Kontrol Etme

Bu bölümü okurken, gizli panelleri tespit etmenize yardımcı olması için vgui_visualizelayout 1 kullanın. Bu fonksiyon, paneller GÜNCELLENDİĞİNDE kırmızı renkte yanıp sönmesini sağlar.

Görünürlük, elemanlar içinde neyi görüp neyi göremediğinizi kontrol etmek için önemlidir. Derma bize basit bir komut olan Panel:SetVisible'i sağlar. Paneller, ebeveynlerinin durumuna göre otomatik olarak gösterilir ve gizlenir. Yani bir paneli gizlerseniz, tüm alt elemanları da gizlenir.

Bir panelin görünürlüğü, şeffaf bir panelden farklıdır. Şeffaf bir panel yine de güncellenir ve görünür gibi davranır, oysa gizli bir panel doğru şekilde güncellenmez.

bir DPanel, DPanel:SetPaintBackground kullanılarak şeffaf hale getirilebilir.

Sonuç

İşte bu kadar, başlamak için ihtiyacınız olan her şey. Bir sonraki bölüme başlamadan önce, Panel sınıfında bulunan farklı fonksiyonlarla denemeler yaparak nelerin mümkün olduğunu görün. İyi bir kontrol noktası, daha karmaşık alanlara geçmeden önce Panel:Remove ile oluşturulmuş panelleri nasıl kaldıracağınızı çözmektir.

İşte bu bölümde ele aldığımız her şeyi detaylandıran bir kod bloğu:

-- DPanel'i oluştur local myFirstPanel = vgui.Create( "DPanel" ) -- Boyutunu ayarla (Genişlik: 200px, Yükseklik: 100px) myFirstPanel:SetSize( 200, 100 ) -- Konumunu ayarla (X: Soldan 300px, Y: Üstten 200px) -- (Görünürlük için biraz farklı koordinatlar deniyoruz) myFirstPanel:SetPos( 300, 200 ) -- Arka planını boyamasını sağla myFirstPanel:SetPaintBackground( true ) -- Arka plan rengini mavi yap (R=0, G=0, B=255, Alfa=255) myFirstPanel:SetBackgroundColor( Color( 0, 0, 255, 255 ) ) -- Görünür olduğundan emin ol (genellikle gizli bir panele ebeveynlenmemişse varsayılan olarak görünürdür) myFirstPanel:SetVisible( true )

Bölüm 2: Etiketler ve Düğmeler (DLabel / DButton)

Son bölüm tamamen dikdörtgenler oluşturmakla ilgiliydi, ancak kullanıcı arayüzleri sadece dikdörtgenlerden oluşmaz. Arayüzümüzün metin içermesini ve onunla bir miktar etkileşim olmasını isteriz, işte bu noktada Etiketler ve Düğmeler devreye girer. Derma için bu elemanlar DLabel ve DButton'dır.

Şimdi bu elemanları kullanmaya başlamadan önce kalıtımı (inheritance) hatırlamak çok önemlidir. DLabel, Label adında motor tabanlı bir panelden türetilirken, DButton elemanı DLabel'dan türetilir. Bu kademeli kalıtımı hatırlamak önemlidir çünkü bu paneller içinde hangi fonksiyonlara erişip hangilerine erişemeyeceğinizi hatırlamanıza yardımcı olacaktır. Bu elemanların bir sonraki bölüme ayrılmasının nedeni budur.

İstisnalar olsa da, motor panelinden türeyen elemanlar genellikle düzen ve gruplama gibi şeyler için kullanılır. Motor etiket panelinden türeyen elemanlar ise daha çok fare etkileşimi için kullanılır.

Etiket Ekleme

Etiketlerimizi ve düğmelerimizi eklemeden önce bir temel panel oluşturalım:

-- Önceki örneklerde açıklanan fonksiyonlar netlik için yorumlanmayacaktır local myBasePanel = vgui.Create( "DPanel" ) myBasePanel:SetSize( 300, 150 ) myBasePanel:Center() myBasePanel:SetPaintBackground( true ) myBasePanel:SetBackgroundColor( Color( 0, 0, 255, 255 ) ) myBasePanel:MakePopup() -- Üstte kalmasını ve fareyi tıklamaları yakalamak için serbest bırakmasını sağlar.

Şimdi bir DLabel ekleyelim

local myTitleLabel = vgui.Create( "DLabel", myBasePanel ) -- İkinci argümanı kullanarak onu 'myBasePanel'e ebeveyn yapıyoruz -- Göstermesi gereken metni ayarla myTitleLabel:SetText( "My Awesome Panel" ) -- Konumunu myBasePanel'in sol-üst köşesine *göreceli* olarak ayarla myTitleLabel:SetPos( 10, 10 ) -- Etiketin genişliğini metne sığacak şekilde otomatik olarak ayarla myTitleLabel:SizeToContents() -- İsteğe bağlı: Metin rengini değiştir myTitleLabel:SetTextColor( color_white ) -- Beyaz rengi elde etmek için yerleşik varsayılan rengi kullanıyoruz

Panelinize metin eklemek gerçekten bu kadar basit!

Düğme Ekleme

Şimdi myBasePanel üzerine bir yere, paneli bizim için kapatacak bir DButton ekleyelim. Umarım Bölüm 1'de panel kaldırmayı tetiklemenin bir yolunu bulmuşsunuzdur, böylece bu, panel yönetimini kolaylaştıracaktır.

local myCloseButton = vgui.Create( "DButton", myBasePanel ) myCloseButton:SetText( "Close Me" ) -- Boyutunu ayarla (Düğmeler genellikle etiketimizi ayarladığımızın aksine belirli bir boyuta ihtiyaç duyar) myCloseButton:SetSize( 100, 30 ) -- Panelin sağ alt kısmına yakın konumlandır -- Konumu panelin boyutuna göre hesaplıyoruz local panelW, panelH = myBasePanel:GetSize() myCloseButton:SetPos( panelW - 110, panelH - 40 ) -- Sağ/alttan 10px boşluk -- ofset sayılarını 'boyut + boşluk' yaparak elde ettik,

Kolay! şimdi düğmemizi ayarladığımıza göre, tıklarsanız hiçbir şey yapmadığını fark edeceksiniz. Bunun nedeni, ilgili hook'larda herhangi bir davranış ayarlamamış olmamızdır.

DButton, metotlarını DLabel'dan miras aldığı ve DLabel'ın DLabel:DoClick metoduna sahip olduğu için, düğmemiz için o hook'u kullanabiliriz. Eğer bu tam olarak mantıklı gelmiyorsa, bu hook'u nasıl ve neden kullanabildiğimizi anlamak için bir an durup düşünün. Kontroller daha karmaşık hale geldikçe kalıtımı şimdi anlamak çok önemlidir.

Bu fonksiyonu myCloseButton panelimizin oluşturulmasının altında bir yerde tanımlayalım.

-- myCloseButton tıklandığında ne olacağını tanımla myCloseButton.DoClick = function( theButton ) -- 'theButton' tıklanan düğmedir (bu durumda myCloseButton) print( "Close button clicked!" ) -- Düğmenin tüm paneli kaldırmasını sağlayalım myBasePanel:Remove() end
fonksiyon şu şekilde de yazılabilir
function myCloseButton:DoClick() ... end

bu ikisi arasındaki tek fark Lua Self Anahtar Kelimesi'nin nasıl ele alındığıdır

Oluşturduğumuz düğme çok basittir, sadece mesajımızı yazdırır ve ardından temel panelimizi kaldırır, bu da onun ve tüm alt elemanlarının silinmek üzere işaretlenmesine neden olur.

Sonuç

Artık temel panel kontrolü hakkında daha da güçlü bir anlayışa sahip olmalısınız. Farklı şeyler yapan düğmeler oluşturarak denemeler yapın. Belki bir hesap makinesi? Düzen sistemini Bölüm 3'te ele alacağız.

Kodun tamamı şöyle görünür:

-- Önceki örneklerde açıklanan fonksiyonlar netlik için yorumlanmayacaktır local myBasePanel = vgui.Create( "DPanel" ) myBasePanel:SetSize( 300, 150 ) myBasePanel:Center() myBasePanel:SetPaintBackground( true ) myBasePanel:SetBackgroundColor( Color( 0, 0, 255, 255 ) ) myBasePanel:MakePopup() local myTitleLabel = vgui.Create( "DLabel", myBasePanel ) myTitleLabel:SetText( "My Awesome Panel" ) myTitleLabel:SetPos( 10, 10 ) myTitleLabel:SizeToContents() myTitleLabel:SetTextColor( color_white ) local myCloseButton = vgui.Create( "DButton", myBasePanel ) myCloseButton:SetText( "Close Me" ) myCloseButton:SetSize( 100, 30 ) local panelW, panelH = myBasePanel:GetSize() myCloseButton:SetPos( panelW - 110, panelH - 40 ) myCloseButton.DoClick = function( theButton ) print( "Close button clicked!" ) myBasePanel:Remove() end

Bölüm 3: Düzen Sistemi (Layout System)

Önceki bölümler tamamen eleman oluşturmakla ilgiliydi. Panel:SetPos kullanarak bazı temel konumlandırmaları ele alsak da, bu gerçekten sadece statik elemanlar için en iyi sonucu verir. Eğer katmanlı elemanlarınız varsa ve ebeveyn boyutunu değiştirirse, alt elemanları uygun şekilde güncelleyebilmek istersiniz.

PerformLayout

Panel:PerformLayout, düzen sisteminin bel kemiğidir. Bir panelin alt elemanlarını nasıl düzenleyeceğini bilmesi gerektiğinde bu hook çağrılır. Bu, panel oluşturma, yeniden boyutlandırma veya paneller eklendiğinde veya kaldırıldığında otomatik olarak çağrılabilir. Veya, Panel:InvalidateLayout ile manuel olarak çağrılabilir, ancak bu genellikle gerekli olmayacaktır.

Panel:PerformLayout'ı manuel olarak çağırmanıza asla gerek kalmayacak, sistem düzen geçersiz kılındıktan sonra her zaman sizin için çağıracaktır. Eğer bu yapılması gerekiyorsa, bunu Panel:InvalidateLayout'ı çağırarak yapın

Yaygın Düzen Teknikleri

Burada, PerformLayout hook'u içinde panellerimizi düzenlemenin en yaygın yollarından bazılarını inceleyelim.

1. Manuel Konumlandırma

Bunu zaten biliyorsunuz! Bu sadece istediğiniz kesin koordinatları ve boyutları belirtmeyi içerir. Bu, hassas kontrol sunar ancak uygulayabileceğiniz esnek veya dinamik tasarım miktarını sınırlar.

Bölüm 2'den Manuel Konumlandırma Örnekleri

myTitleLabel:SetPos( 10, 10 ) myCloseButton:SetPos( panelW - 110, panelH - 40 ) myCloseButton:SetSize( 100, 30 )

2. Yaslama (Docking)

Yaslama (Docking) çok güçlüdür. Alt elemana, ebeveyninin bir veya daha fazla kenarına yapışmasını ve mevcut geri kalan alanı doldurmasını söylersiniz.

Panel:Dock fonksiyonu, panelin nasıl yaslanacağını belirtmek için 1'den 5'e kadar sayılar alır. Ancak bu sayıların ne anlama geldiğini hatırlamak yerine, kodumuzu daha okunabilir hale getirmek için DOCK enum'ını kullanabiliriz.

Dock Enum'u Değer Açıklama
NODOCK 0 Yaslama
FILL 1 Diğer paneller tarafından alınmayan kalan alanın olabildiğince fazlasını doldur.
LEFT 2 Panelin yüksekliğini maksimize ederek ebeveynin sol duvarına yapış.
RIGHT 3 Panelin yüksekliğini maksimize ederek ebeveynin sağ duvarına yapış.
TOP 4 Genişliği maksimize ederek ebeveynin üst duvarına yapış.
BOTTOM 5 Genişliği maksimize ederek ebeveynin alt duvarına yapış.

Şimdi, bu yöntemi kullanırsanız, alt elemanları yaslama sırasının önemli olduğunu unutmamanız gerekir!

-- Temel paneli oluştur (önceki gibi) local myBasePanel = vgui.Create( "DPanel" ) myBasePanel:SetSize( 300, 150 ) myBasePanel:Center() myBasePanel:MakePopup() myBasePanel:SetPaintBackground( true ) myBasePanel:SetBackgroundColor( Color( 0, 50, 150, 255 ) ) -- Başlık Etiketini Oluştur local myTitleLabel = vgui.Create( "DLabel", myBasePanel ) myTitleLabel:SetText( "My Awesome Panel" ) myTitleLabel:SetTextColor( Color( 255, 255, 255, 255 ) ) myTitleLabel:SetTall( 25 ) -- Yaslama için sabit bir yükseklik ver myTitleLabel:Dock( TOP ) -- Üste yapış! -- Kapat Düğmesini Oluştur local myCloseButton = vgui.Create( "DButton", myBasePanel ) myCloseButton:SetText( "Close Me" ) myCloseButton:SetTall( 30 ) -- Yaslama için sabit bir yükseklik ver myCloseButton:Dock( BOTTOM ) -- Alta yapış! -- Düğme Eylemi (önceki gibi) myCloseButton.DoClick = function( theButton ) print( "Close button clicked!" ) myBasePanel:Remove() end

Bu kodu çalıştırdıktan sonra, başlık ve kapatma düğmelerinin ebeveyne göre otomatik olarak konumlandığını ve boyutlandığını fark edeceksiniz. Şimdi Panel:DockMargin ve Panel:DockPadding kullanarak bu fonksiyonların görünümünü iyileştirmeye devam edebiliriz. Margin, ebeveynin diğer alt elemanları arasındaki mesafeyi ifade eder. Padding, paneli doldurabileceği kenardan uzağa doğru küçültmeyi ifade eder. Eğer bu hala kafa karıştırıcıysa, işlevsellik aynı olduğu için web geliştirmedeki farkı araştırabilirsiniz.

myTitleLabel:DockMargin( 5, 5, 5, 0 ) -- Sol, Üst, Sağ, Alt boşluk myCloseButton:DockMargin( 5, 0, 5, 5 ) -- Sol, Üst, Sağ, Alt boşluk

3. İçeriğe Göre Boyutlandırma

Bazen, ebeveyni doldurmak yerine, ebeveynin alt elemanlarına göre küçülmesini istersiniz. İşte bu noktada Panel:SizeToContents ve Panel:SizeToChildren devreye girer. :SizeToContents() fonksiyonunu, metnine tam sığacak kadar büyük yapmak için DLabel'ımızda kullandığımız Bölüm 2'den hatırlayabilirsiniz. :SizeToChildren(), tüm panelin alt elemanlarının sınırlayıcı kutusunu (bounding box) hesapladığı ve boyutu bu sınırlayıcı kutuyu barındırabilecek minimum boyuta ayarladığı için bundan farklıdır.

-- Yalnızca bir etiket içeren bir panel hayal edin local container = vgui.Create( "DPanel" ) container:SetPos(100, 100) container:SetPaintBackground(true) container:SetBackgroundColor(Color(200, 200, 200, 255)) local label = vgui.Create( "DLabel", container ) label:SetText( "This text determines the panel size!" ) label:SetPos( 5, 5 ) -- Konteyner içinde konumlandır label:SizeToContents() -- Etiket metnine sığar -- Şimdi, konteyneri etikete sığdır container:SizeToChildren( true, true ) -- Genişliği ve yüksekliği yeniden boyutlandır

4. Hizalama

Bu fonksiyonlar, elemanları ebeveynleri tarafından ayrılan alan içinde konumlandırmaya yardımcı olur (genellikle yaslama veya bir boyut ayarladıktan sonra kullanılır). Örneğin, Panel:SetContentAlignment metni DLabel'ın sınırları içinde ortalardı. Birçok panel ayrıca, paneli ebeveyni içinde ortalayan Panel:Center gibi yardımcı fonksiyonlara sahiptir.

Diğer Hizalama Fonksiyonları:

Konteyner Panelleri ve Düzen Mantığı

Temel DPanel'in PerformLayout'u yalnızca manuel konumlandırmalara ve yaslamaya uysa da, özel konteyner panelleri çok daha akıllı PerformLayout fonksiyonlarına sahiptir.

  • DPanelList: PerformLayout'u, alt elemanları dikey olarak (bir liste gibi) düzenler ve aralığı otomatik olarak ekler.
  • DIconLayout: PerformLayout'u, alt elemanları bir ızgara şeklinde düzenler ve yatayda yer kalmadığında onları bir sonraki satıra kaydırır.
  • DForm Etiketleri ve kontrolleri genellikle ayar menüleri için kullanılan düzgün sıralar halinde düzenler.

Bu özel panelleri bir sonraki bölümde daha detaylı inceleyeceğiz.

Perde Arkası: Düzen Nasıl Gerçekleşir

  1. Tetikleyici: Verilen panelin düzenini geçersiz kılan bir şey olur
  2. Panel:PerformLayout Çağrısı
  3. Yürütme: :PerformLayout() hook'unda ne varsa yürütülür

Sonuç

Bu bölüm, düzen sisteminin nasıl çalıştığını ve bir kullanıcının panellerini organize etmek için kullanabileceği farklı yöntemleri ele almayı tamamladı.

Bir sonraki bölümde Özel Konteyner Panelleri'ni ele alacağız.

Bölüm 4: Konteyner Panelleri

Bölüm 3'te farklı düzen yöntemlerini ve :PerformLayout() hook'unu kullanarak elemanları düzenlemeyi ele aldık. Bu, düğmeler veya etiketler gibi şeyleri yerleştirmek için harika olsa da, uzun bir öğe listemiz varsa bu yöntemler hızla gereksiz hale gelebilir. İşte bu noktada konteyner panelleri kullanışlı hale gelir. Konteyner panelleri, diğer panellerden oluşan bir koleksiyonu tutmak ve organize etmek için özel olarak tasarlanmış panellerdir.

Popüler Konteyner Panelleri: DScrollPanel, DTileLayout, DIconLayout, DListLayout, DGrid, DDrawer

DScrollPanel ile Kaydırma

En popüler konteyner paneli DScrollPanel'dir. Bu panelin tek bir amacı vardır, alt elemanları arasında gezinmenizi sağlamak. Bunu, fare kaydırmalarını algılayarak veya alt elemanları kaydırma benzeri bir şekilde yeniden konumlandırmak için kullanılabilecek bir kaydırma çubuğu oluşturarak yapar.

Genellikle gerçek interaktif elemanlarınızı DScrollPanel'in kendisine eklemezsiniz. Bunun yerine, temel boş bir Panel oluşturur ve elemanlarınızı ona eklersiniz. Bu, DScrollPanel'in o görünmez gruplama panelini kaydırabilmesi ve tüm interaktif elemanları kaydırma sırasında birbirlerine göre göreceli konumlarında tutabilmesi içindir.

local frame = vgui.Create( "DFrame" ) frame:SetSize( 200, 250 ) frame:Center() frame:SetTitle( "Scroll Example" ) frame:MakePopup() local scroll = vgui.Create( "DScrollPanel", frame ) scroll:Dock( FILL ) local groupingPnl = vgui.Create( "DPanel", scroll ) groupingPnl:SetTall( 500 ) -- Gerçekten kaydırabilmemiz için uzun yap groupingPnl:Dock( FILL ) groupingPnl:SetPaintBackground( false ) -- görünmez olmasını istiyoruz -- Kaydırmak istediğiniz interaktif panelleri ekleyin for i = 1, 20 do local label = vgui.Create( "DLabel", groupingPnl ) label:SetText( "Item Number " .. i ) label:SetPos( 10, 5 + (i-1) * 20 ) -- groupingPnl *içinde* manuel olarak konumlandır label:SizeToContents() end

`DIconLayout` ile Izgara Düzenleri

Peki ya öğeleri bir masaüstündeki simgeler veya bir envanter ızgarasındaki öğeler gibi bir ızgarada düzenlemek isterseniz? DIconLayout bunun için tasarlanmıştır. Alt elemanlarını satırlar ve sütunlar halinde düzenler.

-- Ana çerçeveyi oluştur local frame = vgui.Create( "DFrame" ) frame:SetSize( 220, 200 ) -- Biraz daha geniş frame:Center() frame:SetTitle( "IconLayout Example" ) frame:MakePopup() -- Önce bir kaydırma paneli oluştur (DIconLayout varsayılan olarak kaydırmaz) local scroll = vgui.Create( "DScrollPanel", frame ) scroll:Dock( FILL ) -- DIconLayout'u kaydırma panelinin *içinde* oluştur local icons = vgui.Create( "DIconLayout", scroll ) icons:Dock( FILL ) icons:SetSpaceX( 5 ) -- Simgeler arası yatay boşluk icons:SetSpaceY( 5 ) -- Simgeler arası dikey boşluk icons:SetBorder( 5 ) -- İç kenar etrafındaki boşluk -- Öğeleri ekle (simgeleri temsil eden küçük düğmeler) for i = 1, 30 do local iconButton = vgui.Create( "DButton", icons ) -- Ebeveyn, simgeler düzenidir iconButton:SetText( i ) iconButton:SetSize( 40, 40 ) -- "Simgelere" bir boyut ver -- DIconLayout için AddItem çağırmaya gerek yok, sadece ebeveyni ayarla! -- DIconLayout, kendisine eklenen çocukları otomatik olarak algılar. end

Diğer Konteynerler (DListView, DForm, vb.)

Diğer özel konteynerler şunlardır:

  • DListView: Sütunlar ve satırlarla elektronik tablo benzeri görünümler oluşturur. Skor tabloları veya ayrıntılı listeler için harikadır. Öğe eklemek AddLine ve her sütun için veri belirtmeyi içerir.
  • DForm: Ayar menüleri oluşturmak için kullanışlıdır. Etiketleri ve kontrolleri (onay kutuları, metin girişleri gibi) düzgün sıralar halinde düzenlemeye yardımcı olur.
  • DCategoryList: Her biri diğer panelleri içeren, daraltılabilir kategoriler oluşturur.

Bunlar aynı prensipler üzerine kuruludur: Alt elemanlarını belirli şekillerde düzenlemek için özel PerformLayout fonksiyonlarına sahiptirler.

Sonuç

Çoğu eleman görünür olmak ve etkileşime girilmek üzere tasarlanmış olsa da, bazıları öyle değildir; bazıları, benzer kodun birden çok örneğini tek bir noktada toplayarak geliştiricilere çok zaman ve kod karmaşıklığından tasarruf sağlar.

Bir sonraki bölüm, panellerinizin güzel görünmesini sağlamak için "skinning" ve "painting" konularını ele alacaktır.

Bölüm 5: Görünüm (Skinning) ve Boyama (Painting)

Son bölümde konteyner panellerini ele aldığımıza göre, artık panelleri oluşturma, yönetme ve hareket ettirme ile ilgili tüm temel bilgilere sahibiz. Ancak henüz nasıl göründüklerini ele almadık. İşte bu noktada "painting" (boyama) ve "skinning" (görünüm) devreye girecek. Başlamadan önce bu iki terim arasındaki farkı bilmelisiniz. Painting, belirli bir paneli boyamayı ifade eder; bu genellikle Draw ve Surface gibi kütüphaneleri içerir. Skinning ise farklı bir yaklaşımdır; bu, GWEN gibi kütüphaneler kullanarak bir "skin" (görünüm) oluşturmayı ve boyama fonksiyonlarının referans alacağı UI sprite sheet'leri (arayüz resim dosyaları) oluşturmayı içerir.

Her birinin kendi güçlü ve zayıf yönleri vardır, ancak genel olarak, painting yapmak daha kolaydır ama her bir panel için ayrı ayrı yapılması gerekir. Skinning, başlangıçta daha fazla yatırım gerektirir ancak tüm elemanlarda tek bir yerden kontrol edilen tutarlı bir görünüm sağlayabilir.

Derma'da Çizim

Skinning, tüm paneller için "varsayılan" tutarlı bir görünüm sağlar. Painting, belirli bir panel için bu görünümü geçersiz kılmanıza olanak tanır. Bir paneli boyamak, ister bir skin'den ister başka bir kaynaktan gelsin, varsayılan görünümü her zaman geçersiz kılar.

Paint Fonksiyonu

Her bir panelin bir :Paint( w, h ) fonksiyonu olacaktır. Panel, nasıl görünmesi gerektiğini belirlemek için bunu kullanır. Bu hook, panelin görünür olduğu her karede çağrılır. Paint hook'u her zaman iki argümanla çağrılır: mevcut panelin genişliği ve yüksekliği (genellikle w ve h olarak belirtilir).

İşte bir Paint Hook'u oluşturmanın iki yoluna bir örnek Self Açık (Explicit)

PANEL.Paint = function( self, w, h ) ... end

veya self'in örtük (implicit) olması

function PANEL:Paint( w, h ) ... end

Her iki seçenek de doğrudur ve kişisel tercihe bağlıdır. Self kullanımı hakkında daha fazla bilgi için Beginner_Tutorial_Self konusuna bakın.

Boyama Sistemi

Çizim için kullanacağınız araçlar her zaman Surface kütüphanesinden gelecektir. Bu kütüphane, istediğiniz her türlü kullanıcı arayüzünü oluşturmak için ihtiyacınız olan her şeyi sağlar. Ancak bazen daha karmaşık görevleri surface'ta yapmak zor olabilir, bu yüzden Draw kütüphanesi oluşturulmuştur. Bu kütüphane hala altta surface kütüphanesini kullanır ancak daha kullanışlı fonksiyonlara ve arka planda daha karmaşık surface hileleri yapan fonksiyonlara sahiptir. Genel olarak, bir şey sadece surface'ta yapılabiliyorsa, onu surface'ta yapın. Eğer bir şey karmaşık ve surface'ta yapması zorsa, draw'ı kullanın.

Burada size surface'ta mevcut olan bazı (hepsi değil) fonksiyonları sunuyoruz:

Surface.SetDrawColor ve Surface.SetFont gibi fonksiyonlarımız olduğunu fark edeceksiniz. Bunun nedeni, surface'ın surface.DrawRect gibi diğer tüm fonksiyonlarda kullanmak üzere bu fonksiyonlardan gelen son girdiyi saklayarak çalışmasıdır. Surface kullanarak çizim yapmaya çalışmadan önce her zaman rengi veya fontu ayarlamak isteyeceksiniz, çünkü bunu yapmamak yanlış renk/font çizilmesine neden olabilir.

İşte draw ile kullanılabilen bazı (hepsi değil) fonksiyonlar:

Burada bu fonksiyonların kaynak kodunu incelerseniz, hepsinin sadece bir dizi surface fonksiyonu olduğunu görürsünüz. Bu fonksiyonları saf surface formatında yazabilir ve aynı sonuçları alabilirsiniz, ancak bu kütüphanenin amacı bu daha karmaşık surface taktiklerinin kolaylığı ve kullanım rahatlığıdır.

Görünüm (Skinning) Sistemi

Oluşturduğunuz her bir panelin bir boyama fonksiyonu olacaktır, ancak bunları sırf tutarlı bir görünüm elde etmek için neredeyse aynı surface ve draw fonksiyonlarıyla doldurmak inanılmaz derecede tekrarlayıcı ve israf olabilir.

İşte bu noktada Skin'ler (Görünümler) devreye girer. Her Skin, tüm standart Derma elemanları için varsayılan görünümü ve hissi tanımlar. Standartlaştırılmış renkler, fontlar veya hatta düğmeler, etiketler ve çerçeveler gibi farklı türdeki elemanlar için varsayılan boyama fonksiyonları içerir.

Bütün bunlar derma.SkinHook kullanılarak yapılır, bazen Derma_Hook kullanılır ki bu da ilk fonksiyon için süslü bir sarmalayıcıdır (wrapper) ancak burada bahsedilmeyi gerektirecek kadar sık kullanılır.

Birçok varsayılan derma panelinin boyama fonksiyonlarının içinde bu fonksiyonlardan birini şu şekilde yazılmış bulacaksınız:

derma.SkinHook( "Paint", "Button", self, w, h )

bu satır esasen mevcut skin'e bir düğme türü eleman için Paint işlemini nasıl gerçekleştireceğini sorar ve panel tablosunu ve boyutlarını iletir.

sonuç olarak skin içinde aşağıdaki fonksiyon çağrılır

function SKIN:PaintButton( panel, w, h ) ... end

Garry's Mod, varsayılan olarak bir skin ile gelir, default.lua skin'i. Bu, lua/skins/ içinde yer almaktadır. Bu skin hakkında daha ayrıntılı bir inceleme için Derma_Skin_Creation konusuna bakın.

Paint Hook'unu Kullanma

Önceki örneklerden aşağıdaki koda aşina olmalısınız:

-- Temel çerçeveyi oluştur local frame = vgui.Create( "DFrame" ) frame:SetSize( 200, 150 ) frame:Center() frame:SetTitle( "Custom Paint Example" ) frame:MakePopup() -- Standart bir DButton oluştur local myButton = vgui.Create( "DButton", frame ) myButton:SetText( "Hover or Click Me" ) myButton:SetSize( 160, 40 ) myButton:SetPos( 20, 40 ) -- Çerçeve içine konumlandır -- Temel eylem myButton.DoClick = function( btn ) print( "Button Clicked!" ) end

Şimdi, bu belirli düğmeye (myButton) farklı bir Paint fonksiyonu kullanmasını söyleyelim.

-- myButton için özel boyama fonksiyonumuzu tanımla myButton.Paint = function( panel, w, h ) -- 'panel' myButton'ın kendisidir -- 'w' düğmenin genişliğidir (160) -- 'h' düğmenin yüksekliğidir (40) -- Özel çizim kodumuz buraya gelecek! -- !! Önemli: Varsayılan metin çizimini durdurmak için true döndürün !! -- Eğer metni kendimiz çizersek, true döndürürüz. -- Eğer arka planımızdan sonra varsayılan skin'in metni çizmesini isteseydik, -- true döndürmezdik (veya false/nil döndürürdük). -- Bu örnek için, her şeyi kendimiz çizeceğiz. return true end

Doğrudan myButton.Paint'e yeni bir fonksiyon atadık. Artık her karede, Garry's Mod varsayılan DButton boyama mantığını (ki bu derma.SkinHook kullanır) çağırmak yerine, bizim fonksiyonumuzu çağıracak.

Çizim kodunu özel Paint fonksiyonumuzun içine ekleyelim. Şunları istiyoruz:

  • Normalde yeşil bir arka plan.
  • Üzerine gelindiğinde daha parlak yeşil bir arka plan.
  • Tıklandığında (basılı tutulduğunda) daha koyu yeşil bir arka plan.
  • Beyaz metin.
-- myButton için özel boyama fonksiyonumuzu tanımla myButton.Paint = function( panel, w, h ) -- Düğmenin durumunu kontrol et local isHovered = panel:IsHovered() local isDown = panel:IsDown() -- Duruma göre arka plan rengini belirle local bgColor if isDown then bgColor = Color( 0, 100, 0, 255 ) -- Koyu Yeşil elseif isHovered then bgColor = Color( 0, 200, 0, 255 ) -- Parlak Yeşil else bgColor = Color( 0, 150, 0, 255 ) -- Normal Yeşil end -- Arka plan dikdörtgenini çiz surface.SetDrawColor( bgColor ) surface.DrawRect( 0, 0, w, h ) -- Tüm paneli doldur (0,0'dan w,h'ye) -- Metni çiz surface.SetFont( "DermaDefault" ) surface.SetTextColor( Color( 255, 255, 255, 255 ) ) -- Beyaz -- Metni ortalamak için pozisyonunu hesapla local text = panel:GetText() -- Düğmenin metnini al local textW, textH = surface.GetTextSize( text ) local textX = (w - textW) / 2 local textY = (h - textH) / 2 surface.SetTextPos( textX, textY ) surface.DrawText( text ) -- Metin dahil her şeyi hallettik. Varsayılan çizimi durdur. return true end

Yeşil bir düğmesi olan bir pencere görmelisiniz. Farenizi üzerine getirdiğinizde parlak yeşile döner. Tıklayıp basılı tuttuğunuzda koyu yeşile döner. Metin baştan sona beyaz kalır. Varsayılan düğme görünümünü başarıyla geçersiz kıldınız!

Sonuç

Painting ve skinning konularını ele aldığımıza göre, Derma'ya giriş bilginizi tamamlamış bulunuyorsunuz. Umarız şimdiye kadar bazı temel UI elemanları oluşturmaya ve bunları kendi zevkinize göre özelleştirmeye başlamak için yeterli bilgi birikimine sahip olmuşsunuzdur.

Tebrikler ve Derma'ya hoş geldiniz!

Tüm sunucular · GmodTR Launcher · Rehber · GMod Wiki · GmodTR nedir? · Sunucu ekle · Discord