- Fixed Art and TexMap to no longer get loaded if their Size is <= 0

This commit is contained in:
Andreas Schneider 2009-12-10 22:05:38 +01:00
parent 5c3de09d10
commit 34765f7235
6 changed files with 553 additions and 534 deletions

View File

@ -56,7 +56,7 @@
<MinVersion Major="4" Minor="5" Release="1" Valid="True"/> <MinVersion Major="4" Minor="5" Release="1" Valid="True"/>
</Item5> </Item5>
</RequiredPackages> </RequiredPackages>
<Units Count="40"> <Units Count="42">
<Unit0> <Unit0>
<Filename Value="CentrED.lpr"/> <Filename Value="CentrED.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
@ -298,6 +298,16 @@
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UMulManager"/> <UnitName Value="UMulManager"/>
</Unit39> </Unit39>
<Unit40>
<Filename Value="../MulProvider/UArtProvider.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="UArtProvider"/>
</Unit40>
<Unit41>
<Filename Value="../MulProvider/UTexmapProvider.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="UTexmapProvider"/>
</Unit41>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -42,7 +42,7 @@ uses
UGUIPlatformUtils, UPlatformTypes, UfrmRegionControl, UPackets, UGUIPlatformUtils, UPlatformTypes, UfrmRegionControl, UPackets,
UPacketHandlers, UAdminHandling, UGameResources, ULandscape, UfrmToolWindow, UPacketHandlers, UAdminHandling, UGameResources, ULandscape, UfrmToolWindow,
Logging, UTileDataProvider, UMap, UWorldItem, UStatics, UTiledata, UAnimData, Logging, UTileDataProvider, UMap, UWorldItem, UStatics, UTiledata, UAnimData,
UGLFont, UAnimDataProvider, UMulManager; UGLFont, UAnimDataProvider, UMulManager, UArtProvider, UTexmapProvider;
{$IFDEF WINDOWS}{$R CentrED.rc}{$ENDIF} {$IFDEF WINDOWS}{$R CentrED.rc}{$ENDIF}

View File

@ -37,7 +37,7 @@ type
{ TGameResourceManager } { TGameResourceManager }
TGameResourceManager = class(TObject) TGameResourceManager = class
constructor Create(ADataDir: string); constructor Create(ADataDir: string);
destructor Destroy; override; destructor Destroy; override;
protected protected

View File

