diff -Nru castle-game-engine-6.4+dfsg1/debian/changelog castle-game-engine-6.4+dfsg1/debian/changelog --- castle-game-engine-6.4+dfsg1/debian/changelog 2020-06-04 16:41:09.000000000 +0000 +++ castle-game-engine-6.4+dfsg1/debian/changelog 2020-08-10 15:24:31.000000000 +0000 @@ -1,3 +1,16 @@ +castle-game-engine (6.4+dfsg1-5) unstable; urgency=medium + + [ Debian Janitor ] + * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository, + Repository-Browse. + + [ Abou Al Montacir ] + * Fix compilation with FPC 3.2.0. (Closes: Bug#968120) + Thanks to Michalis Kamburelis + * Fixed issue with thread manager initialization in fpmake with FPC 3.2.0. + + -- Abou Al Montacir Mon, 10 Aug 2020 17:24:31 +0200 + castle-game-engine (6.4+dfsg1-4) unstable; urgency=medium [ Olivier Tilloy ] diff -Nru castle-game-engine-6.4+dfsg1/debian/gbp.conf castle-game-engine-6.4+dfsg1/debian/gbp.conf --- castle-game-engine-6.4+dfsg1/debian/gbp.conf 2017-07-12 18:52:38.000000000 +0000 +++ castle-game-engine-6.4+dfsg1/debian/gbp.conf 2020-08-10 15:23:23.000000000 +0000 @@ -1,2 +1,14 @@ +[DEFAULT] +pristine-tar = True +cleaner = /bin/true + [import-orig] filter = [ 'doc/pasdoc/reference/*', 'src/fonts/castletexturefont_dejavusans*.pas', 'src/fonts/castletexturefont_djv*.pas', 'src/fonts/data/*.ttf' ] + +[buildpackage] +pbuilder = true +pbuilder-options=--source-only-changes + +[dch] +git-author = true +full = true diff -Nru castle-game-engine-6.4+dfsg1/debian/patches/Fix-compilation-with-FPC-3.2.0.patch castle-game-engine-6.4+dfsg1/debian/patches/Fix-compilation-with-FPC-3.2.0.patch --- castle-game-engine-6.4+dfsg1/debian/patches/Fix-compilation-with-FPC-3.2.0.patch 1970-01-01 00:00:00.000000000 +0000 +++ castle-game-engine-6.4+dfsg1/debian/patches/Fix-compilation-with-FPC-3.2.0.patch 2020-08-10 15:22:30.000000000 +0000 @@ -0,0 +1,444 @@ +From 66e272cbecc76a2f344c044471ea73e26a9a07be Mon Sep 17 00:00:00 2001 +From: Michalis Kamburelis +Date: Sun, 21 Jun 2020 14:12:38 +0200 +Description: Fix compilation with FPC 3.2.0 (these are backported minimal + changes from master branch) + +--- + src/3d/castleboxes.pas | 18 ++++++---- + src/3d/castlequaternions.pas | 18 ++++++---- + src/base/castleconf.inc | 21 +++++++----- + src/base/castleparameters.pas | 48 +++++++++++++-------------- + src/base/castleutils_struct_list.inc | 16 ++++----- + src/x3d/x3dnodes_standard_time.inc | 5 +-- + src/x3d/x3dtime.pas | 10 ++++-- + tools/build-tool/code/toolproject.pas | 4 +-- + 8 files changed, 81 insertions(+), 59 deletions(-) + +diff --git a/src/3d/castleboxes.pas b/src/3d/castleboxes.pas +index 5008efb51..3e1356653 100644 +--- a/src/3d/castleboxes.pas ++++ b/src/3d/castleboxes.pas +@@ -113,12 +113,11 @@ TBox3D = record + public + Data: array [0..1] of TVector3; + +- const +- { Special TBox3D value meaning "bounding box is empty". +- This is different than just bounding box with zero sizes, +- as bounding box with zero sizes still has some position. +- Empty bounding box doesn't contain any portion of 3D space. } +- Empty: TBox3D = (Data: ((Data: (0, 0, 0)), (Data: (-1, -1, -1)))); ++ { Special TBox3D value meaning "bounding box is empty". ++ This is different than just bounding box with zero sizes, ++ as bounding box with zero sizes still has some position. ++ Empty bounding box doesn't contain any portion of 3D space. } ++ class function Empty: TBox3D; static; + + { Check is box empty. + You can think of this function as "compare Box with TBox3D.Empty". +@@ -703,6 +702,13 @@ procedure TBox3D.SetMax(const Value: TVector3); + Data[1] := Value; + end; + ++class function TBox3D.Empty: TBox3D; ++const ++ R: TBox3D = (Data: ((Data: (0, 0, 0)), (Data: (-1, -1, -1)))); ++begin ++ Result := R; ++end; ++ + function TBox3D.IsEmpty: boolean; + begin + Result := Data[0].Data[0] > Data[1].Data[0]; +diff --git a/src/3d/castlequaternions.pas b/src/3d/castlequaternions.pas +index bc6ace7c3..9f45dc3d1 100644 +--- a/src/3d/castlequaternions.pas ++++ b/src/3d/castlequaternions.pas +@@ -39,12 +39,11 @@ TQuaternion = record + Vector4: TVector4); + end; + +- const +- { Quaternion representing @italic("no rotation"). +- Note: this is @italic(not) a quaternion filled with zeros +- (the @code(Data.Real) component is 1.0), instead this is a unit quaternion +- that correctly represents @italic("rotation by zero degrees/radians"). } +- ZeroRotation: TQuaternion = (Data: (Vector: (Data: (0, 0, 0)); Real: 1)); ++ { Quaternion representing @italic("no rotation"). ++ Note: this is @italic(not) a quaternion filled with zeros ++ (the @code(Data.Real) component is 1.0), instead this is a unit quaternion ++ that correctly represents @italic("rotation by zero degrees/radians"). } ++ class function ZeroRotation: TQuaternion; static; + + { Calculate axis (will be normalized) and angle (will be in radians) + of rotation encoded in unit quaternion Q. +@@ -182,6 +181,13 @@ implementation + + { TQuaternion ---------------------------------------------------------------- } + ++class function TQuaternion.ZeroRotation: TQuaternion; static; ++const ++ R: TQuaternion = (Data: (Vector: (Data: (0, 0, 0)); Real: 1)); ++begin ++ Result := R; ++end; ++ + procedure TQuaternion.ToAxisAngle(out Axis: TVector3; + out AngleRad: Single); + { Data is a normalized quaternion, so +diff --git a/src/base/castleconf.inc b/src/base/castleconf.inc +index edf8566c5..5a37ba080 100644 +--- a/src/base/castleconf.inc ++++ b/src/base/castleconf.inc +@@ -142,22 +142,25 @@ + {$undef ALLOW_DLOPEN_FROM_UNIT_INITIALIZATION} + {$endif} + +-// This serves two purposes: ++// *Not* define ENABLE_SELF_RECORD_CONSTANTS because: ++// + // - Declaring something like TVector3.Zero (constant filled with zeros, + // inside a record, which type is the same record) + // causes internal error in FPC 3.0.2, 3.0.4 (not in 3.0.0 or 3.1.1, + // so already fixed in FPC). ++// + // - Declaring something like TVector3.Zero or TVector3.One + // (any constant inside a record, which type is the same record) + // is not allowed in Delphi, causes error that type is not completely defined. +-{$ifdef FPC} +- {$define ENABLE_SELF_RECORD_CONSTANTS} +- {$ifdef VER3_0} +- {$ifndef VER3_0_0} +- {$undef ENABLE_SELF_RECORD_CONSTANTS} +- {$endif} +- {$endif} +-{$endif} ++// ++// - Since FPC 3.3.1 (at least revision 40292, revision 40000 was OK) ++// FPC reports the same error as Delphi ++// (Error: Type "TGenericVector2" is not completely defined). ++// ++// So ENABLE_SELF_RECORD_CONSTANTS is just *never* defined for now. ++// If FPC 3.3.1 will keep this behaviour, we'll just simplify the code ++// in the future to not make this optional. ++{.$define ENABLE_SELF_RECORD_CONSTANTS} + + // Workaround FPC 3.0.0 bug (not present in 3.0.2, 3.0.4, 3.1.1 -- so already fixed). + {$ifdef VER3_0_0} +diff --git a/src/base/castleparameters.pas b/src/base/castleparameters.pas +index 87aac8c73..ae2ff826b 100644 +--- a/src/base/castleparameters.pas ++++ b/src/base/castleparameters.pas +@@ -98,7 +98,7 @@ EMissingOptionArgument = class(EWrongOptionArgument); + type + { Callback used by TParameters.Parse to notify about new option. + +- @param(OptionNum The option number in the Options table (zero-based).) ++ @param(OptionNum The option number in the AOptions table (zero-based).) + + @param(HasArgument Says if you have a single argument in the Argument + parameter. Always @false when your option has oaNone or +@@ -159,7 +159,7 @@ TOption = record + They can be modified to remove the already-handled parameters.) + + @itemLabel @italic(Option) +- @item(Options are things encoded by the user in the parameters. ++ @item(AOptions are things encoded by the user in the parameters. + Examples: + + @unorderedList( +@@ -237,7 +237,7 @@ TParameters = class(TCastleStringList) + function IsPresent(const A: array of string): boolean; + + { Parse command-line parameters. Given a specification of your command-line +- options (in Options), we will find and pass these options to your ++ options (in AOptions), we will find and pass these options to your + OptionProc callback. The handled options will be removed from + the @link(Parameters) list. + +@@ -301,10 +301,10 @@ TParameters = class(TCastleStringList) + in some weird situations. + + @groupBegin } +- procedure Parse(Options: POption_Array; OptionsCount: Integer; ++ procedure Parse(AOptions: POption_Array; OptionsCount: Integer; + OptionProc: TOptionProc; OptionProcData: Pointer; + ParseOnlyKnownLongOptions: boolean = false); overload; +- procedure Parse(const Options: array of TOption; ++ procedure Parse(const AOptions: array of TOption; + OptionProc: TOptionProc; OptionProcData: Pointer; + ParseOnlyKnownLongOptions: boolean = false); overload; + { @groupEnd } +@@ -403,10 +403,10 @@ function TParameters.IsPresent(const A: array of string): boolean; + Result := false; + end; + +-procedure TParameters.Parse(const Options: array of TOption; OptionProc: TOptionProc; ++procedure TParameters.Parse(const AOptions: array of TOption; OptionProc: TOptionProc; + OptionProcData: Pointer; ParseOnlyKnownLongOptions: boolean); + begin +- Parse(@Options, System.High(Options)+1, OptionProc, OptionProcData, ++ Parse(@AOptions, System.High(AOptions)+1, OptionProc, OptionProcData, + ParseOnlyKnownLongOptions); + end; + +@@ -451,7 +451,7 @@ procedure SplitLongParameter(const s: string; out ParamLong: string; + end; + + procedure TParameters.Parse( +- Options: POption_Array; OptionsCount: Integer; OptionProc: TOptionProc; ++ AOptions: POption_Array; OptionsCount: Integer; OptionProc: TOptionProc; + OptionProcData: Pointer; ParseOnlyKnownLongOptions: boolean); + + function ParseLongParameter(const s: string; out HasArgument: boolean; +@@ -461,7 +461,7 @@ procedure TParameters.Parse( + zero-based), wyciaga tez zapisany razem z nia parametr i zwraca + HasArgument i Argument (pamietaj ze wyciaga tylko argumenty dolaczone + do opcji przy pomocy znaku "="; nie sprawdza tez w ogole czy HasArgument +- w jakis sposob zgadza sie z Options[result].Argument.). ++ w jakis sposob zgadza sie z AOptions[result].Argument.). + + Jezeli ParseOnlyKnownLongOptions to moze zwrocic -1 aby zaznaczyc ze + ten parametr nie reprezentuje zadnej znanej opcji (chociaz ciagle +@@ -472,7 +472,7 @@ procedure TParameters.Parse( + begin + SplitLongParameter(s, ParamLong, HasArgument, Argument, 2); + for i := 0 to OptionsCount-1 do +- if Options^[i].Long = ParamLong then ++ if AOptions^[i].Long = ParamLong then + begin result := i; Exit; end; + + if ParseOnlyKnownLongOptions then +@@ -481,7 +481,7 @@ procedure TParameters.Parse( + end; + + function FindShortOption(c: char; const Parameter: string): Integer; +- { znajdz takie i ze Options[i].Short = c (i c <> #0). ++ { znajdz takie i ze AOptions[i].Short = c (i c <> #0). + Jesli sie nie uda - wyjatek EInvalidshortOption. + Parametr "Parameter" jest nam potrzebny + _tylko_ zeby skomponowac ladniejszy (wiecej mowiacy) Message wyjatku, +@@ -493,7 +493,7 @@ procedure TParameters.Parse( + raise EInvalidShortOption.CreateFmt(SInvalidShortOpt, ['#0 (null char)', Parameter]); + + for result := 0 to OptionsCount-1 do +- if Options^[result].Short = c then Exit; ++ if AOptions^[result].Short = c then Exit; + + raise EInvalidShortOption.CreateFmt(SInvalidShortOpt, [c, Parameter]); + end; +@@ -508,9 +508,9 @@ procedure TParameters.Parse( + podane razem z ostatnia opcja (czyli z opcja zwracana pod nazwa). + Te proste opcje zostaly "skombinowane" razem z ostatnia opcja w + jednym parametrze. W rezultacie nazywam je "prostymi" bo one nie moga +- miec argumentu - Options^[].Argument tych opcji moze byc tylko oaNone ++ miec argumentu - AOptions^[].Argument tych opcji moze byc tylko oaNone + lub oaOptional. Ta procedura NIE sprawdza ze to sie zgadza +- tak jak w ogole nie sprawdza zadnego Options^[].Argument, takze ++ tak jak w ogole nie sprawdza zadnego AOptions^[].Argument, takze + dla ostatniej (zwracanej pod nazwa) opcji nie sprawdza - moze wiec + zwrocic opcje oaNone z HasArgument albo oaRequired[*Separate] z + not HasArgument. +@@ -569,12 +569,12 @@ procedure TParameters.Parse( + if SCharIs(Strings[i], 2, '-') then + begin + OptionNum := ParseLongParameter(Strings[i], HasArgument, Argument); +- if OptionNum <> -1 then OptionName := '--'+Options^[OptionNum].Long; ++ if OptionNum <> -1 then OptionName := '--'+AOptions^[OptionNum].Long; + end else + if not ParseOnlyKnownLongOptions then + begin + OptionNum := ParseShortParameter(Strings[i], HasArgument, Argument, SimpleShortOptions); +- OptionName := '-'+Options^[OptionNum].Short; ++ OptionName := '-'+AOptions^[OptionNum].Short; + end; + end; + +@@ -589,9 +589,9 @@ procedure TParameters.Parse( + { najpierw zajmij sie SimpleShortOptions } + for k := 0 to SimpleShortOptions.Count-1 do + begin +- if not (Options^[SimpleShortOptions[k]].Argument in [oaNone, oaOptional]) then ++ if not (AOptions^[SimpleShortOptions[k]].Argument in [oaNone, oaOptional]) then + raise EMissingOptionArgument.Create('Missing argument for short option -'+ +- Options^[SimpleShortOptions[k]].Short +'; when combining short options only the last '+ ++ AOptions^[SimpleShortOptions[k]].Short +'; when combining short options only the last '+ + 'option can have an argument'); + OptionProc(SimpleShortOptions[k], false, '', EmptySeparateArgs, OptionProcData); + end; +@@ -605,7 +605,7 @@ procedure TParameters.Parse( + { upewnij sie ze HasArgument ma dopuszczalna wartosc. Odczytaj argumenty + podane jako osobne paranetry dla oaRequired i oaRequired?Separate. } + +- if (Options^[OptionNum].Argument = oaRequired) and (not HasArgument) then ++ if (AOptions^[OptionNum].Argument = oaRequired) and (not HasArgument) then + begin + if i > High then + raise EMissingOptionArgument.Create('Missing argument for option '+OptionName); +@@ -613,22 +613,22 @@ procedure TParameters.Parse( + Argument := Strings[i]; + Delete(i); + end else +- if (Options^[OptionNum].Argument = oaNone) and HasArgument then ++ if (AOptions^[OptionNum].Argument = oaNone) and HasArgument then + raise EExcessiveOptionArgument.Create('Excessive argument for option '+OptionName) else +- if Options^[OptionNum].Argument in OptionArgumentsRequiredSeparate then ++ if AOptions^[OptionNum].Argument in OptionArgumentsRequiredSeparate then + begin + if HasArgument then + raise EExcessiveOptionArgument.CreateFmt('Option %s requires %d arguments, '+ + 'you cannot give them using the form --option=argument, you must give '+ + 'all the arguments as separate parameters', [OptionName, +- OptionSeparateArgumentToCount(Options^[OptionNum].Argument) ]); ++ OptionSeparateArgumentToCount(AOptions^[OptionNum].Argument) ]); + +- for j := 1 to OptionSeparateArgumentToCount(Options^[OptionNum].Argument) do ++ for j := 1 to OptionSeparateArgumentToCount(AOptions^[OptionNum].Argument) do + begin + if i > High then + raise EMissingOptionArgument.CreateFmt('Not enough arguments for option %s, '+ + 'this option needs %d arguments but we have only %d', [OptionName, +- OptionSeparateArgumentToCount(Options^[OptionNum].Argument), j-1]); ++ OptionSeparateArgumentToCount(AOptions^[OptionNum].Argument), j-1]); + SeparateArgs[j] := Strings[i]; + Delete(i); + end; +diff --git a/src/base/castleutils_struct_list.inc b/src/base/castleutils_struct_list.inc +index af2e7422b..2dcf15cc3 100644 +--- a/src/base/castleutils_struct_list.inc ++++ b/src/base/castleutils_struct_list.inc +@@ -24,7 +24,7 @@ type + TStructList = class({$ifdef CASTLE_OBJFPC}specialize{$endif} TList) + public + type +- PT = ^T; ++ PtrT = ^T; + TTypeList = array [0 .. {$ifdef FPC} MaxInt div SizeOf(T) - 1 {$else} 1000 * 1000 {$endif}] of T; + PTypeList = ^TTypeList; + +@@ -70,15 +70,15 @@ type + + See the @link(List) description for a more detailed explanation and example. + @seealso List } +- function L: PT; ++ function L: PtrT; + + { Increase Count and return pointer to new item. + Comfortable and efficient way to add a new item that you want to immediately + initialize. } +- function Add: PT; overload; ++ function Add: PtrT; overload; + + { Pointer to ith item. } +- function Ptr(I: Integer): PT; ++ function Ptr(I: Integer): PtrT; + + procedure Assign(const Source: TStructList {$ifndef CASTLE_OBJFPC}{$endif}); overload; + procedure Assign(const A: array of T); overload; +@@ -101,18 +101,18 @@ begin + Result := PTypeList({$ifdef FPC} FItems {$else} inherited List {$endif}); + end; + +-function TStructList{$ifndef CASTLE_OBJFPC}{$endif}.L: PT; ++function TStructList{$ifndef CASTLE_OBJFPC}{$endif}.L: PtrT; + begin +- Result := PT({$ifdef FPC} FItems {$else} inherited List {$endif}); ++ Result := PtrT({$ifdef FPC} FItems {$else} inherited List {$endif}); + end; + +-function TStructList{$ifndef CASTLE_OBJFPC}{$endif}.Add: PT; ++function TStructList{$ifndef CASTLE_OBJFPC}{$endif}.Add: PtrT; + begin + Count := Count + 1; + Result := Addr(List^[Count - 1]); + end; + +-function TStructList{$ifndef CASTLE_OBJFPC}{$endif}.Ptr(I: Integer): PT; ++function TStructList{$ifndef CASTLE_OBJFPC}{$endif}.Ptr(I: Integer): PtrT; + begin + Result := Addr(List^[I]); + end; +diff --git a/src/x3d/x3dnodes_standard_time.inc b/src/x3d/x3dnodes_standard_time.inc +index b32e9bd2e..d6d694ee2 100644 +--- a/src/x3d/x3dnodes_standard_time.inc ++++ b/src/x3d/x3dnodes_standard_time.inc +@@ -195,12 +195,13 @@ + TAbstractTimeDependentNode = class(TAbstractChildNode, IAbstractTimeDependentNode) + strict private + FInternalTimeDependentHandler: TInternalTimeDependentHandler; +- { To satify IAbstractTimeDependentNode } +- function GetInternalTimeDependentHandler: TInternalTimeDependentHandler; + strict protected + { CycleInterval that is always > 0. } + function SafeCycleInterval: TFloatTime; + public ++ { To satify IAbstractTimeDependentNode } ++ function GetInternalTimeDependentHandler: TInternalTimeDependentHandler; ++ + procedure CreateNode; override; + destructor Destroy; override; + +diff --git a/src/x3d/x3dtime.pas b/src/x3d/x3dtime.pas +index 76d51da5d..a388fcc1e 100644 +--- a/src/x3d/x3dtime.pas ++++ b/src/x3d/x3dtime.pas +@@ -74,8 +74,7 @@ TX3DTime = record + Seconds: TFloatTime; + PlusTicks: Cardinal; + +- const +- Oldest: TX3DTime = (Seconds: OldestTime; PlusTicks: 0); ++ class function Oldest: TX3DTime; static; + + class operator {$ifdef FPC}>{$else}GreaterThan{$endif} (const Time1, Time2: TX3DTime): boolean; + class operator {$ifdef FPC}>={$else}GreaterThanOrEqual{$endif} (const Time1, Time2: TX3DTime): boolean; +@@ -95,6 +94,13 @@ TX3DTime = record + + implementation + ++class function TX3DTime.Oldest: TX3DTime; static; ++const ++ R: TX3DTime = (Seconds: OldestTime; PlusTicks: 0); ++begin ++ Result := R; ++end; ++ + class operator TX3DTime.{$ifdef FPC}>{$else}GreaterThan{$endif} (const Time1, Time2: TX3DTime): boolean; + begin + Result := (Time1.Seconds > Time2.Seconds) or +diff --git a/tools/build-tool/code/toolproject.pas b/tools/build-tool/code/toolproject.pas +index b6a8e19d1..703770039 100644 +--- a/tools/build-tool/code/toolproject.pas ++++ b/tools/build-tool/code/toolproject.pas +@@ -321,7 +321,7 @@ constructor TCastleProject.Create(const APath: string); + (QualifiedName[Length(QualifiedName)] = '.')) then + raise Exception.CreateFmt('%s (in CastleEngineManifest.xml) cannot start or end with a dot: "%s"', [OptionName, QualifiedName]); + +- Components := SplitString(QualifiedName, '.'); ++ Components := CastleStringUtils.SplitString(QualifiedName, '.'); + try + for I := 0 to Components.Count - 1 do + begin +@@ -1662,7 +1662,7 @@ function TCastleProject.ReplaceMacros(const Source: string): string; + PreviousMacros: array of TStringStringMap.TDictionaryPair; + begin + { calculate version as 4 numbers, Windows resource/manifest stuff expect this } +- VersionComponentsString := SplitString(Version, '.'); ++ VersionComponentsString := CastleStringUtils.SplitString(Version, '.'); + try + for I := 0 to High(VersionComponents) do + if I < VersionComponentsString.Count then +diff --git a/fpmake.pp b/fpmake.pp +index b556623..c4caad2 100644 +--- a/fpmake.pp ++++ b/fpmake.pp +@@ -17,7 +17,7 @@ program fpmake; + + uses + { It seems that FPC 3.1.1 requires thread support for FpMkUnit. } +- {$ifdef VER3_1} CThreads, {$endif} ++ {$IF (FPC_FULLVERSION >= 030100)} CThreads, {$endif} + SysUtils, fpmkunit; + + var diff -Nru castle-game-engine-6.4+dfsg1/debian/patches/Fix-test-output-when-compiled-with-FPC-3.2.0.patch castle-game-engine-6.4+dfsg1/debian/patches/Fix-test-output-when-compiled-with-FPC-3.2.0.patch --- castle-game-engine-6.4+dfsg1/debian/patches/Fix-test-output-when-compiled-with-FPC-3.2.0.patch 1970-01-01 00:00:00.000000000 +0000 +++ castle-game-engine-6.4+dfsg1/debian/patches/Fix-test-output-when-compiled-with-FPC-3.2.0.patch 2020-08-10 15:22:30.000000000 +0000 @@ -0,0 +1,106 @@ +From 3c33e42733c5c8290a1890b4674f995f3290e851 Mon Sep 17 00:00:00 2001 +From: Michalis Kamburelis +Date: Sun, 21 Jun 2020 16:44:36 +0200 +Subject: [PATCH] Fix test output when compiled with FPC 3.2.0 + +--- + src/base/castlestringutils.pas | 11 ++++++++ + tests/testsysutils.pas | 48 +++++++++++++++++++++++++--------- + 2 files changed, 47 insertions(+), 12 deletions(-) + +diff --git a/src/base/castlestringutils.pas b/src/base/castlestringutils.pas +index 2a8502462..3d948bc1e 100644 +--- a/src/base/castlestringutils.pas ++++ b/src/base/castlestringutils.pas +@@ -2174,8 +2174,13 @@ function FormatNameCounter(const NamePattern: string; + var + R: {$ifdef FPC} TRegExpr {$else} TRegEx {$endif}; + C: TRegExprCounter; ++ {$ifndef FPC} ++ P : TMatchEvaluator; ++ {$endif} + begin + {$ifdef FPC} ++ if NamePattern = '' then ++ Exit(''); // avoid error TRegExpr exec: empty input string + R := TRegExpr.Create; + R.Expression := '@counter\(([\d]+)\)'; + {$else} +@@ -2185,7 +2190,13 @@ function FormatNameCounter(const NamePattern: string; + C := TRegExprCounter.Create; + try + C.Index := Index; ++ {$ifdef FPC} + Result := R.Replace(NamePattern, {$ifdef CASTLE_OBJFPC}@{$endif} C.ReplaceCallback); ++ {$else} ++ // Fix for delphi < Tokio, needs an extra Variable for the call ++ P := C.ReplaceCallback; ++ Result := r.Replace(NamePattern, P); ++ {$endif} + ReplacementsDone := C.ReplacementsDone; + finally FreeAndNil(C) end; + finally FreeAndNil(R) end; +diff --git a/tests/testsysutils.pas b/tests/testsysutils.pas +index 7c2c5a3ac..1be549051 100644 +--- a/tests/testsysutils.pas ++++ b/tests/testsysutils.pas +@@ -31,23 +31,47 @@ implementation + + procedure TTestSysUtils.TestDirectoryFileExists; + begin +- { window/gtk/castlewindow_gtk.inc uses FileExists and DirectoryExists +- to detect file/dir } ++ { Before FPC 3.2.0: + +- { FileExists doesn't differ dirs and non-dirs... On non-Windows. +- On Windows, it does, unfortunately +- (although I would like to see it consistent one day...). ++ FPC FileExists on Unix answers true for both regular files and directories. ++ Unlike FPC FileExists on Windows, that answers true only for regular files. + See http://www.freepascal.org/docs-html/rtl/sysutils/fileexists.html +- http://free-pascal-general.1045716.n5.nabble.com/FileExists-inconsistency-td2813433.html } ++ http://free-pascal-general.1045716.n5.nabble.com/FileExists-inconsistency-td2813433.html ++ ++ IMHO that's quite bad. ++ - It's inconsistent across two platforms. ++ - And Unix behavior is unexpected. ++ ++ FPC docs for FileExists say that this is deliberate on Unix, ++ because "on Unix files are directories". ++ But this seems like an after-thought explanation of a broken behavior ++ in FPC docs. ++ Indeed on Unix many things are "some kind of files" ++ (including directories, sockets, pipes) when looking at C API and kernel API, ++ but that's an internal detail for most people. ++ In normal conversations, in normal API descriptions, ++ when someone talks about "files", it's natural ++ (also to Unix users and developers) to understand ++ that you mean "regular files; not directories, network sockets, pipes...". ++ ++ It was fixed in ++ https://github.com/graemeg/freepascal/commit/6fbfe3fc4c1dc23908b14a68fe54ae04d53ded73 , ++ thankfully. ++ } + {$ifdef MSWINDOWS} +- AssertFalse(FileExists(URIToFilenameSafe(ApplicationData('')))); +- AssertFalse(FileExists(URIToFilenameSafe(ApplicationData('images/')))); ++ AssertFalse(FileExists(URIToFilenameSafe('castle-data:/'))); ++ AssertFalse(FileExists(URIToFilenameSafe('castle-data:/images/'))); + {$else} +- AssertTrue(FileExists(URIToFilenameSafe(ApplicationData('')))); +- AssertTrue(FileExists(URIToFilenameSafe(ApplicationData('images/')))); ++ {$if not defined(VER3_3)} // For FPC 3.3.1, the behaviour depends on exact revision... ++ {$if defined(VER3_0) or defined(VER3_1)} ++ AssertTrue(FileExists(URIToFilenameSafe('castle-data:/'))); ++ AssertTrue(FileExists(URIToFilenameSafe('castle-data:/images/'))); ++ {$else} ++ AssertFalse(FileExists(URIToFilenameSafe('castle-data:/'))); ++ AssertFalse(FileExists(URIToFilenameSafe('castle-data:/images/'))); ++ {$endif} ++ {$endif} + {$endif} +- AssertTrue(FileExists(URIToFilenameSafe(ApplicationData('test.xml')))); +- AssertTrue(not FileExists(URIToFilenameSafe(ApplicationData('test-not-existing.xml')))); + + { DirectoryExists differs dirs and non-dirs } + AssertTrue(DirectoryExists(URIToFilenameSafe(ApplicationData('')))); diff -Nru castle-game-engine-6.4+dfsg1/debian/patches/Fix-TGLSLUniform-compilation-with-FPC-3.2.0.patch castle-game-engine-6.4+dfsg1/debian/patches/Fix-TGLSLUniform-compilation-with-FPC-3.2.0.patch --- castle-game-engine-6.4+dfsg1/debian/patches/Fix-TGLSLUniform-compilation-with-FPC-3.2.0.patch 1970-01-01 00:00:00.000000000 +0000 +++ castle-game-engine-6.4+dfsg1/debian/patches/Fix-TGLSLUniform-compilation-with-FPC-3.2.0.patch 2020-08-10 15:22:30.000000000 +0000 @@ -0,0 +1,39 @@ +From da11c1909dd51db9e4e76c543034068df9e83416 Mon Sep 17 00:00:00 2001 +From: Michalis Kamburelis +Date: Sun, 21 Jun 2020 16:39:47 +0200 +Subject: [PATCH] Fix TGLSLUniform compilation with FPC 3.2.0 + +--- + src/images/opengl/castleglshaders.pas | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/images/opengl/castleglshaders.pas b/src/images/opengl/castleglshaders.pas +index c70c70080..a2046473c 100644 +--- a/src/images/opengl/castleglshaders.pas ++++ b/src/images/opengl/castleglshaders.pas +@@ -95,9 +95,8 @@ TGLSLUniform = record + Name: string; + Location: TGLint; + +- const +- { Calling @link(TGLSLUniform.SetValue) of this is ignored. } +- NotExisting: TGLSLUniform = (Owner: nil; Name: ''; Location: -1); ++ { Calling @link(TGLSLUniform.SetValue) of this is ignored. } ++ class function NotExisting: TGLSLUniform; static; + + { Set uniform variable value. + You should get the uniform information first using the +@@ -684,6 +683,13 @@ procedure TGLSLUniform.SetValueEnd(const ForceException: boolean); + end; + end; + ++class function TGLSLUniform.NotExisting: TGLSLUniform; static; ++const ++ R: TGLSLUniform = (Owner: nil; Name: ''; Location: -1); ++begin ++ Result := R; ++end; ++ + procedure TGLSLUniform.SetValue(const Value: boolean; const ForceException: boolean); + begin + if Location = -1 then Exit; // ignore non-existing uniform here diff -Nru castle-game-engine-6.4+dfsg1/debian/patches/series castle-game-engine-6.4+dfsg1/debian/patches/series --- castle-game-engine-6.4+dfsg1/debian/patches/series 2020-05-03 19:33:08.000000000 +0000 +++ castle-game-engine-6.4+dfsg1/debian/patches/series 2020-08-10 15:22:30.000000000 +0000 @@ -3,3 +3,6 @@ add_debug_info_for_powerpc.patch dont-add-website-header-and-footer-to-doc.patch inkscape-dropped--export-png.patch +Fix-compilation-with-FPC-3.2.0.patch +Fix-TGLSLUniform-compilation-with-FPC-3.2.0.patch +Fix-test-output-when-compiled-with-FPC-3.2.0.patch diff -Nru castle-game-engine-6.4+dfsg1/debian/upstream/metadata castle-game-engine-6.4+dfsg1/debian/upstream/metadata --- castle-game-engine-6.4+dfsg1/debian/upstream/metadata 1970-01-01 00:00:00.000000000 +0000 +++ castle-game-engine-6.4+dfsg1/debian/upstream/metadata 2020-08-03 14:38:58.000000000 +0000 @@ -0,0 +1,5 @@ +--- +Bug-Database: https://github.com/castle-engine/castle-engine/issues +Bug-Submit: https://github.com/castle-engine/castle-engine/issues/new +Repository: https://github.com/castle-engine/castle-engine.git +Repository-Browse: https://github.com/castle-engine/castle-engine