Repository navigation
Expand file tree
/
Copy pathUI.lua
More file actions
822 lines (691 loc) · 33.3 KB
/
Copy pathUI.lua
File metadata and controls
822 lines (691 loc) · 33.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
--[[
===========================================================================
Project Jaina - Gráficos HD & Opciones Avanzadas
Archivo: UI.lua
Interfaz visual moderna para control nativo de renderizado y fidelidad HD
===========================================================================
]]
ProjectJaina_Graphics = ProjectJaina_Graphics or {}
local WPG = ProjectJaina_Graphics
local BLANCO = "Interface\\Buttons\\WHITE8X8"
local c = WPG.Colors
-- Lista de controles para refresco dinámico
local UI_CONTROLS = {
checkboxes = {},
sliders = {},
shadowButtons = {},
apiButtons = {},
audioButtons = {}
}
-- ============================================================================
-- HELPERS DE ESTILO VISUAL (MOTOR FLAT DARK WOW PERÚ)
-- ============================================================================
local function CrearFondo(parent, color, alfa)
local t = parent:CreateTexture(nil, "BACKGROUND")
t:SetTexture(BLANCO)
t:SetVertexColor(color[1], color[2], color[3], alfa or 1)
t:SetAllPoints(parent)
return t
end
local function CrearBorde(parent, color, grosor)
color = color or c.borde
grosor = grosor or 1
local lados = {}
for _, lado in ipairs({ "TOP", "BOTTOM", "LEFT", "RIGHT" }) do
local t = parent:CreateTexture(nil, "BORDER")
t:SetTexture(BLANCO)
t:SetVertexColor(color[1], color[2], color[3], 1)
if lado == "TOP" or lado == "BOTTOM" then
t:SetHeight(grosor)
t:SetPoint(lado .. "LEFT")
t:SetPoint(lado .. "RIGHT")
else
t:SetWidth(grosor)
t:SetPoint("TOP" .. lado)
t:SetPoint("BOTTOM" .. lado)
end
lados[#lados + 1] = t
end
parent._bordes = lados
return lados
end
local function SetBordeColor(parent, color)
if parent._bordes then
for _, t in ipairs(parent._bordes) do
t:SetVertexColor(color[1], color[2], color[3], 1)
end
end
end
local function CrearPanel(parent, w, h, color)
local p = CreateFrame("Frame", nil, parent)
p:SetWidth(w)
p:SetHeight(h)
CrearFondo(p, color or c.panel, 0.92)
CrearBorde(p, c.borde, 1)
return p
end
local function EstilarBoton(btn, colorBorde, colorHover)
colorBorde = colorBorde or c.borde
colorHover = colorHover or c.oro
CrearFondo(btn, c.panelAlto, 1)
CrearBorde(btn, colorBorde, 1)
btn._colorBordeNormal = colorBorde
btn._colorHover = colorHover
btn:HookScript("OnEnter", function(self)
SetBordeColor(self, self._colorHover)
end)
btn:HookScript("OnLeave", function(self)
SetBordeColor(self, self._colorBordeNormal)
end)
end
-- ============================================================================
-- CREACIÓN DE LA VENTANA PRINCIPAL
-- ============================================================================
function WPG:CreateMainUI()
if WPG.MainFrame then return end
local f = CreateFrame("Frame", "ProjectJaina_Graphics_MainFrame", UIParent)
f:SetWidth(720)
f:SetHeight(570)
f:SetPoint("CENTER", UIParent, "CENTER", 0, 20)
f:SetMovable(true)
f:EnableMouse(true)
f:RegisterForDrag("LeftButton")
f:SetScript("OnDragStart", f.StartMoving)
f:SetScript("OnDragStop", f.StopMovingOrSizing)
f:SetClampedToScreen(true)
f:SetFrameStrata("DIALOG")
f:Hide()
-- Registrar para que ESC cierre la ventana
tinsert(UISpecialFrames, "ProjectJaina_Graphics_MainFrame")
-- Fondo y bordes exteriores de la ventana
CrearFondo(f, c.fondo, 0.96)
CrearBorde(f, c.borde, 2)
-- Cabecera / Barra de título
local header = CreateFrame("Frame", nil, f)
header:SetHeight(44)
header:SetPoint("TOPLEFT", f, "TOPLEFT", 0, 0)
header:SetPoint("TOPRIGHT", f, "TOPRIGHT", 0, 0)
CrearFondo(header, c.panelAlto, 1)
CrearBorde(header, c.borde, 1)
local title = header:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
title:SetPoint("LEFT", header, "LEFT", 16, 4)
title:SetText("|cFFFFD700Project Jaina|r |cFF00FFCCGráficos HD & Suite de Motores|r")
local subtitle = header:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
subtitle:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -2)
subtitle:SetText("Fidelidad visual nativa & Aceleración por Hardware · Vulkan 1.3 / ModernWoW / D3D9")
-- Botón de cerrar [X]
local closeBtn = CreateFrame("Button", nil, header, "UIPanelCloseButton")
closeBtn:SetPoint("RIGHT", header, "RIGHT", -6, 0)
closeBtn:SetScript("OnClick", function() f:Hide() end)
-- ========================================================================
-- BARRA DE PRESETS RÁPIDOS
-- ========================================================================
local presetBar = CreateFrame("Frame", nil, f)
presetBar:SetHeight(38)
presetBar:SetPoint("TOPLEFT", header, "BOTTOMLEFT", 12, -8)
presetBar:SetPoint("TOPRIGHT", header, "BOTTOMRIGHT", -12, -8)
CrearFondo(presetBar, c.panel, 0.85)
CrearBorde(presetBar, c.borde, 1)
local presetLabel = presetBar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
presetLabel:SetPoint("LEFT", presetBar, "LEFT", 12, 0)
presetLabel:SetText("|cFFFFD700Perfiles Rápidos:|r")
local function CrearBotonPreset(texto, presetKey, xOffset, colorHover)
local btn = CreateFrame("Button", nil, presetBar)
btn:SetWidth(170)
btn:SetHeight(24)
btn:SetPoint("LEFT", presetBar, "LEFT", xOffset, 0)
local fontStr = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
fontStr:SetPoint("CENTER")
fontStr:SetText(texto)
btn.text = fontStr
EstilarBoton(btn, c.borde, colorHover)
btn:SetScript("OnClick", function()
PlaySound("igMainMenuOptionCheat")
WPG:ApplyPreset(presetKey)
end)
return btn
end
CrearBotonPreset("Ultra HD Nativo", "ultra", 120, c.cian)
CrearBotonPreset("Raid 25 (120 FPS)", "raid", 300, c.oro)
CrearBotonPreset("Original Blizzard", "classic", 480, c.textoSuave)
-- ========================================================================
-- CONTENEDORES DE LAS 3 COLUMNAS TÉCNICAS
-- ========================================================================
local colW = 222
local colH = 410
local topY = -96
local col1 = CrearPanel(f, colW, colH)
col1:SetPoint("TOPLEFT", f, "TOPLEFT", 12, topY)
local col2 = CrearPanel(f, colW, colH)
col2:SetPoint("TOPLEFT", col1, "TOPRIGHT", 14, 0)
local col3 = CrearPanel(f, colW, colH)
col3:SetPoint("TOPLEFT", col2, "TOPRIGHT", 14, 0)
-- Cabeceras de columna
local function AddColHeader(col, text, color)
local h = col:CreateFontString(nil, "OVERLAY", "GameFontNormal")
h:SetPoint("TOPLEFT", col, "TOPLEFT", 10, -10)
h:SetText(color .. text .. "|r")
local sep = col:CreateTexture(nil, "ARTWORK")
sep:SetTexture(BLANCO)
sep:SetVertexColor(c.borde[1], c.borde[2], c.borde[3], 0.8)
sep:SetHeight(1)
sep:SetPoint("TOPLEFT", h, "BOTTOMLEFT", -2, -4)
sep:SetPoint("RIGHT", col, "RIGHT", -10, 0)
return sep
end
AddColHeader(col1, "1. Nitidez & Post-procesado", "|cFF00FFCC")
AddColHeader(col2, "2. Vegetación & Entorno", "|cFFFFD700")
AddColHeader(col3, "3. Sombras, Motor & Audio", "|cFF4CD964")
-- ========================================================================
-- COLUMNA 1: NITIDEZ Y POST-PROCESADO
-- ========================================================================
local function AddCheckbox(parent, labelText, cvar, invert, tooltipText, x, y)
local cbName = "WPG_CB_" .. cvar .. (invert and "_Inv" or "")
local cb = CreateFrame("CheckButton", cbName, parent, "UICheckButtonTemplate")
cb:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)
cb:SetWidth(22)
cb:SetHeight(22)
local label = _G[cbName .. "Text"]
label:SetFontObject("GameFontHighlightSmall")
label:SetText(labelText)
label:SetPoint("LEFT", cb, "RIGHT", 4, 1)
cb.cvar = cvar
cb.invert = invert
cb.tooltip = tooltipText
cb:SetScript("OnClick", function(self)
PlaySound("igMainMenuOptionCheckBoxOn")
local isChecked = self:GetChecked()
local val
if self.invert then
val = isChecked and "0" or "1"
else
val = isChecked and "1" or "0"
end
WPG:SetCVar(self.cvar, val)
end)
cb:SetScript("OnEnter", function(self)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetText(labelText, 1, 0.82, 0)
GameTooltip:AddLine(self.tooltip, 1, 1, 1, true)
GameTooltip:AddLine("CVar: " .. self.cvar, 0.5, 0.5, 0.5)
GameTooltip:Show()
end)
cb:SetScript("OnLeave", function() GameTooltip:Hide() end)
UI_CONTROLS.checkboxes[#UI_CONTROLS.checkboxes + 1] = cb
return cb
end
local yPos1 = -38
local ySpacing = -34
AddCheckbox(col1, "Nitidez Cristalina (Sin Blur)", "ffxGlow", true,
"Desactiva el resplandor lechoso borroso de 2008. Deja texturas de armaduras, armas y terreno nítidas al 100%.", 10, yPos1)
AddCheckbox(col1, "Claridad Estado Fantasma", "ffxDeath", true,
"Elimina la distorsión borrosa en blanco y negro al morir.", 10, yPos1 + ySpacing)
AddCheckbox(col1, "Sombras en el Terreno", "mapShadows", false,
"Proyecta sombras dinámicas sobre el relieve del terreno del mapa.", 10, yPos1 + ySpacing * 2)
AddCheckbox(col1, "Ondulaciones en Agua", "waterRipples", false,
"Activa ondulaciones físicas en el agua al caminar o nadar.", 10, yPos1 + ySpacing * 3)
AddCheckbox(col1, "Texturas Proyectadas", "projectedTextures", false,
"Muestra áreas de hechizos y círculos en el suelo.", 10, yPos1 + ySpacing * 4)
AddCheckbox(col1, "Brillo Especular de Armaduras", "specular", false,
"Reflejos de luz sobre metales pulidos y armaduras de placas.", 10, yPos1 + ySpacing * 5)
AddCheckbox(col1, "Optimización de Mallas M2", "M2Faster", false,
"Activa aceleración de renderizado en modelos tridimensionales.", 10, yPos1 + ySpacing * 6)
AddCheckbox(col1, "Objetos sin Desvanecimiento", "objectFade", true,
"Evita que objetos lejanos desaparezcan prematuramente.", 10, yPos1 + ySpacing * 7)
-- ========================================================================
-- COLUMNA 2: VEGETACIÓN Y ENTORNO (SLIDERS)
-- ========================================================================
local function AddSlider(parent, labelText, cvar, minVal, maxVal, stepVal, tooltipText, x, y)
local sName = "WPG_Slider_" .. cvar
local s = CreateFrame("Slider", sName, parent, "OptionsSliderTemplate")
s:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)
s:SetWidth(190)
s:SetHeight(15)
s:SetMinMaxValues(minVal, maxVal)
s:SetValueStep(stepVal)
local titleLabel = _G[sName .. "Text"]
titleLabel:SetFontObject("GameFontHighlightSmall")
titleLabel:SetText(labelText)
local lowLabel = _G[sName .. "Low"]
lowLabel:SetText(tostring(minVal))
lowLabel:SetFontObject("GameFontDisableSmall")
local highLabel = _G[sName .. "High"]
highLabel:SetText(tostring(maxVal))
highLabel:SetFontObject("GameFontDisableSmall")
local valLabel = s:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
valLabel:SetPoint("TOP", s, "BOTTOM", 0, -2)
s.valLabel = valLabel
s.cvar = cvar
s.tooltip = tooltipText
s.stepVal = stepVal
s:SetScript("OnValueChanged", function(self, value)
if self.stepVal and self.stepVal < 1 then
value = math.floor(value / self.stepVal + 0.5) * self.stepVal
self.valLabel:SetText(string.format("|cFF00FFCC%.1f|r", value))
WPG:SetCVar(self.cvar, string.format("%.1f", value))
else
if self.stepVal and self.stepVal > 1 then
value = math.floor(value / self.stepVal + 0.5) * self.stepVal
else
value = math.floor(value + 0.5)
end
if self.cvar == "maxFPS" and value == 0 then
self.valLabel:SetText("|cFF00FFCCIlimitado (0)|r")
elseif self.cvar == "maxFPS" then
self.valLabel:SetText("|cFF00FFCC" .. tostring(value) .. " FPS|r")
else
self.valLabel:SetText("|cFF00FFCC" .. tostring(value) .. "|r")
end
WPG:SetCVar(self.cvar, tostring(value))
end
end)
s:SetScript("OnEnter", function(self)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetText(labelText, 1, 0.82, 0)
GameTooltip:AddLine(self.tooltip, 1, 1, 1, true)
GameTooltip:AddLine("CVar: " .. self.cvar, 0.5, 0.5, 0.5)
GameTooltip:Show()
end)
s:SetScript("OnLeave", function() GameTooltip:Hide() end)
UI_CONTROLS.sliders[#UI_CONTROLS.sliders + 1] = s
return s
end
local yPos2 = -44
local sSpacing = -54
AddSlider(col2, "Densidad de Césped / Vegetación", "groundEffectDensity", 16, 256, 16,
"Multiplica la densidad de césped en el suelo. El menú clásico solo permite 64; aquí puedes subir a 256.", 16, yPos2)
AddSlider(col2, "Distancia de Vegetación", "groundEffectDist", 40, 140, 10,
"Distancia máxima a la que se dibuja el césped visible.", 16, yPos2 + sSpacing)
AddSlider(col2, "Distancia de Visión (Farclip)", "farclip", 300, 1277, 50,
"Distancia máxima de dibujo del terreno y estructuras.", 16, yPos2 + sSpacing * 2)
AddSlider(col2, "Detalle de Entorno (WMO)", "environmentDetail", 0.5, 1.5, 0.1,
"Nivel de detalle geométrico y distancia de estructuras en el mundo.", 16, yPos2 + sSpacing * 3)
AddSlider(col2, "Límite de FPS (0 = Ilimitado)", "maxFPS", 0, 240, 10,
"Tasa de cuadros por segundo máxima. 0 para FPS ilimitado; 120 o 144 para monitores de alta frecuencia.", 16, yPos2 + sSpacing * 4)
-- ========================================================================
-- COLUMNA 3: SOMBRAS, MOTOR Y AUDIO
-- ========================================================================
local yPos3 = -38
-- Selector de Sombras
local shTitle = col3:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
shTitle:SetPoint("TOPLEFT", col3, "TOPLEFT", 10, yPos3)
shTitle:SetText("|cFFFFD700Modo de Sombras Dinámicas:|r")
local function CrearBotonSombra(texto, sLevel, extQ, x, y, w)
local btn = CreateFrame("Button", nil, col3)
btn:SetWidth(w or 96)
btn:SetHeight(22)
btn:SetPoint("TOPLEFT", col3, "TOPLEFT", x, y)
local fontStr = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
fontStr:SetPoint("CENTER")
fontStr:SetText(texto)
btn.text = fontStr
btn.sLevel = sLevel
btn.extQ = extQ
EstilarBoton(btn, c.borde, c.verde)
btn:SetScript("OnClick", function(self)
PlaySound("igMainMenuOption")
WPG:SetCVar("shadowLevel", tostring(self.sLevel))
WPG:SetCVar("extShadowQuality", tostring(self.extQ))
WPG:Print("Sombras configuradas: " .. texto)
WPG:RefreshButtons()
end)
UI_CONTROLS.shadowButtons[#UI_CONTROLS.shadowButtons + 1] = btn
return btn
end
CrearBotonSombra("Desactivadas", 0, 0, 10, yPos3 - 20, 98)
CrearBotonSombra("Básicas (Óvalo)", 1, 0, 114, yPos3 - 20, 98)
CrearBotonSombra("Dinámicas", 1, 1, 10, yPos3 - 46, 98)
CrearBotonSombra("Avanzadas", 2, 1, 114, yPos3 - 46, 98)
-- Motor Gráfico Direct3D
local d3dTitle = col3:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
d3dTitle:SetPoint("TOPLEFT", col3, "TOPLEFT", 10, yPos3 - 82)
d3dTitle:SetText("|cFFFFD700Motor DirectX (gxApi):|r")
local function CrearBotonAPI(texto, apiVal, tooltipTitle, tooltipDesc, x, y)
local btn = CreateFrame("Button", nil, col3)
btn:SetWidth(98)
btn:SetHeight(22)
btn:SetPoint("TOPLEFT", col3, "TOPLEFT", x, y)
local fontStr = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
fontStr:SetPoint("CENTER")
fontStr:SetText(texto)
btn.text = fontStr
btn.apiVal = apiVal
EstilarBoton(btn, c.borde, c.cian)
btn:SetScript("OnClick", function(self)
PlaySound("igMainMenuOption")
WPG:SetCVar("gxApi", self.apiVal)
if self.apiVal == "D3D9Ex" then
WPG:Print("|cFFFF3333[AVISO GPU]|r D3D9Ex puede generar Error #132 en GPUs AMD Radeon bajo Windows 11 al componer texturas HD.")
else
WPG:Print("Motor gráfico asignado a: " .. self.apiVal .. " (Aplica tras reiniciar Wow.exe)")
end
WPG:RefreshButtons()
end)
btn:SetScript("OnEnter", function(self)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetText(tooltipTitle, 1, 0.82, 0)
GameTooltip:AddLine(tooltipDesc, 1, 1, 1, true)
GameTooltip:AddLine("CVar: gxApi " .. self.apiVal, 0.5, 0.5, 0.5)
GameTooltip:Show()
end)
btn:SetScript("OnLeave", function() GameTooltip:Hide() end)
UI_CONTROLS.apiButtons[#UI_CONTROLS.apiButtons + 1] = btn
return btn
end
CrearBotonAPI("D3D9 (Estable)", "D3D9", "Direct3D 9 Nativo (Recomendado)", "Modo estándar con gestión nativa de memoria D3DPOOL_MANAGED. Cero fallos de violación de acceso en AMD Radeon, Intel y NVIDIA.", 10, yPos3 - 102)
CrearBotonAPI("D3D9Ex (Inestable)", "D3D9Ex", "Direct3D 9Ex (No recomendado)", "|cFFFF3333PELIGRO DE CRASH:|r Causa 'Error #132 (Access Violation 0xC0000005)' en controladores AMD modernos (Radeon 780M) al bloquear texturas dinámicas de personajes.", 114, yPos3 - 102)
-- Canales de Sonido
local sndTitle = col3:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
sndTitle:SetPoint("TOPLEFT", col3, "TOPLEFT", 10, yPos3 - 138)
sndTitle:SetText("|cFFFFD700Canales de Sonido (Audio):|r")
local function CrearBotonCanales(canales, x, y)
local btn = CreateFrame("Button", nil, col3)
btn:SetWidth(62)
btn:SetHeight(22)
btn:SetPoint("TOPLEFT", col3, "TOPLEFT", x, y)
local fontStr = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
fontStr:SetPoint("CENTER")
fontStr:SetText(canales .. " Can.")
btn.text = fontStr
btn.canales = canales
EstilarBoton(btn, c.borde, c.oro)
btn:SetScript("OnClick", function(self)
PlaySound("igMainMenuOption")
WPG:SetCVar("Sound_NumChannels", tostring(self.canales))
WPG:Print("Canales de sonido ajustados a: " .. self.canales)
WPG:RefreshButtons()
end)
UI_CONTROLS.audioButtons[#UI_CONTROLS.audioButtons + 1] = btn
return btn
end
CrearBotonCanales(32, 10, yPos3 - 158)
CrearBotonCanales(64, 78, yPos3 - 158)
CrearBotonCanales(128, 146, yPos3 - 158)
-- Checkboxes de Columna 3
AddCheckbox(col3, "Audio en Segundo Plano", "Sound_EnableSoundWhenGameIsInBG", false,
"Permite escuchar el juego al minimizar o cambiar de ventana con Alt+Tab.", 10, yPos3 - 192)
AddCheckbox(col3, "Sincronización Vertical (VSync)", "gxVSync", false,
"Elimina cortes horizontales de pantalla fijando los FPS a la tasa de refresco.", 10, yPos3 - 224)
AddCheckbox(col3, "Triple Búfer (TripleBuffering)", "gxTripleBuffer", false,
"Evita caídas drásticas de FPS cuando VSync está activado.", 10, yPos3 - 256)
-- Botón de Reinicio de Motor Gráfico
local restartBtn = CreateFrame("Button", nil, col3)
restartBtn:SetWidth(198)
restartBtn:SetHeight(22)
restartBtn:SetPoint("TOPLEFT", col3, "TOPLEFT", 10, yPos3 - 294)
local rText = restartBtn:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
rText:SetPoint("CENTER")
rText:SetText("|cFFFFD700Reiniciar Motor (RestartGx)|r")
EstilarBoton(restartBtn, c.oro, c.cian)
restartBtn:SetScript("OnClick", function()
PlaySound("igMainMenuOption")
RestartGx()
WPG:Print("Motor gráfico reiniciado.")
end)
-- Botón Selector & Guía de Motores Gráficos de Jaina
local proxyBtn = CreateFrame("Button", nil, col3)
proxyBtn:SetWidth(198)
proxyBtn:SetHeight(22)
proxyBtn:SetPoint("TOPLEFT", col3, "TOPLEFT", 10, yPos3 - 322)
local pText = proxyBtn:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
pText:SetPoint("CENTER")
pText:SetText("|cFF00FFCCSuite de Motores Gráficos|r")
EstilarBoton(proxyBtn, c.cian, c.oro)
proxyBtn:SetScript("OnEnter", function(self)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetText("|cFFD4AF37Suite de Motores Gráficos de Jaina|r", 1, 0.82, 0)
GameTooltip:AddLine("Arquitectura de renderizado triple de Project Jaina:\n", 1, 1, 1)
GameTooltip:AddLine("|cFF00FF001. Vulkan 1.3 (DXVK 2.4.1):|r Máximo rendimiento sobre AMD Radeon 780M RDNA 3.", 0.9, 0.9, 0.9)
GameTooltip:AddLine("|cFF00FFCC2. ModernWoW Shaders:|r Niebla volumétrica y sombras PCF (F7 / F11 / F12).", 0.9, 0.9, 0.9)
GameTooltip:AddLine("|cFFFFD7003. Vanilla Direct3D 9:|r Estándar nativo universal sin proxies.", 0.9, 0.9, 0.9)
GameTooltip:AddLine("\n|cFF00FFCCHaz clic para abrir el panel técnico de motores.|r", 0, 1, 0.8)
GameTooltip:Show()
end)
proxyBtn:SetScript("OnLeave", function() GameTooltip:Hide() end)
-- Modal Interactiva de la Suite de Motores Gráficos
local mModal = CreateFrame("Frame", "ProjectJaina_Graphics_ModernModal", f)
mModal:SetWidth(580)
mModal:SetHeight(420)
mModal:SetPoint("CENTER", f, "CENTER", 0, 0)
mModal:SetFrameStrata("FULLSCREEN_DIALOG")
mModal:EnableMouse(true)
CrearFondo(mModal, c.fondo, 0.98)
CrearBorde(mModal, c.cian, 2)
mModal:Hide()
local mHeader = CreateFrame("Frame", nil, mModal)
mHeader:SetHeight(36)
mHeader:SetPoint("TOPLEFT", mModal, "TOPLEFT", 0, 0)
mHeader:SetPoint("TOPRIGHT", mModal, "TOPRIGHT", 0, 0)
CrearFondo(mHeader, c.panelAlto, 1)
CrearBorde(mHeader, c.borde, 1)
local mTitle = mHeader:CreateFontString(nil, "OVERLAY", "GameFontNormal")
mTitle:SetPoint("LEFT", mHeader, "LEFT", 14, 0)
mTitle:SetText("|cFFFFD700Project Jaina|r |cFF00FFCCSuite de Motores Gráficos (Vulkan / ModernWoW / D3D9)|r")
local mClose = CreateFrame("Button", nil, mHeader, "UIPanelCloseButton")
mClose:SetPoint("RIGHT", mHeader, "RIGHT", -4, 0)
mClose:SetScript("OnClick", function() mModal:Hide() end)
local mSub = mModal:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
mSub:SetPoint("TOPLEFT", mModal, "TOPLEFT", 16, -44)
mSub:SetPoint("TOPRIGHT", mModal, "TOPRIGHT", -16, -44)
mSub:SetJustifyH("LEFT")
mSub:SetText("Arquitectura gráfica multimodelo de Project Jaina: combina aceleración de última generación por hardware para el host y compatibilidad universal inmutable para el cliente público.")
-- Panel de los 3 Motores
local mEngines = CreateFrame("Frame", nil, mModal)
mEngines:SetHeight(154)
mEngines:SetPoint("TOPLEFT", mModal, "TOPLEFT", 16, -82)
mEngines:SetPoint("TOPRIGHT", mModal, "TOPRIGHT", -16, -82)
CrearFondo(mEngines, c.panel, 0.85)
CrearBorde(mEngines, c.borde, 1)
local eTitle = mEngines:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
eTitle:SetPoint("TOPLEFT", mEngines, "TOPLEFT", 12, -8)
eTitle:SetText("|cFFFFD700Motores Gráficos Oficiales Disponibles:|r")
local eDesc = mEngines:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
eDesc:SetPoint("TOPLEFT", eTitle, "BOTTOMLEFT", 0, -6)
eDesc:SetPoint("RIGHT", mEngines, "RIGHT", -12, 0)
eDesc:SetJustifyH("LEFT")
eDesc:SetText("|cFF00FF00[1] Modo Vulkan 1.3 (DXVK 2.4.1):|r Optimizado para AMD Ryzen 7 8700G (Radeon 780M RDNA 3). Delega las 23.8 GB de texturas a VRAM, compila shaders de forma asíncrona (8 hilos) y ofrece 120-144 FPS estables sin saturar el heap de 32 bits.\n\n|cFF00FFCC[2] Modo Cinematográfico (ModernWoWRenderer):|r Niebla volumétrica, oclusión SSAO y sombras PCF. Atajos in-game: |cFFFFD700[F7]|r Menú de ajustes | |cFFFFD700[F11]|r Alternar efectos | |cFFFFD700[F12]|r Recargar shaders.\n\n|cFFFFD100[3] Modo Vanilla Direct3D 9 Nativo:|r Estándar de Blizzard sin proxies. Estándar de la distribución pública con 100% de compatibilidad en laptops y GPUs Intel HD.")
-- Panel de Conmutación & Diagnóstico
local mStatus = CreateFrame("Frame", nil, mModal)
mStatus:SetHeight(100)
mStatus:SetPoint("TOPLEFT", mEngines, "BOTTOMLEFT", 0, -10)
mStatus:SetPoint("TOPRIGHT", mEngines, "BOTTOMRIGHT", 0, -10)
CrearFondo(mStatus, c.panelAlto, 0.9)
CrearBorde(mStatus, c.borde, 1)
local sTitle = mStatus:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
sTitle:SetPoint("TOPLEFT", mStatus, "TOPLEFT", 12, -8)
sTitle:SetText("|cFFFFD700Cómo Conmutar de Motor Gráfico (1 Clic):|r")
local sDesc = mStatus:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
sDesc:SetPoint("TOPLEFT", sTitle, "BOTTOMLEFT", 0, -6)
sDesc:SetPoint("RIGHT", mStatus, "RIGHT", -12, 0)
sDesc:SetJustifyH("LEFT")
sDesc:SetText("1. |cFF00FFCCDesde el Lanzador Oficial v2.1:|r Abre Ajustes (icono de engranaje) y selecciona el motor deseado en el selector interactivo antes de iniciar el juego.\n2. |cFF00FFCCDesde el Explorador de Windows:|r Ejecuta |cFFFFD700Activar_Modo_Vulkan.bat|r, |cFFFFD700Activar_Modo_Cinematografico_HD.bat|r o |cFFFFD700Activar_Modo_Vanilla_D3D9.bat|r en la carpeta raíz del cliente maestro.")
-- Botones de pie de modal
local btnCalib = CreateFrame("Button", nil, mModal)
btnCalib:SetWidth(200)
btnCalib:SetHeight(26)
btnCalib:SetPoint("BOTTOMLEFT", mModal, "BOTTOMLEFT", 16, 14)
local bct = btnCalib:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
bct:SetPoint("CENTER")
bct:SetText("|cFF00FFCCCalibrar CVars de Motor|r")
btnCalib.text = bct
EstilarBoton(btnCalib, c.cian, c.oro)
btnCalib:SetScript("OnClick", function()
PlaySound("igMainMenuOption")
WPG:SetCVar("gxApi", "D3D9")
WPG:SetCVar("extShadowQuality", "1")
WPG:SetCVar("shadowLevel", "2")
WPG:SetCVar("anisotropic", "16")
WPG:SetCVar("M2Faster", "1")
WPG:SetCVar("maxFPS", "144")
WPG:Print("|cFF00FFCC[Project Jaina]|r CVars calibradas (D3D9, 144 FPS, sombras dinámicas y filtrado 16x).")
WPG:RefreshButtons()
end)
local btnRestartModal = CreateFrame("Button", nil, mModal)
btnRestartModal:SetWidth(180)
btnRestartModal:SetHeight(26)
btnRestartModal:SetPoint("LEFT", btnCalib, "RIGHT", 12, 0)
local brmt = btnRestartModal:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
brmt:SetPoint("CENTER")
brmt:SetText("|cFFFFD700Reiniciar Motor (RestartGx)|r")
btnRestartModal.text = brmt
EstilarBoton(btnRestartModal, c.oro, c.cian)
btnRestartModal:SetScript("OnClick", function()
PlaySound("igMainMenuOption")
RestartGx()
WPG:Print("Motor gráfico reiniciado.")
end)
local btnCloseModal = CreateFrame("Button", nil, mModal)
btnCloseModal:SetWidth(110)
btnCloseModal:SetHeight(26)
btnCloseModal:SetPoint("RIGHT", mModal, "RIGHT", -16, 0)
btnCloseModal:SetPoint("BOTTOM", mModal, "BOTTOM", 0, 14)
local bcmt = btnCloseModal:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
bcmt:SetPoint("CENTER")
bcmt:SetText("Entendido")
btnCloseModal.text = bcmt
EstilarBoton(btnCloseModal, c.borde, c.cian)
btnCloseModal:SetScript("OnClick", function()
mModal:Hide()
end)
proxyBtn:SetScript("OnClick", function()
PlaySound("igMainMenuOption")
if mModal:IsShown() then
mModal:Hide()
else
mModal:Show()
end
end)
-- ========================================================================
-- BARRA INFERIOR / FOOTER
-- ========================================================================
local footer = CreateFrame("Frame", nil, f)
footer:SetHeight(38)
footer:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 12, 10)
footer:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -12, 10)
CrearFondo(footer, c.panelAlto, 1)
CrearBorde(footer, c.borde, 1)
-- Telemetría de FPS en tiempo real
local fpsText = footer:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
fpsText:SetPoint("LEFT", footer, "LEFT", 14, 0)
fpsText:SetText("FPS: -- | Memoria Lua: -- KB")
local elapsedTimer = 0
footer:SetScript("OnUpdate", function(self, elapsed)
elapsedTimer = elapsedTimer + elapsed
if elapsedTimer > 0.5 then
elapsedTimer = 0
local curFPS = math.floor(GetFramerate() or 0)
local memKB = math.floor(gcinfo() or 0)
fpsText:SetText(string.format("|cFF00FFCCFPS:|r %d |cFF60626B·|r |cFFFFD700Memoria:|r %d KB", curFPS, memKB))
end
end)
-- Botón Cerrar
local okBtn = CreateFrame("Button", nil, footer)
okBtn:SetWidth(140)
okBtn:SetHeight(24)
okBtn:SetPoint("RIGHT", footer, "RIGHT", -10, 0)
local okText = okBtn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
okText:SetPoint("CENTER")
okText:SetText("|cFFFFD700Cerrar y Guardar|r")
EstilarBoton(okBtn, c.oro, c.cian)
okBtn:SetScript("OnClick", function()
f:Hide()
end)
WPG.MainFrame = f
end
-- ============================================================================
-- REFRESCO DE BOTONES DE MODO (SOMBRAS, AUDIO, API)
-- ============================================================================
function WPG:RefreshButtons()
local sLevel = WPG:GetCVarNum("shadowLevel", 1)
local extQ = WPG:GetCVarNum("extShadowQuality", 0)
local curApi = WPG:GetCVar("gxApi", "D3D9")
local curSnd = WPG:GetCVarNum("Sound_NumChannels", 128)
-- Sombras
for _, btn in ipairs(UI_CONTROLS.shadowButtons) do
local isActive = (btn.sLevel == sLevel and btn.extQ == extQ)
if isActive then
btn._colorBordeNormal = c.verde
SetBordeColor(btn, c.verde)
btn.text:SetTextColor(c.verde[1], c.verde[2], c.verde[3], 1)
else
btn._colorBordeNormal = c.borde
SetBordeColor(btn, c.borde)
btn.text:SetTextColor(c.texto[1], c.texto[2], c.texto[3], 1)
end
end
-- API
for _, btn in ipairs(UI_CONTROLS.apiButtons) do
local isActive = (string.lower(btn.apiVal) == string.lower(curApi))
if isActive then
btn._colorBordeNormal = c.cian
SetBordeColor(btn, c.cian)
btn.text:SetTextColor(c.cian[1], c.cian[2], c.cian[3], 1)
else
btn._colorBordeNormal = c.borde
SetBordeColor(btn, c.borde)
btn.text:SetTextColor(c.texto[1], c.texto[2], c.texto[3], 1)
end
end
-- Audio
for _, btn in ipairs(UI_CONTROLS.audioButtons) do
local isActive = (btn.canales == curSnd)
if isActive then
btn._colorBordeNormal = c.oro
SetBordeColor(btn, c.oro)
btn.text:SetTextColor(c.oro[1], c.oro[2], c.oro[3], 1)
else
btn._colorBordeNormal = c.borde
SetBordeColor(btn, c.borde)
btn.text:SetTextColor(c.texto[1], c.texto[2], c.texto[3], 1)
end
end
end
-- ============================================================================
-- REFRESCO DE VALORES ACTUALES EN LOS CONTROLES
-- ============================================================================
function WPG:RefreshUI()
if not WPG.MainFrame then return end
-- Actualizar checkboxes
for _, cb in ipairs(UI_CONTROLS.checkboxes) do
local rawVal = WPG:GetCVar(cb.cvar)
local isEnabled
if cb.invert then
isEnabled = (rawVal == "0" or rawVal == 0)
else
isEnabled = (rawVal == "1" or rawVal == 1 or rawVal == "true")
end
cb:SetChecked(isEnabled)
end
-- Actualizar sliders
for _, s in ipairs(UI_CONTROLS.sliders) do
local numVal = WPG:GetCVarNum(s.cvar, 0)
s:SetValue(numVal)
if s.valLabel then
if s.cvar == "maxFPS" and numVal == 0 then
s.valLabel:SetText("|cFF00FFCCIlimitado (0)|r")
elseif s.cvar == "maxFPS" then
s.valLabel:SetText("|cFF00FFCC" .. tostring(numVal) .. " FPS|r")
elseif s.stepVal and s.stepVal < 1 then
s.valLabel:SetText(string.format("|cFF00FFCC%.1f|r", numVal))
else
s.valLabel:SetText("|cFF00FFCC" .. tostring(numVal) .. "|r")
end
end
end
-- Actualizar botones de modo activo
WPG:RefreshButtons()
end
-- ============================================================================
-- TOGGLE DE LA INTERFAZ
-- ============================================================================
function WPG:ToggleUI()
if not WPG.MainFrame then
WPG:CreateMainUI()
end
if WPG.MainFrame:IsShown() then
WPG.MainFrame:Hide()
else
WPG:RefreshUI()
WPG.MainFrame:Show()
end
end