From d0b4e26c3755ae0cb023bcadda3e72f1c021920a Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Tue, 14 Jun 2022 00:40:31 +0300 Subject: [PATCH] panels: handle panel animation in render (bump protocol) --- src/game/g_map.pas | 50 ++------ src/game/g_net.pas | 2 +- src/game/g_netmsg.pas | 31 ++--- src/game/g_panel.pas | 152 +++++++++++-------------- src/game/renders/opengl/r_map.pas | 31 +++-- src/game/renders/opengl/r_textures.pas | 95 +++++++++++----- 6 files changed, 175 insertions(+), 186 deletions(-) diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 03c029f..54d22a1 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -959,11 +959,10 @@ end; function CreateTexture (RecName: AnsiString; Map: String; log: Boolean): Integer; var HName: AnsiString; - WAD, WADz: TWADFile; + WAD: TWADFile; WADName, ResName: String; - ResData, ReszData: Pointer; - ResLen, ReszLen: Integer; - cfg: TConfig; + ResData: Pointer; + ResLen: Integer; id: Integer; begin Result := -1; @@ -1000,40 +999,13 @@ end; begin if WAD.GetResource(ResName, ResData, ResLen, log) then begin - if IsWadData(ResData, ResLen) then - begin - WADz := TWADFile.Create(); - if WADz.ReadMemory(ResData, ResLen) then - begin - if WADz.GetResource('TEXT/ANIM', ReszData, ReszLen) then - begin - cfg := TConfig.CreateMem(ReszData, ReszLen); - if cfg <> nil then - begin - SetLength(Textures, Length(Textures) + 1); - Textures[High(Textures)].TextureName := RecName; - Textures[High(Textures)].FullName := WadName + ':' + ResName; - Textures[High(Textures)].FramesCount := cfg.ReadInt('', 'framecount', 0); - Textures[High(Textures)].Speed := cfg.ReadInt('', 'waitcount', 0); - Result := High(Textures); - TextNameHash.put(HName, result); - cfg.Free; - end; - FreeMem(ReszData); - end - end; - WADz.Free; - end - else - begin - SetLength(Textures, Length(Textures) + 1); - Textures[High(Textures)].FullName := WADName + ':' + ResName; - Textures[High(Textures)].TextureName := RecName; - Result := High(Textures); - TextNameHash.put(HName, result); - end; - FreeMem(ResData); - end + SetLength(Textures, Length(Textures) + 1); + Textures[High(Textures)].FullName := WADName + ':' + ResName; + Textures[High(Textures)].TextureName := RecName; + Result := High(Textures); + TextNameHash.put(HName, result); + end; + FreeMem(ResData); end; WAD.Free; end @@ -2601,7 +2573,7 @@ begin tp := g_Map_PanelByGUID(pguid); if (tp = nil) then exit; tp.NextTexture(AnimLoop); - if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelTexture(pguid, AnimLoop); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelTexture(pguid); end; diff --git a/src/game/g_net.pas b/src/game/g_net.pas index ab13a28..417be8b 100644 --- a/src/game/g_net.pas +++ b/src/game/g_net.pas @@ -21,7 +21,7 @@ uses e_log, e_msg, utils, ENet, Classes, md5, MAPDEF{$IFDEF USE_MINIUPNPC}, miniupnpc;{$ELSE};{$ENDIF} const - NET_PROTOCOL_VER = 188; + NET_PROTOCOL_VER = 189; NET_MAXCLIENTS = 24; NET_CHANS = 12; diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index 08fd9df..4ada394 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -181,7 +181,7 @@ procedure MH_SEND_ItemSpawn(Quiet: Boolean; IID: Word; ID: Integer = NET_EVERYON procedure MH_SEND_ItemDestroy(Quiet: Boolean; IID: Word; ID: Integer = NET_EVERYONE); procedure MH_SEND_ItemPos(IID: Word; ID: Integer = NET_EVERYONE); // PANEL -procedure MH_SEND_PanelTexture(PGUID: Integer; AnimLoop: Byte; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelTexture(PGUID: Integer; ID: Integer = NET_EVERYONE); procedure MH_SEND_PanelState(PGUID: Integer; ID: Integer = NET_EVERYONE); // MONSTER procedure MH_SEND_MonsterSpawn(UID: Word; ID: Integer = NET_EVERYONE); @@ -916,7 +916,7 @@ procedure MH_SEND_Everything(CreatePlayers: Boolean {= False}; ID: Integer {= NE begin result := false; // don't stop MH_SEND_PanelState(pan.guid, ID); // anyway, to sync mplats - if (pan.CanChangeTexture) then MH_SEND_PanelTexture(pan.guid, pan.LastAnimLoop, ID); + if (pan.CanChangeTexture) then MH_SEND_PanelTexture(pan.guid, ID); end; var @@ -1485,22 +1485,18 @@ end; // PANEL -procedure MH_SEND_PanelTexture(PGUID: Integer; AnimLoop: Byte; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelTexture(PGUID: Integer; ID: Integer = NET_EVERYONE); var TP: TPanel; begin TP := g_Map_PanelByGUID(PGUID); if (TP = nil) then exit; - with TP do - begin - NetOut.Write(Byte(NET_MSG_PTEX)); - NetOut.Write(LongWord(PGUID)); - NetOut.Write(FCurTexture); - NetOut.Write(FCurFrame); - NetOut.Write(FCurFrameCount); - NetOut.Write(AnimLoop); - end; + NetOut.Write(Byte(NET_MSG_PTEX)); + NetOut.Write(LongWord(PGUID)); + NetOut.Write(TP.FCurTexture); + NetOut.Write(TP.AnimTime); + NetOut.Write(TP.LastAnimLoop); g_Net_Host_Send(ID, True, NET_CHAN_LARGEDATA); end; @@ -2823,18 +2819,13 @@ end; // PANEL procedure MC_RECV_PanelTexture(var M: TMsg); -var - TP: TPanel; - PGUID: Integer; - Tex, Fr: Integer; - Loop, Cnt: Byte; + var TP: TPanel; PGUID, Tex: Integer; AnimTime: LongWord; Loop: Byte; begin if not gGameOn then Exit; PGUID := Integer(M.ReadLongWord()); Tex := M.ReadLongInt(); - Fr := M.ReadLongInt(); - Cnt := M.ReadByte(); + AnimTime := M.ReadLongWord(); Loop := M.ReadByte(); TP := g_Map_PanelByGUID(PGUID); @@ -2842,7 +2833,7 @@ begin begin // switch texture TP.SetTexture(Tex, Loop); - TP.SetFrame(Fr, Cnt); + TP.SetFrame(AnimTime); end; end; diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas index 58e7477..70d2cc1 100644 --- a/src/game/g_panel.pas +++ b/src/game/g_panel.pas @@ -26,7 +26,6 @@ type TLevelTexture = record TextureName: AnsiString; // as stored in wad FullName: AnsiString; // full path to texture // !!! merge it with TextureName - framesCount, speed: Byte; end; TLevelTextureArray = array of TLevelTexture; @@ -37,7 +36,6 @@ type ATextureID = array of record Texture: Cardinal; // Textures[Texture] - AnTex: TAnimState; end; PPanel = ^TPanel; @@ -49,6 +47,8 @@ type FAlpha: Byte; FBlending: Boolean; FTextureIDs: ATextureID; + FAnimTime: LongWord; + FAnimLoop: Boolean; mMovingSpeed: TDFPoint; mMovingStart: TDFPoint; mMovingEnd: TDFPoint; @@ -96,9 +96,7 @@ type procedure setSizeEndY (v: Integer); inline; public - FCurTexture: Integer; // Íîìåð òåêóùåé òåêñòóðû - FCurFrame: Integer; - FCurFrameCount: Byte; + FCurTexture: Integer; // Номер текущей текстуры FX, FY: Integer; FOldX, FOldY: Integer; FWidth, FHeight: Word; @@ -123,7 +121,7 @@ type destructor Destroy(); override; procedure Update(); - procedure SetFrame(Frame: Integer; Count: Byte); + procedure SetFrame(StartTime: LongWord); procedure NextTexture(AnimLoop: Byte = 0); procedure SetTexture(ID: Integer; AnimLoop: Byte = 0); function GetTextureID(): Cardinal; @@ -196,10 +194,11 @@ type property isGLift: Boolean read getIsGLift; property isGBlockMon: Boolean read getIsGBlockMon; - (* private state *) property Alpha: Byte read FAlpha; property Blending: Boolean read FBlending; property TextureIDs: ATextureID read FTextureIDs; + property AnimTime: LongWord read FAnimTime; + property AnimLoop: Boolean read FAnimLoop; public property movingSpeed: TDFPoint read mMovingSpeed write mMovingSpeed; @@ -282,8 +281,6 @@ begin FOldH := Height; FAlpha := 0; FBlending := False; - FCurFrame := 0; - FCurFrameCount := 0; LastAnimLoop := 0; mapId := PanelRec.id; @@ -304,7 +301,7 @@ begin mNeedSend := false; -// Òèï ïàíåëè: +// Тип панели: PanelType := PanelRec.PanelType; Enabled := True; Door := False; @@ -320,14 +317,14 @@ begin PANEL_LIFTRIGHT: LiftType := LIFTTYPE_RIGHT; end; -// Íåâèäèìàÿ: +// Невидимая: if ByteBool(PanelRec.Flags and PANEL_FLAG_HIDE) then begin SetLength(FTextureIDs, 0); FCurTexture := -1; Exit; end; -// Ïàíåëè, íå èñïîëüçóþùèå òåêñòóðû: +// Панели, не использующие текстуры: if ByteBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or @@ -340,7 +337,7 @@ begin Exit; end; -// Åñëè ýòî æèäêîñòü áåç òåêñòóðû - ñïåöòåêñòóðó: +// Если это жидкость без текстуры - спецтекстуру: if WordBool(PanelType and (PANEL_WATER or PANEL_ACID1 or PANEL_ACID2)) and (not ByteBool(PanelRec.Flags and PANEL_FLAG_WATERTEXTURES)) then begin @@ -364,22 +361,19 @@ begin else FCurTexture := CurTex; - for i := 0 to Length(FTextureIDs)-1 do - begin + for i := 0 to Length(FTextureIDs) - 1 do FTextureIDs[i].Texture := AddTextures[i].Texture; - if Textures[AddTextures[i].Texture].FramesCount > 0 then - FTextureIDs[i].AnTex := TAnimState.Create(True, Textures[AddTextures[i].Texture].Speed, Textures[AddTextures[i].Texture].FramesCount) - else - FTextureIDs[i].AnTex.Invalidate; - end; -// Òåêñòóð íåñêîëüêî - íóæíî ñîõðàíÿòü òåêóùóþ: + FAnimTime := gTime; + FAnimLoop := true; + +// Текстур несколько - нужно сохранять текущую: //if Length(FTextureIDs) > 1 then SaveIt := True; if (PanelRec.TextureRec = nil) then tnum := -1 else tnum := PanelRec.tagInt; if (tnum < 0) then tnum := Length(Textures); -// Åñëè íå ñïåöòåêñòóðà, òî çàäàåì ðàçìåðû: +// Если не спецтекстура, то задаем размеры: if ({PanelRec.TextureNum}tnum > High(Textures)) then begin e_WriteLog(Format('WTF?! tnum is out of limits! (%d : %d)', [tnum, High(Textures)]), TMsgType.Warning); @@ -605,13 +599,6 @@ var begin if (not Enabled) or (Width < 1) or (Height < 1) then exit; - if (FCurTexture >= 0) and (FTextureIDs[FCurTexture].AnTex.IsValid()) and (FAlpha < 255) then - begin - FTextureIDs[FCurTexture].AnTex.Update(); - FCurFrame := FTextureIDs[FCurTexture].AnTex.CurrentFrame; - FCurFrameCount := FTextureIDs[FCurTexture].AnTex.CurrentCounter; - end; - if not g_dbgpan_mplat_active then exit; if (mOldMovingActive <> mMovingActive) then mNeedSend := true; @@ -867,34 +854,21 @@ begin end; end; - -procedure TPanel.SetFrame(Frame: Integer; Count: Byte); - - function ClampInt(X, A, B: Integer): Integer; + procedure TPanel.SetFrame (StartTime: LongWord); begin - Result := X; - if X < A then Result := A else if X > B then Result := B; + if Enabled and (FCurTexture >= 0) and (Width > 0) and (Height > 0) and (FAlpha < 255) then + FAnimTime := StartTime; end; -begin - if Enabled and (FCurTexture >= 0) and (FTextureIDs[FCurTexture].AnTex.IsValid()) and (Width > 0) and (Height > 0) and (FAlpha < 255) then - begin - FCurFrame := ClampInt(Frame, 0, FTextureIDs[FCurTexture].AnTex.TotalFrames - 1); - FCurFrameCount := Count; - FTextureIDs[FCurTexture].AnTex.CurrentFrame := FCurFrame; - FTextureIDs[FCurTexture].AnTex.CurrentCounter := FCurFrameCount; - end; -end; - procedure TPanel.NextTexture(AnimLoop: Byte = 0); begin Assert(FCurTexture >= -1, 'FCurTexture < -1'); -// Íåò òåêñòóð: +// Нет текстур: if Length(FTextureIDs) = 0 then FCurTexture := -1 else - // Òîëüêî îäíà òåêñòóðà: + // Только одна текстура: if Length(FTextureIDs) = 1 then begin if FCurTexture = 0 then @@ -903,23 +877,22 @@ begin FCurTexture := 0; end else - // Áîëüøå îäíîé òåêñòóðû: + // Больше одной текстуры: begin - // Ñëåäóþùàÿ: + // Следующая: Inc(FCurTexture); - // Ñëåäóþùåé íåò - âîçâðàò ê íà÷àëó: + // Следующей нет - возврат к началу: if FCurTexture >= Length(FTextureIDs) then FCurTexture := 0; end; -// Ïåðåêëþ÷èëèñü íà âèäèìóþ àíèì. òåêñòóðó: - if (FCurTexture >= 0) and FTextureIDs[FCurTexture].AnTex.IsValid() then + if FCurTexture >= 0 then begin - if AnimLoop = 1 then - FTextureIDs[FCurTexture].AnTex.Loop := True - else if AnimLoop = 2 then - FTextureIDs[FCurTexture].AnTex.Loop := False; - FTextureIDs[FCurTexture].AnTex.Reset(); + case AnimLoop of + 1: FAnimLoop := true; + 2: FAnimLoop := false; + end; + FAnimTime := gTime; end; LastAnimLoop := AnimLoop; @@ -930,14 +903,13 @@ begin if (ID >= -1) and (ID < Length(FTextureIDs)) then FCurTexture := ID; -// Ïåðåêëþ÷èëèñü íà âèäèìóþ àíèì. òåêñòóðó: - if (FCurTexture >= 0) and FTextureIDs[FCurTexture].AnTex.IsValid() then + if FCurTexture >= 0 then begin - if AnimLoop = 1 then - FTextureIDs[FCurTexture].AnTex.Loop := True - else if AnimLoop = 2 then - FTextureIDs[FCurTexture].AnTex.Loop := False; - FTextureIDs[FCurTexture].AnTex.Reset(); + case AnimLoop of + 1: FAnimLoop := true; + 2: FAnimLoop := false; + end; + FAnimTime := gTime; end; LastAnimLoop := AnimLoop; @@ -961,9 +933,8 @@ end; function TPanel.GetTextureCount(): Integer; begin Result := Length(FTextureIDs); - if Enabled and (FCurTexture >= 0) then - if (FTextureIDs[FCurTexture].AnTex.IsValid()) and (Width > 0) and (Height > 0) and (FAlpha < 255) then - Result := Result + 100; + if Enabled and (FCurTexture >= 0) and (Width > 0) and (Height > 0) and (FAlpha < 255) then + Result := Result + 100; // ??? end; function TPanel.CanChangeTexture(): Boolean; @@ -975,30 +946,34 @@ const PAN_SAVE_VERSION = 1; procedure TPanel.SaveState (st: TStream); -var - anim: Boolean; + var anim: Boolean; stub: TAnimState; begin if (st = nil) then exit; - // Ñèãíàòóðà ïàíåëè + // Сигнатура панели utils.writeSign(st, 'PANL'); utils.writeInt(st, Byte(PAN_SAVE_VERSION)); - // Îòêðûòà/çàêðûòà, åñëè äâåðü + // Открыта/закрыта, если дверь utils.writeBool(st, FEnabled); - // Íàïðàâëåíèå ëèôòà, åñëè ëèôò + // Направление лифта, если лифт utils.writeInt(st, Byte(FLiftType)); - // Íîìåð òåêóùåé òåêñòóðû + // Номер текущей текстуры utils.writeInt(st, Integer(FCurTexture)); - // Êîîðäèíàòû è ðàçìåð + // Координаты и размер utils.writeInt(st, Integer(FX)); utils.writeInt(st, Integer(FY)); utils.writeInt(st, Word(FWidth)); utils.writeInt(st, Word(FHeight)); - // Àíèìèðîâàíà ëè òåêóùàÿ òåêñòóðà - anim := (FCurTexture >= 0) and (FTextureIDs[FCurTexture].AnTex.IsValid()); + // Анимирована ли текущая текстура + anim := FCurTexture >= 0; utils.writeBool(st, anim); - // Åñëè äà - ñîõðàíÿåì àíèìàöèþ - if anim then FTextureIDs[FCurTexture].AnTex.SaveState(st, FAlpha, FBlending); + // Если да - сохраняем анимацию + if anim then + begin + stub := TAnimState.Create(FAnimLoop, 1, 1); + stub.SaveState(st, FAlpha, FBlending); + stub.Invalidate; + end; // moving platform state utils.writeInt(st, Integer(mMovingSpeed.X)); @@ -1022,19 +997,20 @@ end; procedure TPanel.LoadState (st: TStream); + var stub: TAnimState; begin if (st = nil) then exit; - // Ñèãíàòóðà ïàíåëè + // Сигнатура панели if not utils.checkSign(st, 'PANL') then raise XStreamError.create('wrong panel signature'); if (utils.readByte(st) <> PAN_SAVE_VERSION) then raise XStreamError.create('wrong panel version'); - // Îòêðûòà/çàêðûòà, åñëè äâåðü + // Открыта/закрыта, если дверь FEnabled := utils.readBool(st); - // Íàïðàâëåíèå ëèôòà, åñëè ëèôò + // Направление лифта, если лифт FLiftType := utils.readByte(st); - // Íîìåð òåêóùåé òåêñòóðû + // Номер текущей текстуры FCurTexture := utils.readLongInt(st); - // Êîîðäèíàòû è ðàçìåð + // Координаты и размер FX := utils.readLongInt(st); FY := utils.readLongInt(st); FOldX := FX; @@ -1043,12 +1019,14 @@ begin FHeight := utils.readWord(st); FOldW := FWidth; FOldH := FHeight; - // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà + // Анимированная ли текущая текстура if utils.readBool(st) then begin - // Åñëè äà - çàãðóæàåì àíèìàöèþ - Assert((FCurTexture >= 0) and (FTextureIDs[FCurTexture].AnTex.IsValid()), 'TPanel.LoadState: No animation object'); - FTextureIDs[FCurTexture].AnTex.LoadState(st, FAlpha, FBlending); + // Если да - загружаем анимацию + Assert(FCurTexture >= 0, 'TPanel.LoadState: No animation object'); + stub := TAnimState.Create(FAnimLoop, 1, 1); + stub.LoadState(st, FAlpha, FBlending); + stub.Invalidate; end; // moving platform state diff --git a/src/game/renders/opengl/r_map.pas b/src/game/renders/opengl/r_map.pas index 7e9482e..786bd54 100644 --- a/src/game/renders/opengl/r_map.pas +++ b/src/game/renders/opengl/r_map.pas @@ -238,6 +238,7 @@ implementation RenTextures: array of record spec: LongInt; tex: TGLMultiTexture; + anim: TAnimInfo; end; Items: array [0..ITEM_LAST] of record tex: TGLMultiTexture; @@ -547,7 +548,8 @@ implementation end; procedure r_Map_LoadTextures; - var i, n: Integer; + const DefaultAnimInfo: TAnimInfo = (loop: true; delay: 1; frames: 1; back: false); + var i, n: Integer; txt: TAnimTextInfo; begin if Textures <> nil then begin @@ -555,6 +557,7 @@ implementation SetLength(RenTextures, n); for i := 0 to n - 1 do begin + txt.anim := DefaultAnimInfo; RenTextures[i].tex := nil; case Textures[i].TextureName of TEXTURE_NAME_WATER: RenTextures[i].spec := TEXTURE_SPECIAL_WATER; @@ -562,10 +565,13 @@ implementation TEXTURE_NAME_ACID2: RenTextures[i].spec := TEXTURE_SPECIAL_ACID2; else RenTextures[i].spec := 0; - RenTextures[i].tex := r_Textures_LoadMultiFromFile(Textures[i].FullName); + e_LogWritefln('r_Map_LoadTextures: begin load texture: %s', [Textures[i].FullName]); + RenTextures[i].tex := r_Textures_LoadMultiTextFromFile(Textures[i].FullName, txt); + e_LogWritefln('r_Map_LoadTextures: end load texture: %s', [Textures[i].FullName]); if RenTextures[i].tex = nil then e_LogWritefln('r_Map_LoadTextures: failed to load texture: %s', [Textures[i].FullName]); end; + RenTextures[i].anim := txt.anim; end; end; if gMapInfo.SkyFullName <> '' then @@ -588,22 +594,29 @@ implementation end; procedure r_Map_DrawPanel (p: TPanel); - var Texture: Integer; t: TGLMultiTexture; + var Texture: Integer; t: TGLMultiTexture; tex: TGLTexture; count, frame: LongInt; a: TAnimInfo; begin ASSERT(p <> nil); if p.FCurTexture >= 0 then begin Texture := p.TextureIDs[p.FCurTexture].Texture; t := RenTextures[Texture].tex; - if (RenTextures[Texture].spec = 0) or (t <> nil) then begin - if t = nil then - r_Draw_TextureRepeat(nil, p.x, p.y, p.width, p.height, false, 255, 255, 255, 255 - p.alpha, p.blending) - else if p.TextureIDs[p.FCurTexture].AnTex.IsValid() then - r_Draw_MultiTextureRepeat(t, p.TextureIDs[p.FCurTexture].AnTex, p.x, p.y, p.width, p.height, false, 255, 255, 255, 255 - p.alpha, p.blending) + count := 0; frame := 0; + if p.AnimTime <= gTime then + begin + a := RenTextures[Texture].anim; + a.loop := p.AnimLoop; + g_Anim_GetFrameByTime(a, (gTime - p.AnimTime) DIV GAME_TICK, count, frame); + end; + if t <> nil then + begin + tex := t.GetTexture(frame); + r_Draw_TextureRepeat(tex, p.x, p.y, p.width, p.height, false, 255, 255, 255, 255 - p.alpha, p.blending); + end else - r_Draw_TextureRepeat(t.GetTexture(0), p.x, p.y, p.width, p.height, false, 255, 255, 255, 255 - p.alpha, p.blending) + r_Draw_TextureRepeat(nil, p.x, p.y, p.width, p.height, false, 255, 255, 255, 255, false); end; if t = nil then diff --git a/src/game/renders/opengl/r_textures.pas b/src/game/renders/opengl/r_textures.pas index 64d4f53..062f76b 100644 --- a/src/game/renders/opengl/r_textures.pas +++ b/src/game/renders/opengl/r_textures.pas @@ -23,7 +23,7 @@ interface {$ELSE} GL, GLEXT, {$ENDIF} - g_base, // TRectHW + g_base, g_animations, // TRectHW, TAnimInfo utils, r_atlas, r_fonts ; @@ -116,12 +116,20 @@ interface function GetSpace (): Integer; end; + TAnimTextInfo = record + name: AnsiString; + w, h: Integer; + anim: TAnimInfo; + end; + procedure r_Textures_Initialize; procedure r_Textures_Finalize; function r_Textures_LoadFromFile (const filename: AnsiString; log: Boolean = True): TGLTexture; function r_Textures_LoadMultiFromFile (const filename: AnsiString; log: Boolean = True): TGLMultiTexture; function r_Textures_LoadMultiFromFileAndInfo (const filename: AnsiString; w, h, count: Integer; backanim: Boolean; log: Boolean = True): TGLMultiTexture; + function r_Textures_LoadMultiTextFromFile (const filename: AnsiString; var txt: TAnimTextInfo; log: Boolean = True): TGLMultiTexture; + function r_Textures_LoadStreamFromFile (const filename: AnsiString; w, h, count, cw: Integer; st: TGLTextureArray; rs: TRectArray; log: Boolean = True): Boolean; function r_Textures_LoadFontFromFile (const filename: AnsiString; constref f: TFontInfo; skipch: Integer; log: Boolean = true): TGLFont; @@ -494,43 +502,57 @@ implementation end; end; - function r_Textures_LoadMultiFromWad (wad: TWADFile): TGLMultiTexture; - var data: Pointer; size: LongInt; TexRes: AnsiString; w, h, c: Integer; b: Boolean; cfg: TConfig; img: TImageData; + function r_Textures_LoadTextFromMemory (data: Pointer; size: LongInt; var txt: TAnimTextInfo): Boolean; + var cfg: TConfig; + begin + result := false; + if data <> nil then + begin + cfg := TConfig.CreateMem(data, size); + if cfg <> nil then + begin + txt.name := cfg.ReadStr('', 'resource', ''); + txt.w := MAX(0, cfg.ReadInt('', 'framewidth', 0)); + txt.h := MAX(0, cfg.ReadInt('', 'frameheight', 0)); + txt.anim.loop := true; + txt.anim.delay := MAX(0, cfg.ReadInt('', 'waitcount', 0)); + txt.anim.frames := MAX(0, cfg.ReadInt('', 'framecount', 0)); + txt.anim.back := cfg.ReadBool('', 'backanim', false); + cfg.Free; + result := (txt.name <> '') and (txt.w > 0) and (txt.h > 0) and (txt.anim.delay > 0) and (txt.anim.frames > 0); + end; + end; + end; + + function r_Textures_LoadMultiFromWad (wad: TWADFile; var txt: TAnimTextInfo): TGLMultiTexture; + var data: Pointer; size: LongInt; img: TImageData; begin ASSERT(wad <> nil); result := nil; if wad.GetResource('TEXT/ANIM', data, size) then begin - cfg := TConfig.CreateMem(data, size); - FreeMem(data); - if cfg <> nil then + if r_Textures_LoadTextFromMemory(data, size, txt) then begin - TexRes := cfg.ReadStr('', 'resource', ''); - w := cfg.ReadInt('', 'framewidth', 0); - h := cfg.ReadInt('', 'frameheight', 0); - c := cfg.ReadInt('', 'framecount', 0); - b := cfg.ReadBool('', 'backanim', false); - if (TexRes <> '') and (w > 0) and (h > 0) and (c > 0) then + FreeMem(data); + if wad.GetResource('TEXTURES/' + txt.name, data, size) then begin - if wad.GetResource('TEXTURES/' + TexRes, data, size) then - begin - InitImage(img); - try - if LoadImageFromMemory(data, size, img) then - if r_Textures_FixImageData(img) then - result := r_Textures_LoadMultiFromImageAndInfo(img, w, h, c, b) - finally - FreeMem(data); - end; - FreeImage(img); - end + InitImage(img); + try + if LoadImageFromMemory(data, size, img) then + if r_Textures_FixImageData(img) then + result := r_Textures_LoadMultiFromImageAndInfo(img, txt.w, txt.h, txt.anim.frames, txt.anim.back); + finally + FreeMem(data); + end; + FreeImage(img); end; - cfg.Free; end + else + FreeMem(data); end; end; - function r_Textures_LoadMultiFromMemory (data: Pointer; size: LongInt): TGLMultiTexture; + function r_Textures_LoadMultiFromMemory (data: Pointer; size: LongInt; var txt: TAnimTextInfo): TGLMultiTexture; var wad: TWADFile; t: TGLTexture; m: TGLMultiTexture; begin result := nil; @@ -543,6 +565,13 @@ implementation SetLength(m.mTexture, 1); m.mTexture[0] := t; m.mBackanim := false; + txt.name := ''; + txt.w := m.width; + txt.h := m.height; + txt.anim.loop := true; + txt.anim.delay := 1; + txt.anim.frames := 1; + txt.anim.back := false; result := m; end else if IsWadData(data, size) then @@ -550,15 +579,15 @@ implementation wad := TWADFile.Create(); if wad.ReadMemory(data, size) then begin - result := r_Textures_LoadMultiFromWad(wad); + result := r_Textures_LoadMultiFromWad(wad, txt); wad.Free; end end end end; - function r_Textures_LoadMultiFromFile (const filename: AnsiString; log: Boolean = True): TGLMultiTexture; - var wad: TWADFile; wadName, resName: AnsiString; data: Pointer; size: Integer; t: TGLTexture; + function r_Textures_LoadMultiTextFromFile (const filename: AnsiString; var txt: TAnimTextInfo; log: Boolean = True): TGLMultiTexture; + var wad: TWADFile; wadName, resName: AnsiString; data: Pointer; size: Integer; begin result := nil; wadName := g_ExtractWadName(filename); @@ -568,13 +597,19 @@ implementation resName := g_ExtractFilePathName(filename); if wad.GetResource(resName, data, size, log) then begin - result := r_Textures_LoadMultiFromMemory(data, size); + result := r_Textures_LoadMultiFromMemory(data, size, txt); FreeMem(data); end; wad.Free end end; + function r_Textures_LoadMultiFromFile (const filename: AnsiString; log: Boolean = True): TGLMultiTexture; + var txt: TAnimTextInfo; + begin + result := r_Textures_LoadMultiTextFromFile(filename, txt, log); + end; + function r_Textures_LoadMultiFromFileAndInfo (const filename: AnsiString; w, h, count: Integer; backanim: Boolean; log: Boolean = True): TGLMultiTexture; var wad: TWADFile; wadName, resName: AnsiString; data: Pointer; size: Integer; begin -- 2.29.2