@ -1,97 +1,97 @@
(* (*
* CDDL HEADER START * CDDL HEADER START
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only * Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance * (the "License"). You may not use this file except in compliance
* with the License. * with the License.
* *
* You can obtain a copy of the license at * You can obtain a copy of the license at
* http://www.opensource.org/licenses/cddl1.php. * http://www.opensource.org/licenses/cddl1.php.
* See the License for the specific language governing permissions * See the License for the specific language governing permissions
* and limitations under the License. * and limitations under the License.
* *
* When distributing Covered Code, include this CDDL HEADER in each * When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at * file and include the License file at
* http://www.opensource.org/licenses/cddl1.php. If applicable, * http://www.opensource.org/licenses/cddl1.php. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed * add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying * information: * by brackets "[]" replaced with your own identifying * information:
* Portions Copyright [yyyy] [name of copyright owner] * Portions Copyright [yyyy] [name of copyright owner]
* *
* CDDL HEADER END * CDDL HEADER END
* *
* *
* Portions Copyright 2007 Andreas Schneider * Portions Copyright 2009 Andreas Schneider
*) *)
unit UArtProvider; unit UArtProvider;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
interface interface
uses uses
Graphics, UMulProvider, UMulBlock, UGenericIndex, UArt, UHue; Graphics, UMulProvider, UMulBlock, UGenericIndex, UArt, UHue;
type type
TArtProvider = class(TIndexedMulProvider) TArtProvider = class(TIndexedMulProvider)
protected protected
function GetData(AID: Integer; AIndex: TGenericIndex): TMulBlock; override; function GetData(AID: Integer; AIndex: TGenericIndex): TMulBlock; override;
function GetArtData(AID: Integer; AIndex: TGenericIndex; AColor: Word; AHue: THue; APartialHue: Boolean): TArt; function GetArtData(AID: Integer; AIndex: TGenericIndex; AColor: Word; AHue: THue; APartialHue: Boolean): TArt;
public public
function GetArt(AID: Integer; AColor: Word; AHue: THue; APartialHue: Boolean): TArt; function GetArt(AID: Integer; AColor: Word; AHue: THue; APartialHue: Boolean): TArt;
function GetFlatLand(AID: Integer): TArt; function GetFlatLand(AID: Integer): TArt;
end; end;
implementation implementation
{ TArtProvider } { TArtProvider }
function TArtProvider.GetData(AID: Integer; AIndex: TGenericIndex): TMulBlock; function TArtProvider.GetData(AID: Integer; AIndex: TGenericIndex): TMulBlock;
begin begin
Result := GetArtData(AID, AIndex, clBlack, nil, False); Result := GetArtData(AID, AIndex, clBlack, nil, False);
end; end;
function TArtProvider.GetArtData(AID: Integer; AIndex: TGenericIndex; function TArtProvider.GetArtData(AID: Integer; AIndex: TGenericIndex;
AColor: Word; AHue: THue; APartialHue: Boolean): TArt; AColor: Word; AHue: THue; APartialHue: Boolean): TArt;
begin begin
if AIndex.Lookup <> LongInt($FFFFFFFF) then if (AIndex.Lookup > -1) and (AIndex.Size > 0) then
begin begin
if AID < $4000 then if AID < $4000 then
Result := TArt.Create(FData, AIndex, atLand, AColor, AHue, APartialHue) Result := TArt.Create(FData, AIndex, atLand, AColor, AHue, APartialHue)
else else
Result := TArt.Create(FData, AIndex, atStatic, AColor, AHue, APartialHue); Result := TArt.Create(FData, AIndex, atStatic, AColor, AHue, APartialHue);
end else end else
begin begin
if AID < $4000 then if AID < $4000 then
Result := TArt.Create(nil, nil, atLand, AColor, AHue, APartialHue) Result := TArt.Create(nil, nil, atLand, AColor, AHue, APartialHue)
else else
Result := TArt.Create(nil, nil, atStatic, AColor, AHue, APartialHue); Result := TArt.Create(nil, nil, atStatic, AColor, AHue, APartialHue);
end; end;
Result.ID := AID; Result.ID := AID;
end; end;
function TArtProvider.GetArt(AID: Integer; AColor: Word; AHue: THue; APartialHue: Boolean): TArt; function TArtProvider.GetArt(AID: Integer; AColor: Word; AHue: THue; APartialHue: Boolean): TArt;
var var
genericIndex: TGenericIndex; genericIndex: TGenericIndex;
begin begin
FIndex.Position := CalculateIndexOffset(AID); FIndex.Position := CalculateIndexOffset(AID);
genericIndex := TGenericIndex.Create(FIndex); genericIndex := TGenericIndex.Create(FIndex);
Result := GetArtData(AID, genericIndex, AColor, AHue, APartialHue); Result := GetArtData(AID, genericIndex, AColor, AHue, APartialHue);
genericIndex.Free; genericIndex.Free;
Result.OnChanged := @OnChanged; Result.OnChanged := @OnChanged;
Result.OnFinished := @OnFinished; Result.OnFinished := @OnFinished;
end; end;
function TArtProvider.GetFlatLand(AID: Integer): TArt; function TArtProvider.GetFlatLand(AID: Integer): TArt;
var var
genericIndex: TGenericIndex; genericIndex: TGenericIndex;
begin begin
FIndex.Position := CalculateIndexOffset(AID); FIndex.Position := CalculateIndexOffset(AID);
genericIndex := TGenericIndex.Create(FIndex); genericIndex := TGenericIndex.Create(FIndex);
Result := TArt.Create(FData, genericIndex, atLandFlat); Result := TArt.Create(FData, genericIndex, atLandFlat);
genericIndex.Free; genericIndex.Free;
Result.OnChanged := @OnChanged; Result.OnChanged := @OnChanged;
Result.OnFinished := @OnFinished; Result.OnFinished := @OnFinished;
end; end;
end. end.

View File

