hedgewars/uRender.pas
branchui-scaling
changeset 15283 c4fd2813b127
parent 15184 e7d7fe9f20e1
child 15359 c117e17b90bc
child 15361 5c0479d0ed5b
--- a/hedgewars/uRender.pas	Wed May 16 18:22:28 2018 +0200
+++ b/hedgewars/uRender.pas	Wed Jul 31 23:14:27 2019 +0200
@@ -34,6 +34,7 @@
 procedure DrawSpriteClipped     (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
 procedure DrawSpriteRotated     (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
 procedure DrawSpriteRotatedF    (Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
+procedure DrawSpriteRotatedFReal(Sprite: TSprite; X, Y: Real; Frame, Dir: LongInt; Angle: real);
 procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real);
 
 procedure DrawTexture           (X, Y: LongInt; Texture: PTexture); inline;
@@ -53,6 +54,8 @@
 
 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
+procedure DrawLineWrapped       (X0, Y0, X1, Y1, Width: Single; goesLeft: boolean; Wraps: LongWord; color: LongWord); inline;
+procedure DrawLineWrapped       (X0, Y0, X1, Y1, Width: Single; goesLeft: boolean; Wraps: LongWord; r, g, b, a: Byte);
 procedure DrawLineOnScreen      (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
 procedure DrawRect              (rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean);
 procedure DrawHedgehog          (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
@@ -65,7 +68,7 @@
 procedure RenderClear           (mode: TRenderMode);
 {$ENDIF}
 procedure RenderSetClearColor   (r, g, b, a: real);
-procedure Tint                  (r, g, b, a: Byte); inline;
+procedure Tint                  (r, g, b, a: Byte);
 procedure Tint                  (c: Longword); inline;
 procedure untint(); inline;
 procedure setTintAdd            (enable: boolean); inline;
@@ -527,7 +530,10 @@
 
 {$IFNDEF PAS2C}
     if not Load_GL_VERSION_2_0 then
-        halt;
+        begin
+        WriteLnToConsole('Load_GL_VERSION_2_0 returned false!');
+        halt(HaltStartupError);
+        end;
 {$ENDIF}
 
     shaderWater:= CompileProgram('water');
@@ -718,7 +724,7 @@
 end;
 
 procedure openglRotatef(RotX, RotY, RotZ: GLfloat; dir: LongInt); inline;
-{ workaround for pascal bug http://bugs.freepascal.org/view.php?id=27222 }
+{ workaround for pascal bug https://bugs.freepascal.org/view.php?id=27222 }
 var tmpdir: LongInt;
 begin
 tmpdir:=dir;
@@ -1147,7 +1153,7 @@
 
 if Angle <> 0  then
     begin
-    // Check the bounding circle 
+    // Check the bounding circle
     if isCircleOffscreen(X, Y, (sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) div 4) then
         exit;
     end
@@ -1181,6 +1187,45 @@
 
 end;
 
+procedure DrawSpriteRotatedFReal(Sprite: TSprite; X, Y: Real; Frame, Dir: LongInt; Angle: real);
+begin
+
+    if Angle <> 0  then
+    begin
+        // Check the bounding circle
+        if isCircleOffscreen(round(X), round(Y), (sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) div 4) then
+            exit;
+    end
+    else
+    begin
+        if isDxAreaOffscreen(round(X) - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then
+            exit;
+        if isDYAreaOffscreen(round(Y) - SpritesData[Sprite].Height div 2 , SpritesData[Sprite].Height) <> 0 then
+            exit;
+    end;
+
+
+    openglPushMatrix;
+    openglTranslatef(X, Y, 0);
+
+// mirror
+    if Dir < 0 then
+        openglScalef(-1.0, 1.0, 1.0);
+
+// apply angle after (conditional) mirroring
+    if Angle <> 0  then
+        openglRotatef(Angle, 0, 0, 1);
+
+    UpdateModelviewProjection;
+
+    DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
+
+    openglPopMatrix;
+
+    UpdateModelviewProjection;
+
+end;
+
 procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real);
 begin
 if Angle <> 0  then
@@ -1213,6 +1258,8 @@
     openglTranslatef(-PivotX, -PivotY, 0);
     end;
 
+UpdateModelviewProjection;
+
 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
 
 openglPopMatrix;
@@ -1334,11 +1381,17 @@
         end;
 end;
 
+// Same as below, but with color as LongWord
 procedure DrawLine(X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
 begin
 DrawLine(X0, Y0, X1, Y1, Width, (color shr 24) and $FF, (color shr 16) and $FF, (color shr 8) and $FF, color and $FF)
 end;
 
+// Draw line between 2 points
+// X0, Y0: Start point
+// X0, Y1: End point
+// Width: Visual line width
+// r, g, b, a: Color
 procedure DrawLine(X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
 begin
     openglPushMatrix();
@@ -1353,6 +1406,106 @@
     UpdateModelviewProjection;
 end;
 
+// Same as below, but with color as a longword
+procedure DrawLineWrapped(X0, Y0, X1, Y1, Width: Single; goesLeft: boolean; Wraps: LongWord; color: LongWord); inline;
+begin
+DrawLineWrapped(X0, Y0, X1, Y1, Width, goesLeft, Wraps, (color shr 24) and $FF, (color shr 16) and $FF, (color shr 8) and $FF, color and $FF);
+end;
+
+// Draw a line between 2 points, but it wraps around the
+// world edge for a given number of times.
+// goesLeft: true if the line direction from the start point is left
+// Wraps: Number of times the line intersects the wrapping world edge
+// r, g, b, a: color
+procedure DrawLineWrapped(X0, Y0, X1, Y1, Width: Single; goesLeft: boolean; Wraps: LongWord; r, g, b, a: Byte);
+var w: LongWord;
+    startX, startY, endX, endY: Single;
+    // total X and Y distance the line travels if you would unwrap it
+    // with this we know the slope of the line.
+    totalX, totalY: Single;
+    // x variable for the line formula
+    x: Single;
+begin
+    openglPushMatrix();
+    openglTranslatef(WorldDx, WorldDy, 0);
+
+    UpdateModelviewProjection;
+
+    startX:= X0;
+    startY:= Y0;
+    if (Wraps = 0) then
+        begin
+        // Wraps=0 is trivial: Just draw one direct connection
+        endX:= X1;
+        endY:= Y1;
+        DrawLineOnScreen(startX, startY, endX, endY, Width, r, g, b, a);
+        end
+    else
+        begin
+        // A wrapping line is drawn using multiple line segments
+        // which stop at the left and right border. We
+        // calculate the points at which the line intersects with the border.
+        // Then we draws all line segments.
+
+        // Calculate position of first wrap point
+        if goesLeft then
+            begin
+            endX:= LeftX;
+            totalX:= (RightX - X1) + (X0 - LeftX);
+            x:= X0 - LeftX;
+            end
+        else
+            begin
+            endX:= RightX;
+            totalX:= (RightX - X0) + (X1 - LeftX);
+            x:= RightX - X0;
+            end;
+        if (Wraps >= 2) then
+            totalX:= totalX + ((RightX - LeftX) * (Wraps-1));
+        totalY:= Y1 - Y0;
+        // Calculate Y of first wrap point using the line formula
+        endY:= Y0 + (totalY / totalX) * x;
+        // Draw line segment between starting point and first wrap point
+        DrawLineOnScreen(startX, startY, endX, endY, Width, r, g, b, a);
+
+        // Calculate and draw all remaining line segments
+        for w:=1 to Wraps do
+            begin
+            startY:= endY;
+            if goesLeft then
+                begin
+                startX:= RightX;
+                if w < Wraps then
+                    endX:= LeftX
+                else
+                    endX:= X1;
+                end
+            else
+                begin
+                startX:= LeftX;
+                if w < Wraps then
+                    endX:= RightX
+                else
+                    endX:= X1;
+                end;
+            if w < Wraps then
+                begin
+                x:= x + (RightX - LeftX);
+                endY:= Y0 + (totalY / totalX) * x;
+                end
+            else
+                endY:= Y1;
+
+            DrawLineOnScreen(startX, startY, endX, endY, Width, r, g, b, a);
+            end;
+
+        end;
+
+    openglPopMatrix();
+
+    UpdateModelviewProjection;
+end;
+
 procedure DrawLineOnScreen(X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
 begin
     glEnable(GL_LINE_SMOOTH);
@@ -1734,8 +1887,8 @@
 else
     PrepareVbForWater(true,
         OffsetY + WorldDy + cWaterLine, ViewTopY,
-        LongInt(LeftX)  + WorldDx - OffsetX, ViewLeftX,
-        LongInt(RightX) + WorldDx + OffsetX, ViewRightX,
+        leftX  + WorldDx - OffsetX, ViewLeftX,
+        rightX + WorldDx + OffsetX, ViewRightX,
         ViewBottomY,
         first, count);
 
@@ -1825,8 +1978,8 @@
 dY:= -cWaveHeight + dy;
 ox:= -cWaveHeight + ox;
 
-lx:= LongInt(LeftX)  + WorldDx - ox;
-rx:= LongInt(RightX) + WorldDx + ox;
+lx:= leftX  + WorldDx - ox;
+rx:= rightX + WorldDx + ox;
 
 topy:= cWaterLine + WorldDy + dY;
 
@@ -1933,7 +2086,7 @@
     {$ENDIF}
 end;
 
-procedure Tint(r, g, b, a: Byte); inline;
+procedure Tint(r, g, b, a: Byte);
 var
     nc, tw: Longword;
 begin