X-Git-Url: http://deadsoftware.ru/gitweb?p=d2df-sdl.git;a=blobdiff_plain;f=src%2Fgame%2Fopengl%2Fr_animations.pas;h=1b634051753716d481178091eaf2134a6bbe88bb;hp=71d752a79da7606ed47a7c035dd134917c42d3a8;hb=3af68bc5a306b013ddb2a04c24543b6ec6e288af;hpb=d5d513b459869550bc0623d910eb97c706fab07d diff --git a/src/game/opengl/r_animations.pas b/src/game/opengl/r_animations.pas index 71d752a..1b63405 100644 --- a/src/game/opengl/r_animations.pas +++ b/src/game/opengl/r_animations.pas @@ -17,14 +17,44 @@ unit r_animations; interface - uses g_base, g_textures, MAPDEF; // TMirrorType, TAnimation, TDFPoint + uses g_base, g_textures, MAPDEF, Imaging; // TMirrorType, TAnimation, TDFPoint, TDynImageDataArray procedure r_Animation_Draw (t: TAnimation; x, y: Integer; mirror: TMirrorType); procedure r_Animation_DrawEx (t: TAnimation; x, y: Integer; mirror: TMirrorType; rpoint: TDFPoint; angle: SmallInt); + function g_CreateFramesImg (ia: TDynImageDataArray; ID: PDWORD; const Name: AnsiString; BackAnimation: Boolean = false): Boolean; + + function g_Frames_CreateWAD (ID: PDWORD; const Name, Resource: AnsiString; mWidth, mHeight, mCount: Word; BackAnimation: Boolean=false): Boolean; + function g_Frames_CreateFile (ID: PDWORD; const Name, FileName: AnsiString; mWidth, mHeight, mCount: Word; BackAnimation: Boolean = false): Boolean; + function g_Frames_CreateMemory (ID: PDWORD; const Name: AnsiString; pData: Pointer; dataSize: LongInt; mWidth, mHeight, mCount: Word; BackAnimation: Boolean=false): Boolean; + function g_Frames_Dup (const NewName, OldName: AnsiString): Boolean; + function g_Frames_Get (out ID: LongWord; const FramesName: AnsiString): Boolean; + function g_Frames_GetTexture (out ID: LongWord; const FramesName: AnsiString; Frame: Word): Boolean; + function g_Frames_Exists (const FramesName: AnsiString): Boolean; + procedure g_Frames_DeleteByName (const FramesName: AnsiString); + procedure g_Frames_DeleteByID (ID: LongWord); + procedure g_Frames_DeleteAll; + + type + TFrames = record + texturesID: array of LongWord; + name: AnsiString; + frameWidth, frameHeight: Word; + used: Boolean; + end; + + var + framesArray: array of TFrames = nil; + implementation - uses r_graphics; + uses + SysUtils, Classes, Math, + WadReader, utils, + e_log, + r_graphics, + g_language, g_game + ; procedure r_Animation_Draw (t: TAnimation; x, y: Integer; mirror: TMirrorType); begin @@ -38,4 +68,328 @@ implementation e_DrawAdv(framesArray[t.id].TexturesID[t.currentFrame], x, y, t.alpha, true, t.blending, angle, @rpoint, mirror) end; +function allocFrameSlot (): LongWord; +var + f: integer; +begin + for f := 0 to High(framesArray) do + begin + if (not framesArray[f].used) then + begin + result := f; + exit; + end; + end; + + result := Length(framesArray); + SetLength(framesArray, result+64); + for f := result to High(framesArray) do + begin + with framesArray[f] do + begin + texturesID := nil; + name := ''; + frameWidth := 0; + frameHeight := 0; + used := false; + end; + end; +end; + +function g_Frames_CreateFile (ID: PDWORD; const Name, FileName: AnsiString; + mWidth, mHeight, mCount: Word; BackAnimation: Boolean = false): Boolean; +var + a: Integer; + find_id: LongWord; +begin + result := false; + + find_id := allocFrameSlot(); + + if (mCount <= 2) then BackAnimation := false; + + if BackAnimation then SetLength(framesArray[find_id].TexturesID, mCount+mCount-2) + else SetLength(framesArray[find_id].TexturesID, mCount); + + for a := 0 to mCount-1 do + begin + if not e_CreateTextureEx(FileName, framesArray[find_id].TexturesID[a], a*mWidth, 0, mWidth, mHeight) then exit; + end; + + if BackAnimation then + begin + for a := 1 to mCount-2 do framesArray[find_id].TexturesID[mCount+mCount-2-a] := framesArray[find_id].TexturesID[a]; + end; + + framesArray[find_id].used := true; + framesArray[find_id].FrameWidth := mWidth; + framesArray[find_id].FrameHeight := mHeight; + if (Name <> '') then framesArray[find_id].Name := Name else framesArray[find_id].Name := ''; + + if (ID <> nil) then ID^ := find_id; + + result := true; +end; + +function CreateFramesMem (pData: Pointer; dataSize: LongInt; ID: PDWORD; Name: AnsiString; + mWidth, mHeight, mCount: Word; BackAnimation: Boolean = false): Boolean; +var + find_id: LongWord; + a: Integer; +begin + result := false; + + find_id := allocFrameSlot(); + + if (mCount <= 2) then BackAnimation := false; + + if BackAnimation then SetLength(framesArray[find_id].TexturesID, mCount+mCount-2) + else SetLength(framesArray[find_id].TexturesID, mCount); + + for a := 0 to mCount-1 do + if not e_CreateTextureMemEx(pData, dataSize, framesArray[find_id].TexturesID[a], a*mWidth, 0, mWidth, mHeight) then + begin + //!!!FreeMem(pData); + exit; + end; + + if BackAnimation then + begin + for a := 1 to mCount-2 do framesArray[find_id].TexturesID[mCount+mCount-2-a] := framesArray[find_id].TexturesID[a]; + end; + + framesArray[find_id].used := true; + framesArray[find_id].FrameWidth := mWidth; + framesArray[find_id].FrameHeight := mHeight; + if (Name <> '') then framesArray[find_id].Name := Name else framesArray[find_id].Name := ''; + + if (ID <> nil) then ID^ := find_id; + + result := true; +end; + +function g_CreateFramesImg (ia: TDynImageDataArray; ID: PDWORD; const Name: AnsiString; BackAnimation: Boolean = false): Boolean; +var + find_id: LongWord; + a, mCount: Integer; +begin + result := false; + find_id := allocFrameSlot(); + + mCount := Length(ia); + + //e_WriteLog(Format('+++ creating %d frames [%s]', [FCount, Name]), MSG_NOTIFY); + + if (mCount < 1) then exit; + if (mCount <= 2) then BackAnimation := false; + + if BackAnimation then SetLength(framesArray[find_id].TexturesID, mCount+mCount-2) + else SetLength(framesArray[find_id].TexturesID, mCount); + + //e_WriteLog(Format('+++ creating %d frames, %dx%d', [FCount, ia[0].width, ia[0].height]), MSG_NOTIFY); + + for a := 0 to mCount-1 do + begin + if not e_CreateTextureImg(ia[a], framesArray[find_id].TexturesID[a]) then exit; + //e_WriteLog(Format('+++ frame %d, %dx%d', [a, ia[a].width, ia[a].height]), MSG_NOTIFY); + end; + + if BackAnimation then + begin + for a := 1 to mCount-2 do framesArray[find_id].TexturesID[mCount+mCount-2-a] := framesArray[find_id].TexturesID[a]; + end; + + framesArray[find_id].used := true; + framesArray[find_id].FrameWidth := ia[0].width; + framesArray[find_id].FrameHeight := ia[0].height; + if (Name <> '') then framesArray[find_id].Name := Name else framesArray[find_id].Name := ''; + + if (ID <> nil) then ID^ := find_id; + + result := true; +end; + +function g_Frames_CreateWAD (ID: PDWORD; const Name, Resource: AnsiString; + mWidth, mHeight, mCount: Word; BackAnimation: Boolean=false): Boolean; +var + WAD: TWADFile; + FileName: AnsiString; + TextureData: Pointer; + ResourceLength: Integer; +begin + result := false; + + // models without "advanced" animations asks for "nothing" like this; don't spam log + if (Length(Resource) > 0) and ((Resource[Length(Resource)] = '/') or (Resource[Length(Resource)] = '\')) then exit; + + FileName := g_ExtractWadName(Resource); + + WAD := TWADFile.Create(); + WAD.ReadFile(FileName); + + if not WAD.GetResource(g_ExtractFilePathName(Resource), TextureData, ResourceLength) then + begin + WAD.Free(); + e_WriteLog(Format('Error loading texture %s', [Resource]), TMsgType.Warning); + //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING); + exit; + end; + + if not CreateFramesMem(TextureData, ResourceLength, ID, Name, mWidth, mHeight, mCount, BackAnimation) then + begin + FreeMem(TextureData); + WAD.Free(); + exit; + end; + + FreeMem(TextureData); + WAD.Free(); + + result := true; +end; + +function g_Frames_CreateMemory (ID: PDWORD; const Name: AnsiString; pData: Pointer; dataSize: LongInt; + mWidth, mHeight, mCount: Word; BackAnimation: Boolean = false): Boolean; +begin + result := CreateFramesMem(pData, dataSize, ID, Name, mWidth, mHeight, mCount, BackAnimation); +end; + +function g_Frames_Dup (const NewName, OldName: AnsiString): Boolean; +var + find_id, b: LongWord; + a, c: Integer; +begin + result := false; + + if not g_Frames_Get(b, OldName) then exit; + + find_id := allocFrameSlot(); + + framesArray[find_id].used := true; + framesArray[find_id].Name := NewName; + framesArray[find_id].FrameWidth := framesArray[b].FrameWidth; + framesArray[find_id].FrameHeight := framesArray[b].FrameHeight; + + c := High(framesArray[b].TexturesID); + SetLength(framesArray[find_id].TexturesID, c+1); + + for a := 0 to c do framesArray[find_id].TexturesID[a] := framesArray[b].TexturesID[a]; + + result := true; +end; + + +procedure g_Frames_DeleteByName (const FramesName: AnsiString); +var + a, b: Integer; +begin + if (Length(framesArray) = 0) then exit; + for a := 0 to High(framesArray) do + begin + if (StrEquCI1251(framesArray[a].Name, FramesName)) then + begin + if framesArray[a].TexturesID <> nil then + begin + for b := 0 to High(framesArray[a].TexturesID) do e_DeleteTexture(framesArray[a].TexturesID[b]); + end; + framesArray[a].used := false; + framesArray[a].TexturesID := nil; + framesArray[a].Name := ''; + framesArray[a].FrameWidth := 0; + framesArray[a].FrameHeight := 0; + end; + end; +end; + +procedure g_Frames_DeleteByID (ID: LongWord); +var + b: Integer; +begin + if (Length(framesArray) = 0) then exit; + if (framesArray[ID].TexturesID <> nil) then + begin + for b := 0 to High(framesArray[ID].TexturesID) do e_DeleteTexture(framesArray[ID].TexturesID[b]); + end; + framesArray[ID].used := false; + framesArray[ID].TexturesID := nil; + framesArray[ID].Name := ''; + framesArray[ID].FrameWidth := 0; + framesArray[ID].FrameHeight := 0; +end; + +procedure g_Frames_DeleteAll (); +var + a, b: Integer; +begin + for a := 0 to High(framesArray) do + begin + if (framesArray[a].used) then + begin + for b := 0 to High(framesArray[a].TexturesID) do e_DeleteTexture(framesArray[a].TexturesID[b]); + end; + framesArray[a].used := false; + framesArray[a].TexturesID := nil; + framesArray[a].Name := ''; + framesArray[a].FrameWidth := 0; + framesArray[a].FrameHeight := 0; + end; + framesArray := nil; +end; + + +function g_Frames_Get (out ID: LongWord; const FramesName: AnsiString): Boolean; +var + a: Integer; +begin + result := false; + if (Length(framesArray) = 0) then exit; + for a := 0 to High(framesArray) do + begin + if (StrEquCI1251(framesArray[a].Name, FramesName)) then + begin + ID := a; + result := true; + break; + end; + end; + if not result then g_FatalError(Format(_lc[I_GAME_ERROR_FRAMES], [FramesName])); +end; + +function g_Frames_GetTexture (out ID: LongWord; const FramesName: AnsiString; Frame: Word): Boolean; +var + a: Integer; +begin + result := false; + if (Length(framesArray) = 0) then exit; + for a := 0 to High(framesArray) do + begin + if (StrEquCI1251(framesArray[a].Name, FramesName)) then + begin + if (Frame < Length(framesArray[a].TexturesID)) then + begin + ID := framesArray[a].TexturesID[Frame]; + result := true; + break; + end; + end; + end; + if not result then g_FatalError(Format(_lc[I_GAME_ERROR_FRAMES], [FramesName])); +end; + +function g_Frames_Exists (const FramesName: AnsiString): Boolean; +var + a: Integer; +begin + result := false; + if (Length(framesArray) = 0) then exit; + for a := 0 to High(framesArray) do + begin + if (StrEquCI1251(framesArray[a].Name, FramesName)) then + begin + result := true; + exit; + end; + end; +end; + end.