@ -1,378 +1,387 @@
(* (*
* CDDL HEADER START * CDDL HEADER START
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only * Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance * (the "License"). You may not use this file except in compliance
* with the License. * with the License.
* *
* You can obtain a copy of the license at * You can obtain a copy of the license at
* http://www.opensource.org/licenses/cddl1.php. * http://www.opensource.org/licenses/cddl1.php.
* See the License for the specific language governing permissions * See the License for the specific language governing permissions
* and limitations under the License. * and limitations under the License.
* *
* When distributing Covered Code, include this CDDL HEADER in each * When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at * file and include the License file at
* http://www.opensource.org/licenses/cddl1.php. If applicable, * http://www.opensource.org/licenses/cddl1.php. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed * add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying * information: * by brackets "[]" replaced with your own identifying * information:
* Portions Copyright [yyyy] [name of copyright owner] * Portions Copyright [yyyy] [name of copyright owner]
* *
* CDDL HEADER END * CDDL HEADER END
* *
* *
* Portions Copyright 2007 Andreas Schneider * Portions Copyright 2009 Andreas Schneider
*) *)
unit UMulProvider; unit UMulProvider;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
interface interface
uses uses
SysUtils, Classes, UBufferedStreams, UMulBlock, UGenericIndex; SysUtils, Classes, UBufferedStreams, UMulBlock, UGenericIndex;
type type
TOnProgressEvent = procedure(Total, Current: Integer) of object; TOnProgressEvent = procedure(Total, Current: Integer) of object;
TMulEventHandler = class(TObject)
constructor Create; { TMulEventHandler }
destructor Destroy; override;
protected TMulEventHandler = class
FEvents: TList; constructor Create;
public destructor Destroy; override;
procedure RegisterEvent(AEvent: TMulBlockChanged); protected
procedure UnregisterEvent(AEvent: TMulBlockChanged); FEvents: TList;
procedure FireEvents(ABlock: TMulBlock); public
end; procedure RegisterEvent(AEvent: TMulBlockChanged);
TMulProvider = class(TObject) procedure UnregisterEvent(AEvent: TMulBlockChanged);
constructor Create; overload; virtual; procedure FireEvents(ABlock: TMulBlock);
constructor Create(AData: TStream; AReadOnly: Boolean = False); overload; virtual; end;
constructor Create(AData: string; AReadOnly: Boolean = False); overload; virtual;
destructor Destroy; override; { TMulProvider }
protected
FData: TStream; TMulProvider = class
FOwnsData: Boolean; constructor Create; overload; virtual;
FReadOnly: Boolean; constructor Create(AData: TStream; AReadOnly: Boolean = False); overload; virtual;
FChangeEvents: TMulEventHandler; constructor Create(AData: string; AReadOnly: Boolean = False); overload; virtual;
FFinishedEvents: TMulEventHandler; destructor Destroy; override;
function CalculateOffset(AID: Integer): Integer; virtual; abstract; protected
function GetData(AID, AOffset: Integer): TMulBlock; virtual; abstract; FData: TStream;
procedure SetData(AID, AOffset: Integer; ABlock: TMulBlock); virtual; FOwnsData: Boolean;
procedure OnChanged(ABlock: TMulBlock); FReadOnly: Boolean;
procedure OnFinished(ABlock: TMulBlock); FChangeEvents: TMulEventHandler;
public FFinishedEvents: TMulEventHandler;
function GetBlock(AID: Integer): TMulBlock; virtual; function CalculateOffset(AID: Integer): Integer; virtual; abstract;
procedure SetBlock(AID: Integer; ABlock: TMulBlock); virtual; function GetData(AID, AOffset: Integer): TMulBlock; virtual; abstract;
procedure RegisterOnChangeEvent(AEvent: TMulBlockChanged); procedure SetData(AID, AOffset: Integer; ABlock: TMulBlock); virtual;
procedure UnregisterOnChangeEvent(AEvent: TMulBlockChanged); procedure OnChanged(ABlock: TMulBlock);
procedure RegisterOnFinishedEvent(AEvent: TMulBlockChanged); procedure OnFinished(ABlock: TMulBlock);
procedure UnregisterOnFinishedEvent(AEvent: TMulBlockChanged); public
property Block[ID: Integer]: TMulBlock read GetBlock write SetBlock; function GetBlock(AID: Integer): TMulBlock; virtual;
property Data: TStream read FData; procedure SetBlock(AID: Integer; ABlock: TMulBlock); virtual;
end; procedure RegisterOnChangeEvent(AEvent: TMulBlockChanged);
TIndexedMulProvider = class(TMulProvider) procedure UnregisterOnChangeEvent(AEvent: TMulBlockChanged);
constructor Create(AData, AIndex: TStream; AReadOnly: Boolean = False); overload; virtual; procedure RegisterOnFinishedEvent(AEvent: TMulBlockChanged);
constructor Create(AData, AIndex: string; AReadOnly: Boolean = False); overload; virtual; procedure UnregisterOnFinishedEvent(AEvent: TMulBlockChanged);
destructor Destroy; override; property Block[ID: Integer]: TMulBlock read GetBlock write SetBlock;
protected property Data: TStream read FData;
FIndex: TBufferedReader; end;
function CalculateIndexOffset(AID: Integer): Integer; virtual;
function GetData(AID: Integer; AIndex: TGenericIndex): TMulBlock; reintroduce; virtual; abstract; { TIndexedMulProvider }
procedure SetData(AID: Integer; AIndex: TGenericIndex; ABlock: TMulBlock); reintroduce; virtual;
function GetVarious(AID: Integer; ABlock: TMulBlock; ADefault: Integer): Integer; virtual; TIndexedMulProvider = class(TMulProvider)
public constructor Create(AData, AIndex: TStream; AReadOnly: Boolean = False); overload; virtual;
function GetBlock(AID: Integer): TMulBlock; override; constructor Create(AData, AIndex: string; AReadOnly: Boolean = False); overload; virtual;
procedure GetBlockEx(AID: Integer; var ABlock: TMulBlock; var AIndex: TGenericIndex); virtual; destructor Destroy; override;
procedure SetBlock(AID: Integer; ABlock: TMulBlock); override; protected
function Exists(AID: Integer): Boolean; virtual; FIndex: TBufferedReader;
procedure Defragment(ATempStream: TStream; AOnProgress: TOnProgressEvent = nil); virtual; function CalculateIndexOffset(AID: Integer): Integer; virtual;
property Index: TBufferedReader read FIndex; function GetData(AID: Integer; AIndex: TGenericIndex): TMulBlock; reintroduce; virtual; abstract;
end; procedure SetData(AID: Integer; AIndex: TGenericIndex; ABlock: TMulBlock); reintroduce; virtual;
function GetVarious(AID: Integer; ABlock: TMulBlock; ADefault: Integer): Integer; virtual;
implementation public
function GetBlock(AID: Integer): TMulBlock; override;
type procedure GetBlockEx(AID: Integer; var ABlock: TMulBlock; var AIndex: TGenericIndex); virtual;
PMethod = ^TMethod; procedure SetBlock(AID: Integer; ABlock: TMulBlock); override;
function Exists(AID: Integer): Boolean; virtual;
{ TMulEventHandler } procedure Defragment(ATempStream: TStream; AOnProgress: TOnProgressEvent = nil); virtual;
property Index: TBufferedReader read FIndex;
constructor TMulEventHandler.Create; end;
begin
inherited; implementation
FEvents := TList.Create;
end; type
PMethod = ^TMethod;
destructor TMulEventHandler.Destroy;
var { TMulEventHandler }
i: Integer;
begin constructor TMulEventHandler.Create;
if Assigned(FEvents) then begin
begin inherited;
for i := 0 to FEvents.Count - 1 do FEvents := TList.Create;
Dispose(PMethod(FEvents.Items[i])); end;
FreeAndNil(FEvents);
end; destructor TMulEventHandler.Destroy;
inherited; var
end; i: Integer;
begin
procedure TMulEventHandler.FireEvents(ABlock: TMulBlock); if Assigned(FEvents) then
var begin
i: Integer; for i := 0 to FEvents.Count - 1 do
begin Dispose(PMethod(FEvents.Items[i]));
for i := 0 to FEvents.Count - 1 do FreeAndNil(FEvents);
TMulBlockChanged(FEvents.Items[i]^)(ABlock); end;
end; inherited;
end;
procedure TMulEventHandler.RegisterEvent(AEvent: TMulBlockChanged);
var procedure TMulEventHandler.FireEvents(ABlock: TMulBlock);
eventInfo: PMethod; var
begin i: Integer;
UnregisterEvent(AEvent); begin
New(eventInfo); for i := 0 to FEvents.Count - 1 do
eventInfo^.Code := TMethod(AEvent).Code; TMulBlockChanged(FEvents.Items[i]^)(ABlock);
eventInfo^.Data := TMethod(AEvent).Data; end;
FEvents.Add(eventInfo);
end; procedure TMulEventHandler.RegisterEvent(AEvent: TMulBlockChanged);
var
procedure TMulEventHandler.UnregisterEvent(AEvent: TMulBlockChanged); eventInfo: PMethod;
var begin
i: Integer; UnregisterEvent(AEvent);
New(eventInfo);
function RemoveEntry: Boolean; eventInfo^.Code := TMethod(AEvent).Code;
begin eventInfo^.Data := TMethod(AEvent).Data;
Dispose(PMethod(FEvents.Items[i])); FEvents.Add(eventInfo);
FEvents.Delete(i); end;
Result := True;
end; procedure TMulEventHandler.UnregisterEvent(AEvent: TMulBlockChanged);
var
begin i: Integer;
i := 0;
while (i < FEvents.Count) and ((TMethod(AEvent).Code <> TMethod(FEvents.Items[i]^).Code) or (TMethod(AEvent).Data <> TMethod(FEvents.Items[i]^).Data) or not RemoveEntry) do function RemoveEntry: Boolean;
Inc(i); begin
end; Dispose(PMethod(FEvents.Items[i]));
FEvents.Delete(i);
{ TMulProvider } Result := True;
end;
constructor TMulProvider.Create(AData: TStream; AReadOnly: Boolean = False);
begin begin
Create; i := 0;
FData := AData; while (i < FEvents.Count) and ((TMethod(AEvent).Code <> TMethod(FEvents.Items[i]^).Code) or (TMethod(AEvent).Data <> TMethod(FEvents.Items[i]^).Data) or not RemoveEntry) do
FOwnsData := False; Inc(i);
FReadOnly := AReadOnly; end;
end;
{ TMulProvider }
constructor TMulProvider.Create(AData: string; AReadOnly: Boolean = False);
var constructor TMulProvider.Create(AData: TStream; AReadOnly: Boolean = False);
mode: Word; begin
begin Create;
Create; FData := AData;
if AReadOnly then FOwnsData := False;
mode := fmOpenRead or fmShareDenyWrite FReadOnly := AReadOnly;
else end;
mode := fmOpenReadWrite or fmShareDenyWrite;
FData := TFileStream.Create(AData, mode); constructor TMulProvider.Create(AData: string; AReadOnly: Boolean = False);
FOwnsData := True; var
FReadOnly := AReadOnly; mode: Word;
end; begin
Create;
constructor TMulProvider.Create; if AReadOnly then
begin mode := fmOpenRead or fmShareDenyWrite
inherited; else
FChangeEvents := TMulEventHandler.Create; mode := fmOpenReadWrite or fmShareDenyWrite;
FFinishedEvents := TMulEventHandler.Create; FData := TFileStream.Create(AData, mode);
end; FOwnsData := True;
FReadOnly := AReadOnly;
destructor TMulProvider.Destroy; end;
begin
if FOwnsData and Assigned(FData) then FreeAndNil(FData); constructor TMulProvider.Create;
if Assigned(FChangeEvents) then FreeAndNil(FChangeEvents); begin
if Assigned(FFinishedEvents) then FreeAndNil(FFinishedEvents); inherited;
inherited; FChangeEvents := TMulEventHandler.Create;
end; FFinishedEvents := TMulEventHandler.Create;
end;
function TMulProvider.GetBlock(AID: Integer): TMulBlock;
begin destructor TMulProvider.Destroy;
Result := GetData(AID, CalculateOffset(AID)); begin
Result.OnChanged := @OnChanged; if FOwnsData and Assigned(FData) then FreeAndNil(FData);
Result.OnFinished := @OnFinished; if Assigned(FChangeEvents) then FreeAndNil(FChangeEvents);
end; if Assigned(FFinishedEvents) then FreeAndNil(FFinishedEvents);
inherited;
procedure TMulProvider.OnChanged(ABlock: TMulBlock); end;
begin
SetBlock(ABlock.ID, ABlock); function TMulProvider.GetBlock(AID: Integer): TMulBlock;
FChangeEvents.FireEvents(ABlock); begin
end; Result := GetData(AID, CalculateOffset(AID));
Result.OnChanged := @OnChanged;
procedure TMulProvider.OnFinished(ABlock: TMulBlock); Result.OnFinished := @OnFinished;
begin end;
FFinishedEvents.FireEvents(ABlock);
ABlock.Free; procedure TMulProvider.OnChanged(ABlock: TMulBlock);
end; begin
SetBlock(ABlock.ID, ABlock);
procedure TMulProvider.RegisterOnChangeEvent(AEvent: TMulBlockChanged); FChangeEvents.FireEvents(ABlock);
begin end;
FChangeEvents.RegisterEvent(AEvent);
end; procedure TMulProvider.OnFinished(ABlock: TMulBlock);
begin
procedure TMulProvider.RegisterOnFinishedEvent(AEvent: TMulBlockChanged); FFinishedEvents.FireEvents(ABlock);
begin ABlock.Free;
FFinishedEvents.RegisterEvent(AEvent); end;
end;
procedure TMulProvider.RegisterOnChangeEvent(AEvent: TMulBlockChanged);
procedure TMulProvider.SetBlock(AID: Integer; ABlock: TMulBlock); begin
begin FChangeEvents.RegisterEvent(AEvent);
if FReadOnly then Exit; end;
SetData(AID, CalculateOffset(AID), ABlock);
end; procedure TMulProvider.RegisterOnFinishedEvent(AEvent: TMulBlockChanged);
begin
procedure TMulProvider.SetData(AID, AOffset: Integer; ABlock: TMulBlock); FFinishedEvents.RegisterEvent(AEvent);
begin end;
if FReadOnly then Exit;
FData.Position := AOffset; procedure TMulProvider.SetBlock(AID: Integer; ABlock: TMulBlock);
ABlock.Write(FData); begin
end; if FReadOnly then Exit;
SetData(AID, CalculateOffset(AID), ABlock);
procedure TMulProvider.UnregisterOnChangeEvent(AEvent: TMulBlockChanged); end;
begin
FChangeEvents.UnregisterEvent(AEvent); procedure TMulProvider.SetData(AID, AOffset: Integer; ABlock: TMulBlock);
end; begin
if FReadOnly then Exit;
procedure TMulProvider.UnregisterOnFinishedEvent(AEvent: TMulBlockChanged); FData.Position := AOffset;
begin ABlock.Write(FData);
FFinishedEvents.UnregisterEvent(AEvent); end;
end;
procedure TMulProvider.UnregisterOnChangeEvent(AEvent: TMulBlockChanged);
{ TIndexedMulProvider } begin
FChangeEvents.UnregisterEvent(AEvent);
function TIndexedMulProvider.CalculateIndexOffset(AID: Integer): Integer; end;
begin
Result := 12 * AID; procedure TMulProvider.UnregisterOnFinishedEvent(AEvent: TMulBlockChanged);
end; begin
FFinishedEvents.UnregisterEvent(AEvent);
constructor TIndexedMulProvider.Create(AData, AIndex: TStream; AReadOnly: Boolean = False); end;
begin
inherited Create(AData, AReadOnly); { TIndexedMulProvider }
FIndex := TBufferedReader.Create(AIndex);
end; function TIndexedMulProvider.CalculateIndexOffset(AID: Integer): Integer;
begin
constructor TIndexedMulProvider.Create(AData, AIndex: string; AReadOnly: Boolean = False); Result := 12 * AID;
var end;
mode: Word;
begin constructor TIndexedMulProvider.Create(AData, AIndex: TStream; AReadOnly: Boolean = False);
inherited Create(AData, AReadOnly); begin
if AReadOnly then inherited Create(AData, AReadOnly);
mode := fmOpenRead or fmShareDenyWrite FIndex := TBufferedReader.Create(AIndex);
else end;
mode := fmOpenReadWrite or fmShareDenyWrite;
FIndex := TBufferedReader.Create(TFileStream.Create(AIndex, mode), True); constructor TIndexedMulProvider.Create(AData, AIndex: string; AReadOnly: Boolean = False);
end; var
mode: Word;
procedure TIndexedMulProvider.Defragment(ATempStream: TStream; AOnProgress: TOnProgressEvent = nil); begin
var inherited Create(AData, AReadOnly);
genericIndex: TGenericIndex; if AReadOnly then
begin mode := fmOpenRead or fmShareDenyWrite
if FReadOnly then Exit; else
ATempStream.Size := FData.Size; mode := fmOpenReadWrite or fmShareDenyWrite;
ATempStream.Position := 0; FIndex := TBufferedReader.Create(TFileStream.Create(AIndex, mode), True);
FIndex.Position := 0; end;
while FIndex.Position < FIndex.Size do
begin procedure TIndexedMulProvider.Defragment(ATempStream: TStream; AOnProgress: TOnProgressEvent = nil);
genericIndex := TGenericIndex.Create(FIndex); var
if genericIndex.Lookup <> LongInt($FFFFFFFF) then genericIndex: TGenericIndex;
begin begin
FData.Position := genericIndex.Lookup; if FReadOnly then Exit;
genericIndex.Lookup := ATempStream.Position; ATempStream.Size := FData.Size;
ATempStream.CopyFrom(FData, genericIndex.Size); ATempStream.Position := 0;
FIndex.Seek(-12, soFromCurrent); FIndex.Position := 0;
genericIndex.Write(FIndex); while FIndex.Position < FIndex.Size do
end; begin
genericIndex.Free; genericIndex := TGenericIndex.Create(FIndex);
if Assigned(AOnProgress) and (FIndex.Position mod 1200 = 0) then if genericIndex.Lookup <> LongInt($FFFFFFFF) then
AOnProgress(FIndex.Size, FIndex.Position); begin
end; FData.Position := genericIndex.Lookup;
FData.Size := ATempStream.Position; genericIndex.Lookup := ATempStream.Position;
FData.Position := 0; ATempStream.CopyFrom(FData, genericIndex.Size);
ATempStream.Position := 0; FIndex.Seek(-12, soFromCurrent);
FData.CopyFrom(ATempStream, FData.Size); genericIndex.Write(FIndex);
end; end;
genericIndex.Free;
destructor TIndexedMulProvider.Destroy; if Assigned(AOnProgress) and (FIndex.Position mod 1200 = 0) then
begin AOnProgress(FIndex.Size, FIndex.Position);
if Assigned(FIndex) then FreeAndNil(FIndex); end;
inherited; FData.Size := ATempStream.Position;
end; FData.Position := 0;
ATempStream.Position := 0;
function TIndexedMulProvider.Exists(AID: Integer): Boolean; FData.CopyFrom(ATempStream, FData.Size);
var end;
genericIndex: TGenericIndex;
begin destructor TIndexedMulProvider.Destroy;
FIndex.Position := CalculateIndexOffset(AID); begin
genericIndex := TGenericIndex.Create(FIndex); if Assigned(FIndex) then FreeAndNil(FIndex);
Result := genericIndex.Lookup <> LongInt($FFFFFFFF); inherited;
genericIndex.Free; end;
end;
function TIndexedMulProvider.Exists(AID: Integer): Boolean;
function TIndexedMulProvider.GetBlock(AID: Integer): TMulBlock; var
var genericIndex: TGenericIndex;
genericIndex: TGenericIndex; begin
begin FIndex.Position := CalculateIndexOffset(AID);
GetBlockEx(AID, Result, genericIndex); genericIndex := TGenericIndex.Create(FIndex);
genericIndex.Free; Result := (genericIndex.Lookup > -1) and (genericIndex.Size > 0);
end; genericIndex.Free;
end;
procedure TIndexedMulProvider.GetBlockEx(AID: Integer;
var ABlock: TMulBlock; var AIndex: TGenericIndex); function TIndexedMulProvider.GetBlock(AID: Integer): TMulBlock;
begin var
FIndex.Position := CalculateIndexOffset(AID); genericIndex: TGenericIndex;
AIndex := TGenericIndex.Create(FIndex); begin
ABlock := GetData(AID, AIndex); GetBlockEx(AID, Result, genericIndex);
ABlock.OnChanged := @OnChanged; genericIndex.Free;
ABlock.OnFinished := @OnFinished; end;
end;
procedure TIndexedMulProvider.GetBlockEx(AID: Integer;
function TIndexedMulProvider.GetVarious(AID: Integer; ABlock: TMulBlock; var ABlock: TMulBlock; var AIndex: TGenericIndex);
ADefault: Integer): Integer; begin
begin FIndex.Position := CalculateIndexOffset(AID);
Result := ADefault; AIndex := TGenericIndex.Create(FIndex);
end; ABlock := GetData(AID, AIndex);
ABlock.OnChanged := @OnChanged;
procedure TIndexedMulProvider.SetBlock(AID: Integer; ABlock: TMulBlock); ABlock.OnFinished := @OnFinished;
var end;
genericIndex: TGenericIndex;
begin function TIndexedMulProvider.GetVarious(AID: Integer; ABlock: TMulBlock;
if FReadOnly then Exit; ADefault: Integer): Integer;
FIndex.Position := CalculateIndexOffset(AID); begin
genericIndex := TGenericIndex.Create(FIndex); Result := ADefault;
SetData(AID, genericIndex, ABlock); end;
FIndex.Position := CalculateIndexOffset(AID);
genericIndex.Various := GetVarious(AID, ABlock, genericIndex.Various); procedure TIndexedMulProvider.SetBlock(AID: Integer; ABlock: TMulBlock);
genericIndex.Write(FIndex); var
genericIndex.Free; genericIndex: TGenericIndex;
end; begin
if FReadOnly then Exit;
procedure TIndexedMulProvider.SetData(AID: Integer; AIndex: TGenericIndex; FIndex.Position := CalculateIndexOffset(AID);
ABlock: TMulBlock); genericIndex := TGenericIndex.Create(FIndex);
var SetData(AID, genericIndex, ABlock);
size: Integer; FIndex.Position := CalculateIndexOffset(AID);
begin genericIndex.Various := GetVarious(AID, ABlock, genericIndex.Various);
if FReadOnly then Exit; genericIndex.Write(FIndex);
size := ABlock.GetSize; genericIndex.Free;
if size = 0 then end;
begin
AIndex.Lookup := LongInt($FFFFFFFF); procedure TIndexedMulProvider.SetData(AID: Integer; AIndex: TGenericIndex;
AIndex.Various := LongInt($FFFFFFFF); ABlock: TMulBlock);
end else if (size > AIndex.Size) or (AIndex.Lookup = LongInt($FFFFFFFF)) then var
begin size: Integer;
FData.Position := FData.Size; begin
AIndex.Lookup := FData.Position; if FReadOnly then Exit;
ABlock.Write(FData); size := ABlock.GetSize;
end else if size = 0 then
begin begin
FData.Position := AIndex.Lookup; AIndex.Lookup := LongInt($FFFFFFFF);
ABlock.Write(FData); AIndex.Various := LongInt($FFFFFFFF);
end; end else if (size > AIndex.Size) or (AIndex.Lookup = LongInt($FFFFFFFF)) then
AIndex.Size := size; begin
end; FData.Position := FData.Size;
AIndex.Lookup := FData.Position;
end. ABlock.Write(FData);
end else
begin
FData.Position := AIndex.Lookup;
ABlock.Write(FData);
end;
AIndex.Size := size;
end;
end.

