AsphyrePalettes.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:25k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit AsphyrePalettes;
  2. //---------------------------------------------------------------------------
  3. interface
  4. //---------------------------------------------------------------------------
  5. uses
  6.  Classes, SysUtils, Math, StreamEx, TrueColors, AsphyreUtils;
  7. //---------------------------------------------------------------------------
  8. type
  9.  TNodeType = (ntPlain, ntSine, ntAccel, ntBrake);
  10. //---------------------------------------------------------------------------
  11.  PAsphyreColorNode = ^TAsphyreColorNode;
  12.  TAsphyreColorNode = record
  13.   Color   : TTrueColor;
  14.   NodeType: TNodeType;
  15.   Theta   : Real;
  16.  end;
  17. //---------------------------------------------------------------------------
  18.  TAsphyrePalette = class
  19.  private
  20.   Data : array of TAsphyreColorNode;
  21.   FTime: Real;
  22.   FName: string;
  23.   function GetCount(): Integer;
  24.   function GetItem(Num: Integer): PAsphyreColorNode;
  25.   function GetFirstColor(Theta: Real): PAsphyreColorNode;
  26.   function GetColor(Theta: Real): TTrueColor;
  27.   function GetNextColor(Theta: Real): PAsphyreColorNode;
  28.   procedure SetTime(const Value: Real);
  29.  public
  30.   property Count: Integer read GetCount;
  31.   property Items[Num: Integer]: PAsphyreColorNode read GetItem; default;
  32.   property Color[Theta: Real]: TTrueColor read GetColor;
  33.   property Time: Real read FTime write SetTime;
  34.   property Name: string read FName write FName;
  35.   function Add(Color: TTrueColor; NodeType: TNodeType; Theta: Real): Integer; overload;
  36.   function Add(Node: TAsphyreColorNode): Integer; overload;
  37.   function Add(Diffuse: Longword; Theta: Real): Integer; overload;
  38.   procedure Remove(Num: Integer);
  39.   procedure Clear();
  40.   procedure SaveToStream(Stream: TStream);
  41.   procedure LoadFromStream(Stream: TStream);
  42.   procedure SaveToFile(Filename: string);
  43.   procedure LoadFromFile(Filename: string);
  44.   procedure Assign(Source: TAsphyrePalette);
  45.   constructor Create();
  46.   destructor Destroy(); override;
  47.  end;
  48. //---------------------------------------------------------------------------
  49.  TAsphyrePalettes = class
  50.  private
  51.   Data: array of TAsphyrePalette;
  52.   FTitle: string;
  53.   function GetCount(): Integer;
  54.   procedure SetCount(const Value: Integer);
  55.   function GetItem(Num: Integer): TAsphyrePalette;
  56.   procedure SetItem(Num: Integer; const Value: TAsphyrePalette);
  57.   function GetColor(Theta, Time: Real): TTrueColor;
  58.   function GetFirstPal(Time: Real): TAsphyrePalette;
  59.   function GetPrevPal(Time: Real): TAsphyrePalette;
  60.   function GetSuccPal(Time: Real): TAsphyrePalette;
  61.  public
  62.   property Count: Integer read GetCount write SetCount;
  63.   property Items[Num: Integer]: TAsphyrePalette read GetItem write SetItem; default;
  64.   property Color[Theta, Time: Real]: TTrueColor read GetColor;
  65.   property Title: string read FTitle write FTitle;
  66.   function Add(): Integer; overload;
  67.   procedure Add(Color0, Color1, Color2, Color3: Longword); overload;
  68.   procedure Remove(Num: Integer);
  69.   function Find(Name: string): Integer;
  70.   procedure Clear();
  71.   procedure Assign(Source: TAsphyrePalettes);
  72.   procedure SaveToStream(Stream: TStream);
  73.   procedure LoadFromStream(Stream: TStream);
  74.   function LoadFromFile(const Name: string): Boolean;
  75.   function SaveToFile(const Name: string): Boolean;
  76.   constructor Create();
  77.   destructor Destroy(); override;
  78.  end;
  79. //---------------------------------------------------------------------------
  80.  TAsphyrePaletteSet = class
  81.  private
  82.   Data: array of TAsphyrePalettes;
  83.   function GetCount(): Integer;
  84.   function GetItem(Num: Integer): TAsphyrePalettes;
  85.   procedure SetItem(Num: Integer; const Value: TAsphyrePalettes);
  86.  public
  87.   property Count: Integer read GetCount;
  88.   property Item[Num: Integer]: TAsphyrePalettes read GetItem write SetItem; default;
  89.   function Add(): Integer;
  90.   procedure Remove(Num: Integer);
  91.   procedure RemoveAll();
  92.   function Find(Title: string): Integer;
  93.   procedure SaveToStream(Stream: TStream);
  94.   procedure LoadFromStream(Stream: TStream);
  95.   function LoadFromFile(const Name: string): Boolean;
  96.   function SaveToFile(const Name: string): Boolean;
  97.   constructor Create();
  98.   destructor Destroy(); override;
  99.  end;
  100. //---------------------------------------------------------------------------
  101. implementation
  102. //---------------------------------------------------------------------------
  103. constructor TAsphyrePalette.Create();
  104. begin
  105.  inherited;
  106.  SetLength(Data, 0);
  107.  FTime:= 0.0;
  108.  FName:= '';
  109. end;
  110. //---------------------------------------------------------------------------
  111. destructor TAsphyrePalette.Destroy();
  112. begin
  113.  Clear();
  114.  inherited;
  115. end;
  116. //---------------------------------------------------------------------------
  117. function TAsphyrePalette.GetCount(): Integer;
  118. begin
  119.  Result:= Length(Data);
  120. end;
  121. //---------------------------------------------------------------------------
  122. function TAsphyrePalette.GetItem(Num: Integer): PAsphyreColorNode;
  123. begin
  124.  if (Num < 0)or(Num >= Length(Data)) then
  125.   begin
  126.    Result:= nil;
  127.    Exit;
  128.   end;
  129.  Result:= @Data[Num];
  130. end;
  131. //---------------------------------------------------------------------------
  132. function TAsphyrePalette.Add(Color: TTrueColor; NodeType: TNodeType; Theta: Real): Integer;
  133. var
  134.  Index: Integer;
  135. begin
  136.  Index:= Length(Data);
  137.  SetLength(Data, Index + 1);
  138.  Data[Index].Color:= Color;
  139.  Data[Index].NodeType:= NodeType;
  140.  Data[Index].Theta:= Theta;
  141.  Result:= Index;
  142. end;
  143. //---------------------------------------------------------------------------
  144. function TAsphyrePalette.Add(Node: TAsphyreColorNode): Integer;
  145. begin
  146.  Result:= Add(Node.Color, Node.NodeType, Node.Theta);
  147. end;
  148. //---------------------------------------------------------------------------
  149. procedure TAsphyrePalette.Remove(Num: Integer);
  150. var
  151.  i: Integer;
  152. begin
  153.  for i:= Num to Length(Data) - 2 do
  154.   Data[i]:= Data[i + 1];
  155.  SetLength(Data, Length(Data) - 1);
  156. end;
  157. //---------------------------------------------------------------------------
  158. function TAsphyrePalette.Add(Diffuse: Longword; Theta: Real): Integer;
  159. begin
  160.  Result:= Add(Diffuse, ntPlain, Theta);
  161. end;
  162. //---------------------------------------------------------------------------
  163. procedure TAsphyrePalette.Clear();
  164. begin
  165.  SetLength(Data, 0);
  166. end;
  167. //--------------------------------------------------------------------------
  168. function TAsphyrePalette.GetFirstColor(Theta: Real): PAsphyreColorNode;
  169. var
  170.  i, Frame, wIndex: Integer;
  171.  Delta, NewDelta, WorstD: Real;
  172. begin
  173.  Delta:= High(Integer);
  174.  Frame:= -1;
  175.  wIndex:= -1;
  176.  WorstD:= High(Integer);
  177.  for i:= 0 to Length(Data) - 1 do
  178.    begin
  179.     NewDelta:= Abs(Theta - Data[i].Theta);
  180.     if (Data[i].Theta <= Theta)and(NewDelta < Delta) then
  181.      begin
  182.       Frame:= i;
  183.       Delta:= NewDelta;
  184.      end;
  185.     if (NewDelta < WorstD) then
  186.      begin
  187.       wIndex:= i;
  188.       WorstD:= NewDelta;
  189.      end;
  190.    end;
  191.  if (Frame = -1) then
  192.   begin
  193.    Result:= nil;
  194.    if (wIndex <> -1) then Result:= @Data[wIndex];
  195.   end else Result:= @Data[Frame];
  196. end;
  197. //--------------------------------------------------------------------------
  198. function TAsphyrePalette.GetNextColor(Theta: Real): PAsphyreColorNode;
  199. var
  200.  i, Frame, wIndex: Integer;
  201.  Delta, NewDelta, wDelta: Real;
  202. begin
  203.  Delta:= High(Integer);
  204.  Frame:= -1;
  205.  wIndex:= -1;
  206.  wDelta:= High(Integer);
  207.  for i:= 0 to Length(Data) - 1 do
  208.    begin
  209.     NewDelta:= Abs(Data[i].Theta - Theta);
  210.     if (Data[i].Theta > Theta)and(NewDelta < Delta) then
  211.      begin
  212.       Frame:= i;
  213.       Delta:= NewDelta;
  214.      end;
  215.     if (wDelta > NewDelta) then
  216.      begin
  217.       wDelta:= NewDelta;
  218.       wIndex:= i;
  219.      end;  
  220.    end;
  221.  if (Frame = -1) then
  222.   begin
  223.    Result:= nil;
  224.    if (wIndex <> -1) then Result:= @Data[wIndex];
  225.   end else Result:= @Data[Frame];
  226. end;
  227. //---------------------------------------------------------------------------
  228. function TAsphyrePalette.GetColor(Theta: Real): TTrueColor;
  229. const
  230.  PiHalf = Pi * 0.5;
  231. var
  232.  First, Next: PAsphyreColorNode;
  233.  MyTheta: Real;
  234. begin
  235.  // no colors
  236.  if (Length(Data) < 1) then
  237.   begin
  238.    Result.r:= 0.0;
  239.    Result.g:= 0.0;
  240.    Result.b:= 0.0;
  241.    Result.a:= 0.0;
  242.    Exit;
  243.   end;
  244.  // retreive initial color
  245.  First:= GetFirstColor(Theta);
  246.  // use First Color info directly if one of the following is met:
  247.  //  1) Color has exact Theta match
  248.  //  2) Color happens after the Theta (and is the first one)
  249.  if (First.Theta = Theta)or(First.Theta > Theta) then
  250.   begin
  251.    Result:= First.Color;
  252.    Exit;
  253.   end;
  254.  // retreive the next color (to interpolate with)
  255.  Next:= GetNextColor(Theta);
  256.  // if there is no difference in time between two frames, return the next one
  257.  if (Next.Theta = First.Theta)or(Next.Theta = Theta)or(Next = First) then
  258.   begin
  259.    Result:= Next.Color;
  260.    Exit;
  261.   end;
  262.  // calculate interpolation value
  263.  MyTheta:= (Theta - First.Theta) / (Next.Theta - First.Theta);
  264.  // --> initial sine curve
  265.  if ((First.NodeType = ntSine)or(First.NodeType = ntAccel)) then
  266.   begin
  267.    if ((Next.NodeType = ntSine)or(Next.NodeType = ntBrake)) then
  268.     MyTheta:= (Sin((MyTheta * Pi) - PiHalf) + 1.0) / 2.0
  269.      else MyTheta:= Sin((MyTheta * PiHalf) - PiHalf) + 1.0;
  270.   end else
  271.   begin
  272.    if ((Next.NodeType = ntSine)or(Next.NodeType = ntBrake)) then
  273.     MyTheta:= Sin(MyTheta * PiHalf);
  274.   end;
  275.  Result:= AlphaBlendTC(First.Color, Next.Color, MyTheta);
  276. end;
  277. //---------------------------------------------------------------------------
  278. procedure TAsphyrePalette.LoadFromFile(Filename: string);
  279. var
  280.  Stream: TStream;
  281. begin
  282.  Stream:= TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
  283.  try
  284.   LoadFromStream(Stream);
  285.  finally
  286.   Stream.Free();
  287.  end; 
  288. end;
  289. //---------------------------------------------------------------------------
  290. procedure TAsphyrePalette.SaveToFile(Filename: string);
  291. var
  292.  Stream: TStream;
  293. begin
  294.  Stream:= TFileStream.Create(Filename, fmCreate or fmShareExclusive);
  295.  try
  296.   SaveToStream(Stream);
  297.  finally
  298.   Stream.Free();
  299.  end;
  300. end;
  301. //---------------------------------------------------------------------------
  302. procedure TAsphyrePalette.SaveToStream(Stream: TStream);
  303. var
  304.  Count, i: Integer;
  305. begin
  306.  stWriteString(Stream, FName);
  307.  stWriteDouble(Stream, FTime);
  308.  Count:= Length(Data);
  309.  Stream.WriteBuffer(Count, SizeOf(Integer));
  310.  for i:= 0 to Count - 1 do
  311.   Stream.WriteBuffer(Data[i], SizeOf(TAsphyreColorNode));
  312. end;
  313. //---------------------------------------------------------------------------
  314. procedure TAsphyrePalette.LoadFromStream(Stream: TStream);
  315. var
  316.  Count, i: Integer;
  317. begin
  318.  FName:= stReadString(Stream);
  319.  FTime:= stReadDouble(Stream);
  320.  Stream.ReadBuffer(Count, SizeOf(Integer));
  321.  SetLength(Data, Count);
  322.  for i:= 0 to Count - 1 do
  323.   Stream.ReadBuffer(Data[i], SizeOf(TAsphyreColorNode));
  324. end;
  325. //---------------------------------------------------------------------------
  326. procedure TAsphyrePalette.Assign(Source: TAsphyrePalette);
  327. var
  328.  i: Integer;
  329. begin
  330.  FName:= Source.Name;
  331.  Time := Source.Time;
  332.  Clear();
  333.  for i:= 0 to Source.Count - 1 do
  334.   Add(Source[i]^);
  335. end;
  336. //---------------------------------------------------------------------------
  337. procedure TAsphyrePalette.SetTime(const Value: Real);
  338. begin
  339.  FTime:= Max(Min(Value, 1.0), 0.0);
  340. end;
  341. //---------------------------------------------------------------------------
  342. constructor TAsphyrePalettes.Create();
  343. begin
  344.  inherited;
  345.  SetLength(Data, 0);
  346. end;
  347. //---------------------------------------------------------------------------
  348. destructor TAsphyrePalettes.Destroy();
  349. begin
  350.  Clear();
  351.  inherited;
  352. end;
  353. //---------------------------------------------------------------------------
  354. function TAsphyrePalettes.GetCount(): Integer;
  355. begin
  356.  Result:= Length(Data);
  357. end;
  358. //---------------------------------------------------------------------------
  359. procedure TAsphyrePalettes.SetCount(const Value: Integer);
  360. begin
  361.  while (Length(Data) > Value)and(Length(Data) > 0) do Remove(Length(Data) - 1);
  362.  while (Length(Data) < Value) do Add();
  363. end;
  364. //---------------------------------------------------------------------------
  365. function TAsphyrePalettes.GetItem(Num: Integer): TAsphyrePalette;
  366. begin
  367.  if (Num >= 0)and(Num < Length(Data)) then
  368.   Result:= Data[Num] else Result:= nil;
  369. end;
  370. //---------------------------------------------------------------------------
  371. procedure TAsphyrePalettes.SetItem(Num: Integer; const Value: TAsphyrePalette);
  372. begin
  373.  if (Num >= 0)and(Num < Length(Data)) then
  374.   Data[Num].Assign(Value);
  375. end;
  376. //---------------------------------------------------------------------------
  377. function TAsphyrePalettes.Add(): Integer;
  378. var
  379.  Index: Integer;
  380. begin
  381.  Index:= Length(Data);
  382.  SetLength(Data, Index + 1);
  383.  Data[Index]:= TAsphyrePalette.Create();
  384.  Result:= Index;
  385. end;
  386. //---------------------------------------------------------------------------
  387. procedure TAsphyrePalettes.Remove(Num: Integer);
  388. var
  389.  i: Integer;
  390. begin
  391.  if (Num < 0)or(Num >= Length(Data)) then Exit;
  392.  if (Assigned(Data[Num])) then
  393.   begin
  394.    Data[Num].Free();
  395.    Data[Num]:= nil;
  396.   end; 
  397.  for i:= Num to Length(Data) - 2 do
  398.   Data[i]:= Data[i + 1];
  399.  SetLength(Data, Length(Data) - 1);
  400. end;
  401. //---------------------------------------------------------------------------
  402. procedure TAsphyrePalettes.Clear();
  403. var
  404.  i: Integer;
  405. begin
  406.  for i:= 0 to Length(Data) - 1 do
  407.   if (Assigned(Data[i])) then
  408.    begin
  409.     Data[i].Free();
  410.     Data[i]:= nil;
  411.    end;
  412.  SetLength(Data, 0);
  413. end;
  414. //--------------------------------------------------------------------------
  415. function TAsphyrePalettes.GetFirstPal(Time: Real): TAsphyrePalette;
  416. var
  417.  i, LowerIndex, BestIndex: Integer;
  418.  LowerDelta, Delta, BestDelta: Real;
  419. begin
  420.  LowerDelta:= High(Integer);
  421.  BestDelta := High(Integer);
  422.  LowerIndex:= -1;
  423.  BestIndex := -1;
  424.  for i:= 0 to Length(Data) - 1 do
  425.    begin
  426.     Delta:= Abs(Time - Data[i].Time);
  427.     // -> lower index
  428.     if (Data[i].Time <= Time)and(Delta < LowerDelta) then
  429.      begin
  430.       LowerIndex:= i;
  431.       LowerDelta:= Delta;
  432.      end;
  433.     // -> best index
  434.     if (Delta < BestDelta) then
  435.      begin
  436.       BestIndex:= i;
  437.       BestDelta:= Delta;
  438.      end;
  439.    end;
  440.  if (LowerIndex = -1) then
  441.   begin
  442.    Result:= nil;
  443.    if (BestIndex <> -1) then Result:= Data[BestIndex];
  444.   end else Result:= Data[LowerIndex];
  445. end;
  446. //--------------------------------------------------------------------------
  447. function TAsphyrePalettes.GetPrevPal(Time: Real): TAsphyrePalette;
  448. var
  449.  i, LowerIndex, BestIndex: Integer;
  450.  LowerDelta, Delta, BestDelta: Real;
  451. begin
  452.  LowerDelta:= High(Integer);
  453.  BestDelta := High(Integer);
  454.  LowerIndex:= -1;
  455.  BestIndex := -1;
  456.  for i:= 0 to Length(Data) - 1 do
  457.    begin
  458.     Delta:= Abs(Time - Data[i].Time);
  459.     // -> lower index
  460.     if (Data[i].Time < Time)and(Delta < LowerDelta) then
  461.      begin
  462.       LowerIndex:= i;
  463.       LowerDelta:= Delta;
  464.      end;
  465.     // -> best index
  466.     if (Delta < BestDelta) then
  467.      begin
  468.       BestIndex:= i;
  469.       BestDelta:= Delta;
  470.      end;
  471.    end;
  472.  if (LowerIndex = -1) then
  473.   begin
  474.    Result:= nil;
  475.    if (BestIndex <> -1) then Result:= Data[BestIndex];
  476.   end else Result:= Data[LowerIndex];
  477. end;
  478. //--------------------------------------------------------------------------
  479. function TAsphyrePalettes.GetSuccPal(Time: Real): TAsphyrePalette;
  480. var
  481.  i, HigherIndex, BestIndex: Integer;
  482.  HigherDelta, BestDelta, Delta: Real;
  483. begin
  484.  HigherDelta:= High(Integer);
  485.  BestDelta := High(Integer);
  486.  HigherIndex:= -1;
  487.  BestIndex := -1;
  488.  for i:= 0 to Length(Data) - 1 do
  489.    begin
  490.     Delta:= Abs(Data[i].Time - Time);
  491.     // -> higher index
  492.     if (Data[i].Time > Time)and(Delta < HigherDelta) then
  493.      begin
  494.       HigherIndex:= i;
  495.       HigherDelta:= Delta;
  496.      end;
  497.     // -> best index
  498.     if (Delta < BestDelta) then
  499.      begin
  500.       BestIndex:= i;
  501.       BestDelta:= Delta;
  502.      end;
  503.    end;
  504.  if (HigherIndex = -1) then
  505.   begin
  506.    Result:= nil;
  507.    if (BestIndex <> -1) then Result:= Data[BestIndex];
  508.   end else Result:= Data[HigherIndex];
  509. end;
  510. //---------------------------------------------------------------------------
  511. function TAsphyrePalettes.GetColor(Theta, Time: Real): TTrueColor;
  512. const
  513.  PiHalf = Pi * 0.5;
  514. var
  515.  First, Second, Left, Right: TAsphyrePalette;
  516.  Alpha: Real;
  517.  Color0, Color1, Color2, Color3: TTrueColor;
  518. begin
  519.  // no palettes
  520.  if (Length(Data) < 1) then
  521.   begin
  522.    Result.r:= 0.0;
  523.    Result.g:= 0.0;
  524.    Result.b:= 0.0;
  525.    Result.a:= 0.0;
  526.    Exit;
  527.   end;
  528.  // retreive initial palette
  529.  First:= GetFirstPal(Time);
  530.  // use First Palette directly if one of the following is met:
  531.  //  1) Palette has exact Time match
  532.  //  2) Palette appears after the Time
  533.  if (First.Time = Time)or(First.Time > Time) then
  534.   begin
  535.    Result:= First.Color[Theta];
  536.    Exit;
  537.   end;
  538.  // retreive the second palette
  539.  Second:= GetSuccPal(Time);
  540.  // if there is no difference in time between two palettes, return the next one
  541.  if (Second.Time = First.Time)or(Second.Time = Time)or(Second = First) then
  542.   begin
  543.    Result:= Second.Color[Theta];
  544.    Exit;
  545.   end;
  546.  // retreive another two palettes for cubic interpolation
  547.  Left := GetPrevPal(First.Time);
  548.  Right:= GetSuccPal(Second.Time);
  549.  // calculate interpolation value
  550.  Alpha:= (Time - First.Time) / (Second.Time - First.Time);
  551.  // retreive all four colors
  552.  Color0:= Left.Color[Theta];
  553.  Color1:= First.Color[Theta];
  554.  Color2:= Second.Color[Theta];
  555.  Color3:= Right.Color[Theta];
  556.  // interpolate the result
  557.  Result.r:= CatmullRom(Color0.r, Color1.r, Color2.r, Color3.r, Alpha);
  558.  Result.g:= CatmullRom(Color0.g, Color1.g, Color2.g, Color3.g, Alpha);
  559.  Result.b:= CatmullRom(Color0.b, Color1.b, Color2.b, Color3.b, Alpha);
  560.  Result.a:= CatmullRom(Color0.a, Color1.a, Color2.a, Color3.a, Alpha);
  561. { Result.r:= SineTheta(Color1.r, Color2.r, Alpha);
  562.  Result.g:= SineTheta(Color1.g, Color2.g, Alpha);
  563.  Result.b:= SineTheta(Color1.b, Color2.b, Alpha);
  564.  Result.a:= SineTheta(Color1.a, Color2.a, Alpha);}
  565.  Result.r:= Abs(Result.r);
  566.  Result.g:= Abs(Result.g);
  567.  Result.b:= Abs(Result.b);
  568.  Result.a:= Abs(Result.a);
  569.  if (Result.r > 1.0) then Result.r:= 2.0 - Result.r;
  570.  if (Result.g > 1.0) then Result.g:= 2.0 - Result.g;
  571.  if (Result.b > 1.0) then Result.b:= 2.0 - Result.b;
  572.  if (Result.a > 1.0) then Result.a:= 2.0 - Result.a;
  573. { Result.r:= Min(Max(Result.r, 0.0), 1.0);
  574.  Result.g:= Min(Max(Result.g, 0.0), 1.0);
  575.  Result.b:= Min(Max(Result.b, 0.0), 1.0);
  576.  Result.a:= Min(Max(Result.a, 0.0), 1.0);}
  577. end;
  578. //---------------------------------------------------------------------------
  579. procedure TAsphyrePalettes.SaveToStream(Stream: TStream);
  580. var
  581.  Count, i: Integer;
  582. begin
  583.  stWriteString(Stream, FTitle);
  584.  Count:= Length(Data);
  585.  Stream.WriteBuffer(Count, SizeOf(Integer));
  586.  for i:= 0 to Length(Data) - 1 do
  587.   Data[i].SaveToStream(Stream);
  588. end;
  589. //---------------------------------------------------------------------------
  590. procedure TAsphyrePalettes.LoadFromStream(Stream: TStream);
  591. var
  592.  Count, i: Integer;
  593. begin
  594.  FTitle:= stReadString(Stream);
  595.  Stream.ReadBuffer(Count, SizeOf(Integer));
  596.  Clear();
  597.  SetLength(Data, Count);
  598.  for i:= 0 to Length(Data) - 1 do Data[i]:= nil;
  599.  for i:= 0 to Length(Data) - 1 do
  600.   begin
  601.    Data[i]:= TAsphyrePalette.Create();
  602.    Data[i].LoadFromStream(Stream);
  603.   end;
  604. end;
  605. //---------------------------------------------------------------------------
  606. function TAsphyrePalettes.SaveToFile(const Name: string): Boolean;
  607. var
  608.  Stream: TStream;
  609. begin
  610.  Result:= True;
  611.  try
  612.   Stream:= TFileStream.Create(Name, fmCreate or fmShareExclusive);
  613.   try
  614.    SaveToStream(Stream);
  615.   finally
  616.    Stream.Free();
  617.   end; 
  618.  except
  619.   Result:= False;
  620.  end;
  621. end;
  622. //---------------------------------------------------------------------------
  623. function TAsphyrePalettes.LoadFromFile(const Name: string): Boolean;
  624. var
  625.  Stream: TStream;
  626. begin
  627.  Result:= True;
  628.  try
  629.   Stream:= TFileStream.Create(Name, fmOpenRead or fmShareDenyWrite);
  630.   try
  631.    LoadFromStream(Stream);
  632.   finally
  633.    Stream.Free();
  634.   end;
  635.  except
  636.   Result:= False;
  637.  end;
  638. end;
  639. //---------------------------------------------------------------------------
  640. function TAsphyrePalettes.Find(Name: string): Integer;
  641. var
  642.  Index: Integer;
  643. begin
  644.  Name:= LowerCase(Name);
  645.  Result:= -1;
  646.  for Index:= 0 to Length(Data) - 1 do
  647.   if (Name = LowerCase(Data[Index].Name)) then
  648.    begin
  649.     Result:= Index;
  650.     Break;
  651.    end;
  652. end;
  653. //---------------------------------------------------------------------------
  654. procedure TAsphyrePalettes.Assign(Source: TAsphyrePalettes);
  655. var
  656.  i: Integer;
  657. begin
  658.  FTitle:= Source.Title;
  659.  Count:= Source.Count;
  660.  for i:= 0 to Length(Data) - 1 do
  661.   Data[i].Assign(Source[i]);
  662. end;
  663. //---------------------------------------------------------------------------
  664. procedure TAsphyrePalettes.Add(Color0, Color1, Color2, Color3: Longword);
  665. var
  666.  Index: Integer;
  667. begin
  668.  Index:= Add();
  669.  Data[Index].Clear();
  670.  Data[Index].Add(Color0, 0.0);
  671.  Data[Index].Add(Color1, 0.333);
  672.  Data[Index].Add(Color2, 0.667);
  673.  Data[Index].Add(Color3, 1.0);
  674. end;
  675. //---------------------------------------------------------------------------
  676. constructor TAsphyrePaletteSet.Create();
  677. begin
  678.  inherited;
  679.  SetLength(Data, 0);
  680. end;
  681. //---------------------------------------------------------------------------
  682. destructor TAsphyrePaletteSet.Destroy();
  683. begin
  684.  RemoveAll();
  685.  inherited;
  686. end;
  687. //---------------------------------------------------------------------------
  688. function TAsphyrePaletteSet.GetCount(): Integer;
  689. begin
  690.  Result:= Length(Data);
  691. end;
  692. //---------------------------------------------------------------------------
  693. function TAsphyrePaletteSet.GetItem(Num: Integer): TAsphyrePalettes;
  694. begin
  695.  if (Num >= 0)and(Num < Length(Data)) then
  696.   Result:= Data[Num] else Result:= nil;
  697. end;
  698. //---------------------------------------------------------------------------
  699. procedure TAsphyrePaletteSet.SetItem(Num: Integer; const Value: TAsphyrePalettes);
  700. begin
  701.  if (Num >= 0)and(Num < Length(Data)) then
  702.   Data[Num].Assign(Value);
  703. end;
  704. //---------------------------------------------------------------------------
  705. function TAsphyrePaletteSet.Add(): Integer;
  706. var
  707.  Index: Integer;
  708. begin
  709.  Index:= Length(Data);
  710.  SetLength(Data, Index + 1);
  711.  Data[Index]:= TAsphyrePalettes.Create();
  712.  Result:= Index;
  713. end;
  714. //---------------------------------------------------------------------------
  715. procedure TAsphyrePaletteSet.Remove(Num: Integer);
  716. var
  717.  i: Integer;
  718. begin
  719.  if (Num < 0)or(Num >= Length(Data)) then Exit;
  720.  Data[Num].Free();
  721.  for i:= Num to Length(Data) - 2 do
  722.   Data[i]:= Data[i + 1];
  723.  SetLength(Data, Length(Data) - 1); 
  724. end;
  725. //---------------------------------------------------------------------------
  726. procedure TAsphyrePaletteSet.RemoveAll();
  727. var
  728.  i: Integer;
  729. begin
  730.  for i:= 0 to Length(Data) - 1 do
  731.   if (Data[i] <> nil) then
  732.    begin
  733.     Data[i].Free();
  734.     Data[i]:= nil;
  735.    end;
  736.  SetLength(Data, 0);
  737. end;
  738. //---------------------------------------------------------------------------
  739. procedure TAsphyrePaletteSet.SaveToStream(Stream: TStream);
  740. var
  741.  Count, i: Integer;
  742. begin
  743.  Count:= Length(Data);
  744.  Stream.WriteBuffer(Count, SizeOf(Integer));
  745.  for i:= 0 to Length(Data) - 1 do
  746.   Data[i].SaveToStream(Stream);
  747. end;
  748. //---------------------------------------------------------------------------
  749. procedure TAsphyrePaletteSet.LoadFromStream(Stream: TStream);
  750. var
  751.  Count, i: Integer;
  752. begin
  753.  Stream.ReadBuffer(Count, SizeOf(Integer));
  754.  RemoveAll();
  755.  SetLength(Data, Count);
  756.  for i:= 0 to Length(Data) - 1 do Data[i]:= nil;
  757.  for i:= 0 to Length(Data) - 1 do
  758.   begin
  759.    Data[i]:= TAsphyrePalettes.Create();
  760.    Data[i].LoadFromStream(Stream);
  761.   end;
  762. end;
  763. //---------------------------------------------------------------------------
  764. function TAsphyrePaletteSet.SaveToFile(const Name: string): Boolean;
  765. var
  766.  Stream: TStream;
  767. begin
  768.  Result:= True;
  769.  try
  770.   Stream:= TFileStream.Create(Name, fmCreate or fmShareExclusive);
  771.   try
  772.    SaveToStream(Stream);
  773.   finally
  774.    Stream.Free();
  775.   end; 
  776.  except
  777.   Result:= False;
  778.  end;
  779. end;
  780. //---------------------------------------------------------------------------
  781. function TAsphyrePaletteSet.LoadFromFile(const Name: string): Boolean;
  782. var
  783.  Stream: TStream;
  784. begin
  785.  Result:= True;
  786.  try
  787.   Stream:= TFileStream.Create(Name, fmOpenRead or fmShareDenyWrite);
  788.   try
  789.    LoadFromStream(Stream);
  790.   finally
  791.    Stream.Free();
  792.   end;
  793.  except
  794.   Result:= False;
  795.  end;
  796. end;
  797. //---------------------------------------------------------------------------
  798. function TAsphyrePaletteSet.Find(Title: string): Integer;
  799. var
  800.  i: Integer;
  801. begin
  802.  Title:= LowerCase(Title);
  803.  Result:= -1;
  804.  
  805.  for i:= 0 to Length(Data) - 1 do
  806.   if (Title = LowerCase(Data[i].Title)) then
  807.    begin
  808.     Result:= i;
  809.     Break;
  810.    end; 
  811. end;
  812. //---------------------------------------------------------------------------
  813. end.