View File

@ -1,56 +1,56 @@
(* (*
* CDDL HEADER START * CDDL HEADER START
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only * Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance * (the "License"). You may not use this file except in compliance
* with the License. * with the License.
* *
* You can obtain a copy of the license at * You can obtain a copy of the license at
* http://www.opensource.org/licenses/cddl1.php. * http://www.opensource.org/licenses/cddl1.php.
* See the License for the specific language governing permissions * See the License for the specific language governing permissions
* and limitations under the License. * and limitations under the License.
* *
* When distributing Covered Code, include this CDDL HEADER in each * When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at * file and include the License file at
* http://www.opensource.org/licenses/cddl1.php. If applicable, * http://www.opensource.org/licenses/cddl1.php. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed * add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying * information: * by brackets "[]" replaced with your own identifying * information:
* Portions Copyright [yyyy] [name of copyright owner] * Portions Copyright [yyyy] [name of copyright owner]
* *
* CDDL HEADER END * CDDL HEADER END
* *
* *
* Portions Copyright 2007 Andreas Schneider * Portions Copyright 2009 Andreas Schneider
*) *)
unit UTexmapProvider; unit UTexmapProvider;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
interface interface
uses uses
UMulProvider, UMulBlock, UGenericIndex, UTexture; UMulProvider, UMulBlock, UGenericIndex, UTexture;
type type
TTexmapProvider = class(TIndexedMulProvider) TTexmapProvider = class(TIndexedMulProvider)
protected protected
function GetData(AID: Integer; AIndex: TGenericIndex): TMulBlock; override; function GetData(AID: Integer; AIndex: TGenericIndex): TMulBlock; override;
end; end;
implementation implementation
{ TTexmapProvider } { TTexmapProvider }
function TTexmapProvider.GetData(AID: Integer; AIndex: TGenericIndex): TMulBlock; function TTexmapProvider.GetData(AID: Integer; AIndex: TGenericIndex): TMulBlock;
begin begin
if AIndex.Lookup <> LongInt($FFFFFFFF) then if (AIndex.Lookup > -1) and (AIndex.Size > 0) then
Result := TTexture.Create(FData, AIndex) Result := TTexture.Create(FData, AIndex)
else else
Result := TTexture.Create(-1); Result := TTexture.Create(-1);
Result.ID := AID; Result.ID := AID;
end; end;
end. end.