Add projects including README.md(s), .gitignore(s) and the actual project files.

Signed-off-by: Michael Fabian Dirks <michael.dirks@project-kube.de>
This commit is contained in:
Michael Fabian Dirks
2014-11-24 18:18:24 +01:00
parent 934da62076
commit 8f3114e377
170 changed files with 22028 additions and 3 deletions
View File
+8
View File
@@ -0,0 +1,8 @@
# Source Backup Files
*.bb_bak2
*.bb_bak1
# Binary Files
*.exe
*.o
*.a
@@ -0,0 +1,23 @@
Global sTestTxt$
sTestTxt$ = sTestTxt$ + "|fFF0000H|fFF7E00a|fFFFF00l|f7EFF00l|f00FF00o |f00FF7EW|f00FFFFe|f007EFFl|f0000FFt|f7E00FF!|fFF00FF!|fFF007E!"+Chr(10)
sTestTxt$ = sTestTxt$ + Chr(10)
sTestTxt$ = sTestTxt$ + "|fFFFFFFDies ist ein Text der |fFF0000Rot |f00FF00Grün |fFFFFFFund |f0000FFBlau |fFFFFFFist." + Chr(10)
sTestTxt$ = sTestTxt$ + "|f33FF33Man kann alle mögli|f0000FFchen Farben machen!" + Chr(10)
sTestTxt$ = sTestTxt$ + "|f000000|bFF0000Sogar|b-1-1-1 |bFF7E00der|b-1-1-1 |bFFFF00Hinter|b7EFF00grund|b-1-1-1 |b00FF00kann|b-1-1-1 |b00FF7Egesetzt|b-1-1-1 |b00FFFFwerden|b-1-1-1!" + Chr(10)
sTestTxt$ = sTestTxt$ + "|fAAAAFF|b-1-1-1Dies kann für mehr|f444400|bAAAAFFzeilige Selektion|fAAAAFF|b-1-1-1 verwendet werden!" + Chr(10)
sTestTxt$ = sTestTxt$ + "|fFFFFFFD|fFF7E00amit wäre der |b7E7E7E|fFFFFFFB|fFF7E00eispieltext|b-1-1-1 beendet|fFFFFFF!"
Graphics 400,300,32,2
SetBuffer BackBuffer()
Global timer = CreateTimer(30)
While Not KeyHit(1)
Cls
AdvText(200,150, sTestTxt, MouseX()/200.0, MouseY()/150.0, 1)
Flip 0
WaitTimer timer
Wend
Include "AdvText.bb"
+193
View File
@@ -0,0 +1,193 @@
;AdvText Function
Dim SplittedString$(0)
Dim sTextLines$(0,1)
Global SplitCount, AdvText_X, AdvText_Y, AdvText_Width, AdvText_Height
Function AdvText(iX, iY, sText$, iCenterX#=0, iCenterY#=0, fLineSpace#=1)
Local iTextLines = 1, iLine = 0
AdvText_X = 0:AdvText_Y = 0:AdvText_Width = 0:AdvText_Height = 0
SplitString(sText, Chr(10))
iTextLines = SplitCount-1
Dim sTextLines$(iTextLines,1)
For iLine = 0 To iTextLines
sTextLines(iLine, 0) = SplittedString$(iLine)
Next
;Parse the Text so that we get only the visible text into the second slot.
Local iLastClr = 1, tabLength = 0
For iLine = 0 To iTextLines
iLastClr = 1
For iPos = 1 To Len(sTextLines(iLine,0))
sChar$ = Mid(sTextLines(iLine,0), iPos, 1)
If sChar = "|" And (Mid(sTextLines(iLine,0), iPos+1, 1) = "f" Or Mid(sTextLines(iLine,0), iPos+1, 1) = "b")
sTextLines(iLine,1) = sTextLines(iLine,1) + Mid(sTextLines(iLine,0),iLastClr,iPos-iLastClr)
iLastClr = iPos+8
ElseIf sChar = Chr(9)
sTextLines(iLine,1) = sTextLines(iLine,1) + Mid(sTextLines(iLine,0),iLastClr,iPos-iLastClr)
iLastClr = iPos
;Remove Tab Character
sTextLines(iLine,0) = Left(sTextLines(iLine,0), iPos-1) + Right(sTextLines(iLine,0), Len(sTextLines(iLine,0))-iPos)
tabLength = (4-(Len(sTextLines(iLine,1)) Mod 4))
For iTabSpace = 1 To tabLength
sTextLines(iLine,0) = Left(sTextLines(iLine,0), iPos-1) + " " + Right(sTextLines(iLine,0), Len(sTextLines(iLine,0))-iPos+1)
Next
ElseIf sChar = Chr(11)
sTextLines(iLine,1) = sTextLines(iLine,1) + Mid(sTextLines(iLine,0),iLastClr,iPos-iLastClr)
iLastClr = iPos
;Remove Tab Character
sTextLines(iLine,0) = Left(sTextLines(iLine,0), iPos-1) + Right(sTextLines(iLine,0), Len(sTextLines(iLine,0))-iPos)
tabLength = (8-(Len(sTextLines(iLine,1)) Mod 8))
For iTabSpace = 1 To tabLength
sTextLines(iLine,0) = Left(sTextLines(iLine,0), iPos-1) + " " + Right(sTextLines(iLine,0), Len(sTextLines(iLine,0))-iPos+1)
Next
ElseIf iPos = Len(sTextLines(iLine,0))
sTextLines(iLine,1) = sTextLines(iLine,1) + Mid(sTextLines(iLine,0),iLastClr,iPos-iLastClr+1)
EndIf
Next
; Return width.
If (AdvText_Width < StringWidth(sTextLines(iLine,1))) Then AdvText_Width = StringWidth(sTextLines(iLine,1))
Next
; Return Height
If (AdvText_Height < (FontHeight()*(iTextLines+1)*fLineSpace)) Then AdvText_Height = (FontHeight()*(iTextLines+1)*fLineSpace)
;Real Text Processing
Local iRedO = ColorRed(), iGreenO = ColorGreen(), iBlueO = ColorBlue() ; Original Foreground Color
Local iRed = ColorRed(), iGreen = ColorGreen(), iBlue = ColorBlue() ;Foreground
Local iBGRed = -1, iBGGreen = -1, iBGBlue = -1 ;Background
Local icX, icY, icsX, scText$, iRealPos
For iLine = 0 To iTextLines
sText$ = sTextLines(iLine,0)
icsX = -(StringWidth(sTextLines(iLine,1))*0.5)*iCenterX
icX = icsX
icY = ( -(FontHeight()*(iTextLines+1)*0.5*fLineSpace*iCenterY) + (iLine * FontHeight() * fLineSpace) )
; Return X and Y starting point.
If (AdvText_X > iX + icX) Then AdvText_X = iX + icX
If (AdvText_Y > iY + icY) Then AdvText_Y = iY + icY
iRealPos = 1
For iPos = 1 To Len(sText)
sChar$ = Mid(sText, iPos, 1)
If sChar = "|" And Mid(sText, iPos+1, 1) = "f" ;Foreground Change
If iBGRed > -1 And iBGGreen > -1 And iBGBlue > -1
Color iBGRed, iBGGreen, iBGBlue
Rect iX+icX, iY+icY, StringWidth(scText), FontHeight()*fLineSpace
EndIf
Color iRed, iGreen, iBlue
Text iX+icX, iY+icY, scText$
icX = icX + StringWidth(scText$)
scText = ""
If Mid(sText, iPos+2, 2) = "-1"
iRed = iRedO
iGreen = iGreenO
iBlue = iBlueO
Else
iRed = HexB(Mid(sText, iPos+2, 2))
iGreen = HexB(Mid(sText, iPos+4, 2))
iBlue = HexB(Mid(sText, iPos+6, 2))
EndIf
sText = Left(sText, iPos)+Mid(sText, iPos+8)
ElseIf sChar = "|" And Mid(sText, iPos+1, 1) = "b" ;Background Change
If iBGRed > -1 And iBGGreen > -1 And iBGBlue > -1
Color iBGRed, iBGGreen, iBGBlue
Rect iX+icX, iY+icY, StringWidth(scText), FontHeight()*fLineSpace
EndIf
Color iRed, iGreen, iBlue
Text iX+icX, iY+icY, scText$
icX = icX + StringWidth(scText$)
scText = ""
If Mid(sText, iPos+2, 2) = "-1"
iBGRed = -1
iBGGreen = -1
iBGBlue = -1
Else
iBGRed = HexB(Mid(sText, iPos+2, 2))
iBGGreen = HexB(Mid(sText, iPos+4, 2))
iBGBlue = HexB(Mid(sText, iPos+6, 2))
EndIf
sText = Left(sText, iPos)+Mid(sText, iPos+8)
Else
scText$ = scText$ + sChar$
iRealPos = iRealPos + 1
EndIf
If iPos = Len(sText)
If iBGRed > -1 And iBGGreen > -1 And iBGBlue > -1
Color iBGRed, iBGGreen, iBGBlue
Rect iX+icX, iY+icY, StringWidth(scText), FontHeight()*fLineSpace
EndIf
Color iRed, iGreen, iBlue
Text iX+icX, iY+icY, scText
scText = ""
EndIf
Next
scText$ = ""
Next
End Function
Function HexB#(Hexzahl$)
Local Integer_Result#
If Left$(Hexzahl$,1)="$" Then Hexzahl$=Mid$(Hexzahl$,2)
For i=1 To Len(Hexzahl$)
tmp1$=Upper$(Mid$(Hexzahl$,i,1)):tmp2=tmp1$
If tmp2=0 And tmp1$<>"0" Then tmp2=Asc(tmp1$)-55
Integer_Result=Integer_Result*16:Integer_Result=Integer_Result+tmp2
Next
Return Integer_Result
End Function
Function SplitString(In$, StringSplitter$ = "|")
Local InLength% = Len(In)
Local SplitLength% = Len(StringSplitter)
Local CountPos%, InPos%, SplitIndex%
Local SplitTest$, LineText$
; Count how many Lines there are and resize Dim.
SplitCount = 0
For CountPos = 1 To InLength-(SplitLength-1)
SplitTest = Mid(In,CountPos,1)
If SplitTest = StringSplitter Then SplitCount = SplitCount + 1
Next
Dim SplittedString(SplitCount)
; Split the Text onto multiple lines.
While Not InPos = Len(In)
; Increment Position
InPos = InPos + 1
; Grab a piece of the text.
SplitTest = Mid(In, InPos, SplitLength)
Local Char$ = Left(SplitTest, 1)
; Check if the current Text matches the splitter or if we are near the end.
If SplitTest = StringSplitter Or InPos = InLength
; Append the current character if it doesn't match the Splitter.
If InPos = InLength And SplitTest <> StringSplitter Then LineText = LineText + Char
; Store the Line.
SplittedString(SplitIndex) = LineText
; Increment split index.
SplitIndex = SplitIndex + 1
; Reset LineText
LineText = ""
Else
LineText = LineText + Char
EndIf
Wend
End Function
;~IDEal Editor Parameters:
;~C#Blitz3D
+8
View File
@@ -0,0 +1,8 @@
Advanced Text
=======================
This project adds an advanced text function to BlitzBasic. While somewhat slower, it supports many features and if you cache the result you can get quite good results. It was written for a project that needed such features in the chat, but has been abandoned.
License
=======
Advanced Text by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
@@ -0,0 +1,258 @@
;----------------------------------------------------------------
;-- Types
;----------------------------------------------------------------
Type TList
Field FirstEntry.TListEntry
Field LastEntry.TListEntry
Field Iterator.TListEntry
End Type
Type TListEntry
Field Value%
Field PreviousEntry.TListEntry
Field NextEntry.TListEntry
End Type
;----------------------------------------------------------------
;-- Functions
;----------------------------------------------------------------
Function TList_Create.TList()
Local lList.TList = New TList
lList\FirstEntry = Null
lList\LastEntry = Null
lList\Iterator = Null
Return lList
End Function
Function TList_Destroy(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to destroy non-existing list."
; Delete all entries
pList\Iterator = pList\FirstEntry
While pList\Iterator <> Null
Local lNextEntry.TListEntry = pList\Iterator\NextEntry
Delete pList\Iterator
pList\Iterator = lNextEntry
Wend
End Function
Function TList_Reset(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to reset non-existing list."
pList\Iterator = Null
End Function
Function TList_First%(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
pList\Iterator = pList\FirstEntry
If pList\Iterator <> Null Then Return pList\Iterator\Value
End Function
Function TList_Last%(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
pList\Iterator = pList\LastEntry
If pList\Iterator <> Null Then Return pList\Iterator\Value
End Function
Function TList_Next%(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
If pList\Iterator <> Null Then
pList\Iterator = pList\Iterator\NextEntry
Else
pList\Iterator = pList\FirstEntry
EndIf
If pList\Iterator <> Null Then Return pList\Iterator\Value
End Function
Function TList_Previous%(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
If pList\Iterator <> Null Then
pList\Iterator = pList\Iterator\PreviousEntry
Else
pList\Iterator = pList\LastEntry
EndIf
If pList\Iterator <> Null Then Return pList\Iterator\Value
End Function
Function TList_HasFirst(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
Return (pList\FirstEntry <> Null)
End Function
Function TList_HasLast(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
Return (pList\LastEntry <> Null)
End Function
Function TList_HasNext(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
If pList\Iterator <> Null Then
Return (pList\Iterator\NextEntry <> Null)
Else
Return (pList\FirstEntry <> Null)
EndIf
End Function
Function TList_HasPrevious(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
If pList\Iterator <> Null Then
Return (pList\Iterator\PreviousEntry <> Null)
Else
Return (pList\LastEntry <> Null)
EndIf
End Function
Function TList_AddFirst(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
Local lEntry.TListEntry = New TListEntry
lEntry\Value = Value
If pList\FirstEntry <> Null Then
lEntry\NextEntry = pList\FirstEntry
lEntry\NextEntry\PreviousEntry = lEntry
EndIf
pList\FirstEntry = lEntry
If pList\LastEntry = Null Then pList\LastEntry = lEntry
End Function
Function TList_AddLast(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
Local lEntry.TListEntry = New TListEntry
lEntry\Value = Value
If pList\LastEntry <> Null Then
lEntry\PreviousEntry = pList\LastEntry
lEntry\PreviousEntry\NextEntry = lEntry
EndIf
If pList\FirstEntry = Null pList\FirstEntry = lEntry
pList\LastEntry = lEntry
End Function
Function TList_InsertBefore(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
Local lEntry.TListEntry = New TListEntry
lEntry\Value = Value
If pList\Iterator\PreviousEntry <> Null Then
lEntry\PreviousEntry = pList\Iterator\PreviousEntry
pList\Iterator\PreviousEntry\NextEntry = lEntry
Else
pList\FirstEntry = lEntry
EndIf
pList\Iterator\PreviousEntry = lEntry
If pList\Iterator\NextEntry = Null Then
pList\LastEntry = lEntry
EndIf
lEntry\NextEntry = pList\Iterator
End Function
Function TList_InsertAfter(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
Local lEntry.TListEntry = New TListEntry
lEntry\Value = Value
If pList\Iterator\NextEntry <> Null Then
lEntry\NextEntry = pList\Iterator\NextEntry
pList\Iterator\NextEntry\PreviousEntry = lEntry
Else
pList\LastEntry = lEntry
EndIf
pList\Iterator\NextEntry = lEntry
If pList\Iterator\PreviousEntry = Null Then
pList\FirstEntry = lEntry
EndIf
lEntry\PreviousEntry = pList\Iterator
End Function
Function TList_Replace(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
pList\Iterator\Value = Value
End Function
Function TList_DeleteFirst(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\FirstEntry = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
Local lEntry.TListEntry = pList\FirstEntry
pList\FirstEntry\NextEntry\PreviousEntry = Null
pList\FirstEntry = pList\FirstEntry\NextEntry
Delete lEntry
If pList\FirstEntry <> Null Then Return pList\FirstEntry\Value
End Function
Function TList_DeleteLast(pList.Tlist)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\LastEntry = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
Local lEntry.TListEntry = pList\LastEntry
pList\LastEntry\PreviousEntry\NextEntry = Null
pList\LastEntry = pList\LastEntry\PreviousEntry
Delete lEntry
If pList\LastEntry <> Null Then Return pList\LastEntry\Value
End Function
Function TList_Delete(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
If pList\FirstEntry = pList\Iterator Then pList\FirstEntry = pList\Iterator\NextEntry
If pList\LastEntry = pList\Iterator Then pList\LastEntry = pList\Iterator\PreviousEntry
If pList\Iterator\NextEntry <> Null Then pList\Iterator\NextEntry\PreviousEntry = pList\Iterator\PreviousEntry
If pList\Iterator\PreviousEntry <> Null Then pList\Iterator\PreviousEntry\NextEntry = pList\Iterator\NextEntry
Local lEntry.TListEntry = pList\Iterator
pList\Iterator = pList\Iterator\NextEntry
Delete lEntry
If pList\Iterator <> Null Then Return pList\Iterator\Value
End Function
Function TList_DeleteValue(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\FirstEntry <> Null Then
Local lEntry.TListEntry = pList\FirstEntry
While lEntry <> Null
If lEntry\Value = Value Then
If lEntry\PreviousEntry <> Null Then lEntry\PreviousEntry\NextEntry = lEntry\NextEntry
If lEntry\NextEntry <> Null Then lEntry\NextEntry\PreviousEntry = lEntry\PreviousEntry
If pList\FirstEntry = lEntry Then pList\FirstEntry = lEntry\NextEntry
If pList\LastEntry = lEntry Then pList\LastEntry = lEntry\PreviousEntry
Local lDelEntry.TListEntry = lEntry
lEntry = lEntry\NextEntry
Delete lDelEntry
Else
lEntry = lEntry\NextEntry
EndIf
Wend
EndIf
End Function
@@ -0,0 +1,9 @@
LinkedList Emulation
=======================
Since the early BlitzBasic languages didn't have any kind of lists aside from the global ones, I had to make something out of nothing. This library adds the ability to have linked lists inside of those languages.
It was initially ment to use FastPointer or a similar library, but that failed horrifically, as I wasn't able to cast back into the original type and memory leaks happened. It's somewhat fast, but solutions tailored to a single type still work faster 90% of the time.
License
=======
LinkedList Emulation by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+258
View File
@@ -0,0 +1,258 @@
;----------------------------------------------------------------
;-- Types
;----------------------------------------------------------------
Type TList
Field FirstEntry.TListEntry
Field LastEntry.TListEntry
Field Iterator.TListEntry
End Type
Type TListEntry
Field Value%
Field PreviousEntry.TListEntry
Field NextEntry.TListEntry
End Type
;----------------------------------------------------------------
;-- Functions
;----------------------------------------------------------------
Function TList_Create.TList()
Local lList.TList = New TList
lList\FirstEntry = Null
lList\LastEntry = Null
lList\Iterator = Null
Return lList
End Function
Function TList_Destroy(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to destroy non-existing list."
; Delete all entries
pList\Iterator = pList\FirstEntry
While pList\Iterator <> Null
Local lNextEntry.TListEntry = pList\Iterator\NextEntry
Delete pList\Iterator
pList\Iterator = lNextEntry
Wend
End Function
Function TList_Reset(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to reset non-existing list."
pList\Iterator = Null
End Function
Function TList_First%(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
pList\Iterator = pList\FirstEntry
If pList\Iterator <> Null Then Return pList\Iterator\Value
End Function
Function TList_Last%(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
pList\Iterator = pList\LastEntry
If pList\Iterator <> Null Then Return pList\Iterator\Value
End Function
Function TList_Next%(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
If pList\Iterator <> Null Then
pList\Iterator = pList\Iterator\NextEntry
Else
pList\Iterator = pList\FirstEntry
EndIf
If pList\Iterator <> Null Then Return pList\Iterator\Value
End Function
Function TList_Previous%(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
If pList\Iterator <> Null Then
pList\Iterator = pList\Iterator\PreviousEntry
Else
pList\Iterator = pList\LastEntry
EndIf
If pList\Iterator <> Null Then Return pList\Iterator\Value
End Function
Function TList_HasFirst(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
Return (pList\FirstEntry <> Null)
End Function
Function TList_HasLast(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
Return (pList\LastEntry <> Null)
End Function
Function TList_HasNext(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
If pList\Iterator <> Null Then
Return (pList\Iterator\NextEntry <> Null)
Else
Return (pList\FirstEntry <> Null)
EndIf
End Function
Function TList_HasPrevious(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list."
If pList\Iterator <> Null Then
Return (pList\Iterator\PreviousEntry <> Null)
Else
Return (pList\LastEntry <> Null)
EndIf
End Function
Function TList_AddFirst(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
Local lEntry.TListEntry = New TListEntry
lEntry\Value = Value
If pList\FirstEntry <> Null Then
lEntry\NextEntry = pList\FirstEntry
lEntry\NextEntry\PreviousEntry = lEntry
EndIf
pList\FirstEntry = lEntry
If pList\LastEntry = Null Then pList\LastEntry = lEntry
End Function
Function TList_AddLast(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
Local lEntry.TListEntry = New TListEntry
lEntry\Value = Value
If pList\LastEntry <> Null Then
lEntry\PreviousEntry = pList\LastEntry
lEntry\PreviousEntry\NextEntry = lEntry
EndIf
If pList\FirstEntry = Null pList\FirstEntry = lEntry
pList\LastEntry = lEntry
End Function
Function TList_InsertBefore(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
Local lEntry.TListEntry = New TListEntry
lEntry\Value = Value
If pList\Iterator\PreviousEntry <> Null Then
lEntry\PreviousEntry = pList\Iterator\PreviousEntry
pList\Iterator\PreviousEntry\NextEntry = lEntry
Else
pList\FirstEntry = lEntry
EndIf
pList\Iterator\PreviousEntry = lEntry
If pList\Iterator\NextEntry = Null Then
pList\LastEntry = lEntry
EndIf
lEntry\NextEntry = pList\Iterator
End Function
Function TList_InsertAfter(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
Local lEntry.TListEntry = New TListEntry
lEntry\Value = Value
If pList\Iterator\NextEntry <> Null Then
lEntry\NextEntry = pList\Iterator\NextEntry
pList\Iterator\NextEntry\PreviousEntry = lEntry
Else
pList\LastEntry = lEntry
EndIf
pList\Iterator\NextEntry = lEntry
If pList\Iterator\PreviousEntry = Null Then
pList\FirstEntry = lEntry
EndIf
lEntry\PreviousEntry = pList\Iterator
End Function
Function TList_Replace(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
pList\Iterator\Value = Value
End Function
Function TList_DeleteFirst(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\FirstEntry = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
Local lEntry.TListEntry = pList\FirstEntry
pList\FirstEntry\NextEntry\PreviousEntry = Null
pList\FirstEntry = pList\FirstEntry\NextEntry
Delete lEntry
If pList\FirstEntry <> Null Then Return pList\FirstEntry\Value
End Function
Function TList_DeleteLast(pList.Tlist)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\LastEntry = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
Local lEntry.TListEntry = pList\LastEntry
pList\LastEntry\PreviousEntry\NextEntry = Null
pList\LastEntry = pList\LastEntry\PreviousEntry
Delete lEntry
If pList\LastEntry <> Null Then Return pList\LastEntry\Value
End Function
Function TList_Delete(pList.TList)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry."
If pList\FirstEntry = pList\Iterator Then pList\FirstEntry = pList\Iterator\NextEntry
If pList\LastEntry = pList\Iterator Then pList\LastEntry = pList\Iterator\PreviousEntry
If pList\Iterator\NextEntry <> Null Then pList\Iterator\NextEntry\PreviousEntry = pList\Iterator\PreviousEntry
If pList\Iterator\PreviousEntry <> Null Then pList\Iterator\PreviousEntry\NextEntry = pList\Iterator\NextEntry
Local lEntry.TListEntry = pList\Iterator
pList\Iterator = pList\Iterator\NextEntry
Delete lEntry
If pList\Iterator <> Null Then Return pList\Iterator\Value
End Function
Function TList_DeleteValue(pList.TList, Value%)
If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list."
If pList\FirstEntry <> Null Then
Local lEntry.TListEntry = pList\FirstEntry
While lEntry <> Null
If lEntry\Value = Value Then
If lEntry\PreviousEntry <> Null Then lEntry\PreviousEntry\NextEntry = lEntry\NextEntry
If lEntry\NextEntry <> Null Then lEntry\NextEntry\PreviousEntry = lEntry\PreviousEntry
If pList\FirstEntry = lEntry Then pList\FirstEntry = lEntry\NextEntry
If pList\LastEntry = lEntry Then pList\LastEntry = lEntry\PreviousEntry
Local lDelEntry.TListEntry = lEntry
lEntry = lEntry\NextEntry
Delete lDelEntry
Else
lEntry = lEntry\NextEntry
EndIf
Wend
EndIf
End Function
+27
View File
@@ -0,0 +1,27 @@
Global Logger_Stream
Function Logger_Initialize(File$)
File = "Logs/" + File
CreateDir("./Logs/")
If FileType("./Logs/") <> 2 Then RuntimeError("Unable To create Log File."+Chr(10)+" If the program is running in a protected directory,"+Chr(10)+" consider running it as an administrator.")
Logger_Stream = OpenFile(File)
If Logger_Stream = 0
Logger_Stream = WriteFile(File)
If Logger_Stream = 0 Then RuntimeError("Unable to create log file."+Chr(10)+" If the program is running in a protected directory,"+Chr(10)+" consider running it as an administrator.")
EndIf
End Function
Function Logger_Info(Module$, Message$)
WriteLine Logger_Stream, "[" + CurrentTime() + "] [Info] " + Module + ": " + Message
End Function
Function Logger_Warning(Module$, Message$)
WriteLine Logger_Stream, "[" + CurrentTime() + "] [Warn] " + Module + ": " + Message
End Function
Function Logger_Error(Module$, Message$)
WriteLine Logger_Stream, "[" + CurrentTime() + "] [Errr] " + Module + ": " + Message
End Function
;~IDEal Editor Parameters:
;~C#Blitz3D
+665
View File
@@ -0,0 +1,665 @@
;----------------------------------------------------------------
;-- Packet Descriptors
;----------------------------------------------------------------
;-- Any Packet
;Off Size Desc
; 0 1 Packet Id
;-- Login
;Off Size Desc
; 1 2 Unique Id (Server) / UDP Port (Client)
; 3 2 Version
; 5 16 Name (Always 16B, Only allows bytes above 32)
; 21 4F Initial Position X
; 25 4F Initial Position Y
; 29 4F Initial Position Z
; 33 4F Initial Rotation X
; 37 4F Initial Rotation Y
; 41 4F Initial Rotation Z
;-- Logout
;Off Size Desc
; 1 2 Unique Id
;-- Kick
;Off Size Desc
; 1 2 Reason Length
; 3 ^ Reason
;-- Data
; 1 2 Unique Id
; 3 1 Data Flags (See BNET_DATAFLAG_*)
;... 4F Position X
;... 4F Position Y
;... 4F Position Z
;... 2 Rotation X
;... 2 Rotation Y
;... 2 Rotation Z
;... 2 Velocity X
;... 2 Velocity Y
;... 2 Velocity Z
;... 2 Aim X
;... 2 Aim Y
;-- Action (Yet Unsupported)
;----------------------------------------------------------------
;-- Constants
;----------------------------------------------------------------
; BlitzNet Version
Const BNET_VERSION_MAJOR% = 0
Const BNET_VERSION_MINOR% = 1
; Size of Buffer for Network Packets, 64KB should be enough for now.
Const BNET_BUFFER_SIZE% = (64 * 1024)
; Flags for data changes. Only when the bit is set this data is available.
Const BNET_DATAFLAG_POSX = $00000001
Const BNET_DATAFLAG_POSY = $00000010
Const BNET_DATAFLAG_POSZ = $00000100
Const BNET_DATAFLAG_ROTX = $00001000
Const BNET_DATAFLAG_ROTY = $00010000
Const BNET_DATAFLAG_ROTZ = $00100000
Const BNET_DATAFLAG_VELOCITY = $01000000
Const BNET_DATAFLAG_AIM = $10000000
; Packet Ids, for identification of each one.
Const BNET_PACKET_LOGIN = 0
Const BNET_PACKET_LOGOUT = 1
Const BNET_PACKET_KICK = 2
Const BNET_PACKET_DATA = 3
Const BNET_PACKET_ACTION = 4
; How many updates should we send out each minute?
Const BNET_DATA_COUNT = 150
; How many keyframes should we send out each minute?
Const BNET_DATA_COUNT_KEYFRAME = 3
; How much has the value to change to be considered different?
Const BNET_DATA_THRESHOLD_POS# = 1.0
Const BNET_DATA_THRESHOLD_ROT# = 1.0
Const BNET_DATA_THRESHOLD_VEL# = 1.0
Const BNET_DATA_THRESHOLD_AIM# = 1.0
;----------------------------------------------------------------
;-- Globals
;----------------------------------------------------------------
; Connections to Sector Servers.
Global BNet_Sector_TCP% = 0
Global BNet_Sector_UDP% = 0
; Our UniqueId and Player instance so we know which Player is us.
Global BNet_UniqueId% = -1
Global BNet_Player.BNetPlayer = Null
; Buffer for Network Packets.
Global BNet_Buffer% = CreateBank(BNET_BUFFER_SIZE)
; Set to true when Kicked from the server, or similar.
Global BNet_Kick% = False
Global BNet_Kick_Reason$ = "Not Kicked"
; Update Times
Global BNet_Data_Time = 60000 / BNET_DATA_COUNT
Global BNet_Data_Time_KeyFrame = 60000 / BNET_DATA_COUNT_KEYFRAME
Global BNet_Data_LastUpdate = 0
Global BNet_Data_LastKeyFrame = 0
; Array for all known players. Makes access a bit faster.
Dim BNet_Players.BNetPlayer(65535)
;----------------------------------------------------------------
;-- Types
;----------------------------------------------------------------
Type BNetPlayer
Field Name$ = "Invalid Player"
; Position, Rotation, Velocity and Aim
Field PositionX#, PositionY#, PositionZ#
Field RotationX#, RotationY#, RotationZ#
Field VelocityX#, VelocityY#, VelocityZ#
Field AimX#, AimY#
; Internal Data
Field m_UniqueId%
End Type
;----------------------------------------------------------------
;-- Functions
;----------------------------------------------------------------
Function BNet_Initialize()
TCPTimeouts 100, 100
End Function
Function BNet_Connect(Ip$ = "127.0.0.1", IPort% = 27000, DPort = 27001)
BNet_Kick% = False
BNet_Kick_Reason$ = "Not Kicked"
BNet_Sector_TCP = OpenTCPStream(Ip, IPort)
If BNet_Sector_TCP Then
BNet_Sector_UDP = CreateUDPStream()
If BNet_Sector_UDP Then
Return True
Else
CloseTCPStream BNet_Sector_TCP
BNet_Sector_UDP = 0
BNet_Sector_TCP = 0
EndIf
Else
BNet_Sector_UDP = 0
BNet_Sector_TCP = 0
EndIf
Return False
End Function
Function BNet_Disconnect()
If BNet_UniqueId > -1 Then
; Remove all existing players
For Player.BNetPlayer = Each BNetPlayer
Local UniqueId = Player\m_UniqueId
CB_BNet_DeletePlayer(UniqueId, Player)
Delete BNet_Players(UniqueId):BNet_Players(UniqueId) = Null
Next
; Logout
BNet_Logout()
BNet_UniqueId = -1
EndIf
If BNet_Sector_UDP Then CloseUDPStream(BNet_Sector_UDP):BNet_Sector_UDP = 0
If BNet_Sector_TCP Then CloseTCPStream(BNet_Sector_TCP):BNet_Sector_TCP = 0
End Function
Function BNet_Connected()
If BNet_Sector_TCP = 0 Then Return False
If BNet_Sector_UDP = 0 Then Return False
If Eof(BNet_Sector_TCP) <> 0 Then Return False
Return True
End Function
Function BNet_Login(Name$, PosX# = 0, PosY# = 0, PosZ# = 0, RotX# = 0, RotY# = 0, RotZ# = 0)
If BNet_Connected() And BNet_UniqueId = -1 Then
; Packet Id: Login
PokeByte BNet_Buffer, 0, BNET_PACKET_LOGIN
; Write UDP Port
PokeShort BNet_Buffer, 1, UDPStreamPort(BNet_Sector_UDP)
; Write Client Version
PokeShort BNet_Buffer, 3, BNET_VERSION_MAJOR Shl 8 + BNET_VERSION_MINOR
; Write Name
Local NameLength% = Len(Name)
For NamePos = 1 To NameLength:PokeByte BNet_Buffer, (5 + NamePos - 1), Asc(Mid(Name, NamePos, 1)):Next
For NamePos = NameLength To 16:PokeByte BNet_Buffer, (5 + NamePos - 1), 0:Next
; Write Initial Position
PokeFloat BNet_Buffer, 21, PosX
PokeFloat BNet_Buffer, 25, PosY
PokeFloat BNet_Buffer, 29, PosZ
; Write Initial Rotation
PokeFloat BNet_Buffer, 33, RotX
PokeFloat BNet_Buffer, 37, RotX
PokeFloat BNet_Buffer, 41, RotX
; Write to Stream
WriteBytes BNet_Buffer, BNet_Sector_TCP, 0, 47
Return True
Else
Return False
EndIf
End Function
Function BNet_Logout()
If BNet_Connected() And BNet_UniqueId > -1 Then
; Packet Id: Logout
PokeByte BNet_Buffer, 0, BNET_PACKET_LOGOUT
; Write our own UniqueId
PokeShort BNet_Buffer, 1, BNet_UniqueId
; Write to Stream
WriteBytes BNet_Buffer, BNet_Sector_TCP, 0, 3
Return True
Else
Return False
EndIf
End Function
Function BNet_Update()
Local UniqueId, PacketSize, PacketId, DataFlags, Offset, TempPlayer.BNetPlayer
If BNet_Connected() Then
; TCP
While Not Eof(BNet_Sector_TCP) And ReadAvail(BNet_Sector_TCP) > 0
PacketSize = ReadAvail(BNet_Sector_TCP)
If PacketSize > BNET_BUFFER_SIZE Then PacketSize = BNET_BUFFER_SIZE
ReadBytes(BNet_Buffer, BNet_Sector_TCP, 0, PacketSize)
PacketId = PeekByte(BNet_Buffer, 0)
Select PacketId
Case BNET_PACKET_LOGIN
UniqueId = PeekShort(BNet_Buffer, 1)
BNet_Players(UniqueId) = New BNetPlayer
; Read Name
For NamePos = 1 To 16
Local NameChar = PeekByte(BNet_Buffer, (5 + NamePos - 1))
If NameChar < 32 Then Exit
BNet_Players(UniqueId)\Name$ = BNet_Players(UniqueId)\Name$ + Chr(NameChar)
Next
; Read initital Position
BNet_Players(UniqueId)\PositionX = PeekFloat(BNet_Buffer, 21)
BNet_Players(UniqueId)\PositionY = PeekFloat(BNet_Buffer, 25)
BNet_Players(UniqueId)\PositionZ = PeekFloat(BNet_Buffer, 29)
; Read initial Rotation
BNet_Players(UniqueId)\RotationX = PeekFloat(BNet_Buffer, 33)
BNet_Players(UniqueId)\RotationY = PeekFloat(BNet_Buffer, 37)
BNet_Players(UniqueId)\RotationZ = PeekFloat(BNet_Buffer, 41)
; Assign Unique Id
BNet_Players(UniqueId)\m_UniqueId = UniqueId
; Assign local UniqueId if we don't have one.
If BNet_UniqueId > -1 Then
BNet_UniqueId = UniqueId
Else
CB_BNet_CreatePlayer(UniqueId, BNet_Players(BNet_UniqueId))
EndIf
Case BNET_PACKET_LOGOUT
UniqueId = PeekShort(BNet_Buffer, 1)
; A logout packet for ourselves will make us logout.
If BNet_UniqueId = UniqueId Then
BNet_Disconnect():Return True
ElseIf BNet_Players(UniqueId) <> Null Then
; Otherwise, it is another player removed from visible space.
CB_BNet_DeletePlayer(Unique, BNet_Players(UniqueId))
Delete BNet_Players(UniqueId):BNet_Players(UniqueId) = Null
Else
DebugLog "BNet: Logout for non-existing player."
EndIf
Case BNET_PACKET_KICK
BNet_Kick = True
; Read reason for Kick
Local ReasonLength% = PeekShort(BNet_Buffer, 1)
For ReasonPos = 1 To ReasonLength
Local ReasonChar = PeekByte(BNet_Buffer, (3 + ReasonPos - 1))
If ReasonChar < 32 Then Exit
BNet_Kick_Reason = BNet_Kick_Reason + Chr(NameChar)
Next
BNet_Disconnect():Return True
End Select
Wend
; UDP
While Not Eof(BNet_Sector_UDP) And ReadAvail(BNet_Sector_UDP) > 0
PacketSize = ReadAvail(BNet_Sector_UDP)
If PacketSize > BNET_BUFFER_SIZE Then PacketSize = BNET_BUFFER_SIZE
ReadBytes(BNet_Buffer, BNet_Sector_UDP, 0, PacketSize)
PacketId = PeekByte(BNet_Buffer, 0)
Select PacketId
Case BNET_PACKET_DATA
If BNet_UniqueId > -1 Then
UniqueId = PeekShort(BNet_Buffer, 1)
If BNet_Players(UniqueId) <> Null Then
DataFlags = PeekShort(BNet_Buffer, 3)
Offset% = 5
If DataFlags And BNET_DATAFLAGS_POSX Then BNet_Players(UniqueId)\PositionX = PeekInt(BNet_Buffer, Offset):Offset = Offset + 4
If DataFlags And BNET_DATAFLAGS_POSY Then BNet_Players(UniqueId)\PositionY = PeekInt(BNet_Buffer, Offset):Offset = Offset + 4
If DataFlags And BNET_DATAFLAGS_POSZ Then BNet_Players(UniqueId)\PositionZ = PeekInt(BNet_Buffer, Offset):Offset = Offset + 4
If DataFlags And BNET_DATAFLAGS_ROTX Then BNet_Players(UniqueId)\RotationX = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 360.0:Offset = Offset + 2
If DataFlags And BNET_DATAFLAGS_ROTY Then BNet_Players(UniqueId)\RotationY = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 360.0:Offset = Offset + 2
If DataFlags And BNET_DATAFLAGS_ROTZ Then BNet_Players(UniqueId)\RotationZ = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 360.0:Offset = Offset + 2
If DataFlags And BNET_DATAFLAGS_VELOCITY Then
BNet_Players(UniqueId)\VelocityX = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 255.0
BNet_Players(UniqueId)\VelocityY = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 255.0
BNet_Players(UniqueId)\VelocityZ = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 255.0
Offset = Offset + 6
EndIf
If DataFlags And BNET_DATAFLAGS_AIM Then
BNet_Players(UniqueId)\AimX = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 360.0
BNet_Players(UniqueId)\AimY = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 360.0
Offset = Offset + 4
EndIf
; Tell Client to update visual stuff
CB_BNet_UpdatePlayer(UniqueId, BNet_Players(UniqueId))
EndIf
EndIf
; Case BNET_PACKET_ACTION
; If BNet_UniqueId > -1 Then
;
; EndIf
End Select
Wend
; If we are logged in, tell the server our current data.
If BNet_UniqueId > -1 Then
Local Time = MilliSecs()
; Send out whatever is needed.
If Time - BNet_Data_LastKeyFrame > BNet_Data_Time_KeyFrame Then
; Force Client to update Player object
CB_BNet_SendUpdate(BNet_UniqueId, BNet_Player)
; Packet Id
PokeByte BNet_Buffer, 0, BNET_PACKET_DATA
; Unique Id
PokeShort BNet_Buffer, 1, BNet_UniqueId
; Data Flags (KeyFrame always has this at 255, since it contains all data)
PokeByte BNet_Buffer, 3, $11111111
; Position
PokeFloat BNet_Buffer, 4, BNet_Player\PositionX
PokeFloat BNet_Buffer, 8, BNet_Player\PositionY
PokeFloat BNet_Buffer,12, BNet_Player\PositionZ
; Rotation
PokeShort BNet_Buffer,16, BNet_ShortFromFloat(BNet_Player\RotationX / 360.0)
PokeShort BNet_Buffer,18, BNet_ShortFromFloat(BNet_Player\RotationY / 360.0)
PokeShort BNet_Buffer,20, BNet_ShortFromFloat(BNet_Player\RotationZ / 360.0)
; Velocity
PokeShort BNet_Buffer,22, BNet_ShortFromFloat(BNet_Player\VelocityX / 256.0)
PokeShort BNet_Buffer,24, BNet_ShortFromFloat(BNet_Player\VelocityY / 256.0)
PokeShort BNet_Buffer,26, BNet_ShortFromFloat(BNet_Player\VelocityZ / 256.0)
; Aim
PokeShort BNet_Buffer,28, BNet_ShortFromFloat(BNet_Player\AimX / 360.0)
PokeShort BNet_Buffer,30, BNet_ShortFromFloat(BNet_Player\AimY / 360.0)
; Send Packet
WriteBytes BNet_Buffer, BNet_Sector_UDP, 0, 32
; Swap Player objects.
TempPlayer = BNet_Player
BNet_Player = BNet_Players(BNet_UniqueId)
BNet_Players(BNet_UnqiueId) = TempPlayer
; Set last keyframe and update time to now.
BNet_Data_LastKeyFrame = Time
BNet_Data_LastUpdate = Time
ElseIf Time - BNet_Data_LastUpdate > BNet_Data_Time Then
DataFlags = 0
Offset = 4
; Force Client to update Player object
CB_BNet_SendUpdate(BNet_UniqueId, BNet_Player)
; Packet Id
PokeByte BNet_Buffer, 0, BNET_PACKET_DATA
; Unique Id
PokeShort BNet_Buffer, 1, BNet_UniqueId
; Position
If Abs(BNet_Player\PositionX - BNet_Players(BNet_UniqueId)\PositionX) > BNET_DATA_THRESHOLD_POS Then
DataFlags = DataFlags Or BNET_DATAFLAG_POSX
PokeFloat BNet_Buffer, Offset, BNet_Player\PositionX:Offset = Offset + 4
EndIf
If Abs(BNet_Player\PositionY - BNet_Players(BNet_UniqueId)\PositionY) > BNET_DATA_THRESHOLD_POS Then
DataFlags = DataFlags Or BNET_DATAFLAG_POSY
PokeFloat BNet_Buffer, Offset, BNet_Player\PositionY:Offset = Offset + 4
EndIf
If Abs(BNet_Player\PositionZ - BNet_Players(BNet_UniqueId)\PositionZ) > BNET_DATA_THRESHOLD_POS Then
DataFlags = DataFlags Or BNET_DATAFLAG_POSZ
PokeFloat BNet_Buffer, Offset, BNet_Player\PositionZ:Offset = Offset + 4
EndIf
; Rotation
If Abs(BNet_Player\RotationX - BNet_Players(BNet_UniqueId)\RotationX) > BNET_DATA_THRESHOLD_POS Then
DataFlags = DataFlags Or BNET_DATAFLAG_ROTX
PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\RotationX / 360.0):Offset = Offset + 2
EndIf
If Abs(BNet_Player\RotationY - BNet_Players(BNet_UniqueId)\RotationY) > BNET_DATA_THRESHOLD_POS Then
DataFlags = DataFlags Or BNET_DATAFLAG_ROTY
PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\RotationY / 360.0):Offset = Offset + 2
EndIf
If Abs(BNet_Player\RotationZ - BNet_Players(BNet_UniqueId)\RotationZ) > BNET_DATA_THRESHOLD_POS Then
DataFlags = DataFlags Or BNET_DATAFLAG_ROTZ
PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\RotationZ / 360.0):Offset = Offset + 2
EndIf
; Velocity
If Abs(BNet_Player\VelocityX - BNet_Players(BNet_UniqueId)\VelocityX) + Abs(BNet_Player\VelocityY - BNet_Players(BNet_UniqueId)\VelocityY) + Abs(BNet_Player\VelocityZ - BNet_Players(BNet_UniqueId)\VelocityZ) > BNET_DATA_THRESHOLD_VEL Then
DataFlags = DataFlags Or BNET_DATAFLAG_VELOCITY
PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\VelocityX / 256.0):Offset = Offset + 2
PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\VelocityY / 256.0):Offset = Offset + 2
PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\VelocityZ / 256.0):Offset = Offset + 2
EndIf
; Aim
If Abs(BNet_Player\AimX - BNet_Players(BNet_UniqueId)\AimX) + Abs(BNet_Player\AimY - BNet_Players(BNet_UniqueId)\AimY) > BNET_DATA_THRESHOLD_AIM Then
DataFlags = DataFlags Or BNET_DATAFLAG_AIM
PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\AimX / 360.0):Offset = Offset + 2
PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\AimY / 360.0):Offset = Offset + 2
EndIf
; Data Flags
PokeByte BNet_Buffer, 3, DataFlags
; Send Packet
WriteBytes BNet_Buffer, BNet_Sector_UDP, 0, Offset
; Swap Player objects.
TempPlayer = BNet_Player
BNet_Player = BNet_Players(BNet_UniqueId)
BNet_Players(BNet_UnqiueId) = TempPlayer
; Set last update time to now.
BNet_Data_LastUpdate = Time
EndIf
EndIf
Else
Return False
EndIf
End Function
Function BNet_FloatFromShort#(Value%)
Return BNet_Math_ClipF((Value / 65536.0), 0.0, 1.0)
End Function
Function BNet_ShortFromFloat%(Value#)
Return BNet_Math_ClipF((Value * 65536.0), 0.0, 1.0)
End Function
Function BNet_Math_MinimumF#(Value#, Min#)
If Value < Min Then Return Min
Return Value
End Function
Function BNet_Math_MaximumF#(Value#, Max#)
If Value > Max Then Return Max
Return Value
End Function
Function BNet_Math_ClampF#(Value#, Min#, Max#)
If Value < Min Then Return Min
If Value > Max Then Return Max
Return Value
End Function
Function BNet_Math_ClipF#(Value#, Min#, Max#)
Local Out#, Diff#
Diff = Max - Min:Out = Value - Min
If (Out >= Diff) Or (Out < 0) Then Out = Out - (Floor(Out/Diff) * Diff)
Return Min + Out
End Function
;----------------------------------------------------------------
;-- Callbacks
;----------------------------------------------------------------
;Function CB_BNet_CreatePlayer(UniqueId, Player.BNetPlayer)
;End Function
;Function CB_BNet_UpdatePlayer(UniqueId, Player.BNetPlayer)
;End Function
;Function CB_BNet_DeletePlayer(UniqueId, Player.BNetPlayer)
;End Function
;Function CB_BNet_SendUpdate(UniqueId, Player.BNetPlayer)
;End Function
;----------------------------------------------------------------
;-- Example
;----------------------------------------------------------------
Graphics3D 800, 600, 32, 2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
Local FrameTimer = CreateTimer(60)
Local TimeToLogin = MilliSecs()
Dim Players.TPlayer(65535)
Local Player.TPlayer = Null
Global TestX#, TestY#, TestZ#
Global TestRX#, TestRY#, TestRZ#
Global TestVX#, TestVY#, TestVZ#
Global TestAX#, TestAY#
Local ShipVeloLR#, ShipVeloUD#, ShipVeloFB#
Const ShipMaxVeloLR# = 5.0, ShipMaxVeloUD# = 5.0, ShipMaxVeloFB = 30.0
; Init
TestX = Rnd(-2048, 2048)
TestY = Rnd(-2048, 2048)
TestZ = Rnd(-2048, 2048)
TestRX = Rnd(0, 360)
TestRY = Rnd(0, 360)
TestRZ = Rnd(0, 360)
TestVX = 0
TestVY = 0
TestVZ = 0
TestAX = 0
TestAY = 0
Local Cam = CreateCamera()
Local Conv = CreatePivot()
Print "[INF] Connecting..."
BNet_Initialize()
BNet_Connect()
If BNet_Connected() Then
Print "[INF] Logging in..."
BNet_Login("Test " + Rand(0, 65535), TestX, TestY, TestZ, TestRX, TestRY, TestRZ)
Local LoopExit = False
Local Load = False
Repeat
If Load = False And BNet_UniqueId = -1 And (MilliSecs() - TimeToLogin > 30000) Then
Print "[ERR] Failed to login."
LoopExit = True
ElseIf Load = False And BNet_UniqueId > -1 Then
Print "[INF] Logged in."
Player = New TPlayer
Player\Mesh = CreateCone()
Player\Player = BNet_Player
Players(BNet_UniqueId) = Player
EntityParent Cam, Player\Mesh
Load = True
ElseIf Load = True And BNet_UniqueId > -1
; Player Input
; Velocity
ShipVeloFB = BNet_Math_ClampF(ShipVeloFB + (KeyDown(17) - KeyDown(31)) * 2.5, -ShipMaxVeloFB, ShipMaxVeloFB)
ShipVeloLR = BNet_Math_ClampF(ShipVeloLR + (KeyDown(32) - KeyDown(30)) * 1.5, -ShipMaxVeloLR, ShipMaxVeloLR)
ShipVeloUD = BNet_Math_ClampF(ShipVeloUD + (KeyDown(19) - KeyDown(33)) * 1.5, -ShipMaxVeloUD, ShipMaxVeloUD)
; Rotation
If KeyDown(57) Then
If KeyHit(57) Then MoveMouse 512, 384
TestRX = TestRX + ((MouseX() / 512) - 1.0)
TestRY = TestRY + ((MouseY() / 384) - 1.0)
EndIf
TestRZ = TestRZ + (KeyDown(18) - KeyDown(16)) * 1.0
; Update Game
; Slowly scale down Velocity.
ShipVeloFB = ShipVeloFB * 0.9
ShipVeloLR = ShipVeloLR * 0.8
ShipVeloUD = ShipVeloUD * 0.8
; Convert Local Velocity to Global Velocity
TFormPoint ShipVeloLR, ShipVeloUD, ShipVeloFB, Player\Mesh, Conv
TestVX = TFormedX()
TestVY = TFormedY()
TestVZ = TFormedZ()
; Move player by Velocity.
TestX = TestX + TestVX
TestY = TestY + TestVY
TestZ = TestZ + TestVZ
; Draw Game
; Update Local Mesh
PositionEntity Player\Mesh, TestX, TestY, TestZ
RotateEntity Player\Mesh, TestRX, TestRY, TestRZ
; Update conversion point
PositionEntity Conv, TestX, TestY, TestZ
RenderWorld
Flip 0
EndIf
If BNet_Update() Then
LoopExit = True
EndIf
WaitTimer FrameTimer
Until (LoopExit = True)
If BNet_Kick = True Then Print "[INF] Kicked: " + BNet_Kick_Reason Else Print "Logging out."
BNet_Disconnect()
Else
Print "[ERR] Failed to connect."
EndIf
End
Function CB_BNet_CreatePlayer(UniqueId, Player.BNetPlayer)
DebugLog "[INF] New Player: " + Player\Name + "[" + UniqueId + "]"
DebugLog " Pos: " + Player\PositionX + ", " + Player\PositionY + ", " + Player\PositionZ
DebugLog " Rot: " + Player\RotationX + ", " + Player\RotationY + ", " + Player\RotationZ
If Players(UniqueId) = Null Then Players(UniqueId) = New TPlayer
If Players(UniqueId)\Mesh <> 0 Then Players(UniqueId)\Mesh = CreateCone()
Players(UniqueId)\Player = Player
PositionEntity Players(UniqueId)\Mesh, Player\PositionX, Player\PositionY, Player\PositionZ
RotateEntity Players(UniqueId)\Mesh, Player\RotationX, Player\RotationY, Player\RotationZ
End Function
Function CB_BNet_UpdatePlayer(UniqueId, Player.BNetPlayer)
If Players(UniqueId) <> Null Then
DebugLog "[INF] Update Player: " + Player\Name + "[" + UniqueId + "]"
DebugLog " Pos: " + Player\PositionX + ", " + Player\PositionY + ", " + Player\PositionZ
DebugLog " Rot: " + Player\RotationX + ", " + Player\RotationY + ", " + Player\RotationZ
PositionEntity Players(UniqueId)\Mesh, Player\PositionX, Player\PositionY, Player\PositionZ
RotateEntity Players(UniqueId)\Mesh, Player\RotationX, Player\RotationY, Player\RotationZ
Else
DebugLog "[ERR] Player does not exist: " + Player\Name + "[" + UniqueId + "]"
EndIf
End Function
Function CB_BNet_DeletePlayer(UniqueId, Player.BNetPlayer)
If Players(UniqueId) <> Null Then
DebugLog "[INF] Delete Player: " + UniqueId + "," + Player\Name
FreeEntity Players(UniqueId)\Mesh
Delete Players(UniqueId)
Else
DebugLog "[ERR] Player does not exist: " + Player\Name + "[" + UniqueId + "]"
EndIf
End Function
Function CB_BNet_SendUpdate(UniqueId, Player.BNetPlayer)
DebugLog "[INF] Update Self"
Player\PositionX = TestX
Player\PositionY = TestY
Player\PositionZ = TestZ
Player\VelocityX = TestVX
Player\VelocityY = TestVY
Player\VelocityZ = TestVZ
Player\RotationX = TestRX
Player\RotationY = TestRY
Player\RotationZ = TestRZ
Player\AimX = TestAX
Player\AimY = TestAY
End Function
Type TPlayer
Field Mesh
Field Player.BNetPlayer
End Type
+8
View File
@@ -0,0 +1,8 @@
Random Stuff
=======================
Contains remaining projects that don't require their own folder or were modified to fit a specific project. Most of this is from Sirius Online and BlitzHit, so expect nothing to work.
License
=======
Random Stuff by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+44
View File
@@ -0,0 +1,44 @@
AppTitle "TrueMotion"
Include "TrueMotion.bb"
Graphics3D 1024,768,0,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
Local eCamera = CreateCamera()
Local tCube = CreateTexture(128,128)
SetBuffer TextureBuffer(tCube)
Color 255, 255, 0
Rect 0, 0, 64, 64
Rect 64, 64, 64, 64
Color 0, 127, 255
Rect 64, 0, 64, 64
Rect 0, 64, 64, 64
SetBuffer BackBuffer()
Local eCube = CreateCube()
PositionEntity eCube, 0, 0, 3
EntityTexture eCube, tCube
Local tInstance.TrueMotion = TrueMotion_Create(eCamera)
Timer = CreateTimer(60)
Global Msec
While Not KeyHit(1)
Cls
Msec = Msec + 10
RotateEntity eCube, Cos(Msec/4.0)*30, 0, EntityRoll(eCube) + 16
PositionEntity eCube, 0, Sin(Msec/4.0)*2, 4
TrueMotion_RenderWorld(tInstance)
Flip
WaitTimer(Timer)
Wend
End
;~IDEal Editor Parameters:
;~C#Blitz3D
+207
View File
@@ -0,0 +1,207 @@
Type Tradelane
Field P1.TVector, P2.TVector, Dir.TVector
Field From$, Target$
Field FromSpot.Spotmark, TargetSpot.Spotmark
Field Gates.TList, Lasers.TList
Field RingsTop.TList, RingsBot.TList
Field RingsInnerTop.TList, RingsInnerBot.TList
Field TubesTop.TList, TubesBot.TList
Field PivotTubes
Field PivotRings
Field MeshA, MeshB, OBBa, OBBb
Field XTubeA, XTubeB
Field Range
End Type
Const Tradelane_Speed# = 50.0
Const Tradelane_SpeedForce# = 0.125
Const Tradelane_Force# = 0.1
Const Tradelane_GateDistance# = 5000.0
Const Tradelane_Offset# = 144
Const Tradelane_Size# = 115
Function CreateTradelane(StartX,StartY,StartZ, EndX,EndY,EndZ, From$, Target$)
Local T.Tradelane = New Tradelane
Local TempVec.TVector
; Information
T\From = From:T\Target = Target
; Start, End and Direction Vector
T\P1 = TVector_Create(StartX, StartY, StartZ)
T\P2 = TVector_Create(EndX, EndY, EndZ)
TempVec = TVector_Subtract(T\P2, T\P1)
T\Dir = TVector_Normalize(TempVec):Delete TempVec
Local Range# = TVector_Distance(T\P1, T\P2)
; Initialize LinkedLists
T\Gates = TList_Create()
T\Lasers = TList_Create()
T\RingsTop = TList_Create()
T\RingsBot = TList_Create()
T\RingsInnerTop = TList_Create()
T\RingsInnerBot = TList_Create()
T\TubesTop = TList_Create()
T\TubesBot = TList_Create()
T\PivotRings = CreatePivot(PVTxEFFECT)
T\PivotTubes = CreatePivot(PVTxEFFECT)
; Create Spots
T\FromSpot.Spotmark = CreateSpot(T\P1\X, T\P1\Y, T\P1\Z, 21, (From + ">>>" + Target))
T\FromSpot.Spotmark = CreateSpot(T\P2\X, T\P2\Y, T\P2\Z, 21, (Target + ">>>" + From))
; Create OBB Collisions
TVector_Angle(T\Dir)
Local TX#, TY#, TZ#
TX = (T\P1\X + T\P2\X) / 2.0
TY = (T\P1\Y + T\P2\Y) / 2.0
TZ = (T\P1\Z + T\P2\Z) / 2.0
Local TVecUp.TVector = TVector_Rotate(T\Dir, -90, 0, 0)
T\OBBa=CreateOBB(TX, TY, TZ, TVector_Pitch-90, TVector_Yaw, 0, 115, 115, Range/2)
T\OBBb=CreateOBB(TX, TY, TZ, TVector_Pitch-90, TVector_Yaw, 0, 115, 115, Range/2)
MoveEntity T\OBBa, 0, Tradelane_Offset, 0
MoveEntity T\OBBb, 0, -Tradelane_Offset, 0
Delete TVecUp
; Create Gates, Sprites and Rings
Local Count = Ceil(Range / Tradelane_GateDistance)
Local Stp# = Range / Count
For n = 0 To Count
; Calculate Position
TempVec = TVector_MultiplyScalar(T\Dir, n*Stp)
Local Pos.TVector = TVector_Add(T\P1, TempVec)
; Create Mesh
Local Mesh = CopyEntity(TLxMSH, PVTxNORMAL)
PositionEntity Mesh, Pos\X, Pos\Y, Pos\Z
AlignToVector Mesh, T\Dir\X, T\Dir\Y, T\Dir\Z, 0, 1
RotateEntity Mesh, EntityPitch(Mesh, 1), EntityYaw(Mesh, 1), 0, 1
EntityAutoFade Mesh,14500,15000
TList_AddLast(T\Gates, Mesh)
; Create Laser
Local Laser = CopyEntity(TLxMSX, Mesh)
EntityAutoFade Laser,9500,10000
TList_AddLast(T\Lasers, Laser)
; Create Rings
Local RingTop = CopyEntity(TLxENT, Mesh)
Local RingBot = CopyEntity(TLxENT, Mesh)
MoveEntity RingTop, 0, Tradelane_Offset, 0
MoveEntity RingBot, 0, -Tradelane_Offset, 0
ScaleSprite RingTop, 125, 125:SpriteViewMode RingTop, 2:EntityColor RingTop, 64, 198, 255:EntityAlpha RingTop, 0.5:EntityAutoFade RingTop, 4500, 5000:EntityBlend RingTop, 3:EntityFX RingTop, 1+16
ScaleSprite RingBot, 125, 125:SpriteViewMode RingBot, 2:EntityColor RingBot, 255, 0, 0:EntityAlpha RingBot, 0.5:EntityAutoFade RingBot, 4500, 5000:EntityBlend RingBot, 3:EntityFX RingBot, 1+16
TList_AddLast(T\RingsTop, RingTop)
TList_AddLast(T\RingsBot, RingBot)
Local RingInTop = CopyEntity(TLxENT2, Mesh)
Local RingInBot = CopyEntity(TLxENT2, Mesh)
MoveEntity RingInTop, 0, Tradelane_Offset, 0
MoveEntity RingInBot, 0, -Tradelane_Offset, 0
ScaleSprite RingInTop, 125, 125:SpriteViewMode RingInTop, 2:EntityAlpha RingInTop, 0.5:EntityAutoFade RingInTop, 4500, 5000:EntityBlend RingInTop, 3:EntityFX RingInTop, 1+16
ScaleSprite RingInBot, 125, 125:SpriteViewMode RingInBot, 2:EntityAlpha RingInBot, 0.5:EntityAutoFade RingInBot, 4500, 5000:EntityBlend RingInBot, 3:EntityFX RingInBot, 1+16
TList_AddLast(T\RingsInnerTop, RingInTop)
TList_AddLast(T\RingsInnerBot, RingInBot)
; Create Refraction Tubes
If n < Count
Local Tube
Tube = CreateCylinder(24, 0, RingInTop)
ScaleEntity Tube, Tradelane_Size, Stp/2, Tradelane_Size
TurnEntity Tube, -90, 0, 0
MoveEntity Tube, 0, -Stp/2, 0
EntityParent Tube, T\PivotTubes
EntityAutoFade Tube, 5000, 10000
EntityFX Tube, 1+8+16
EntityTexture Tube,StarBTex,0,0
EntityTexture Tube,ProjectTex,0,1
EntityAlpha Tube, 0.35
TList_AddLast(T\TubesTop, Tube)
Tube = CreateCylinder(24, 0, RingInBot)
ScaleEntity Tube, Tradelane_Size, Stp/2, Tradelane_Size
TurnEntity Tube, 90, 0, 0
MoveEntity Tube, 0, Stp/2, 0
EntityParent Tube, T\PivotTubes
EntityAutoFade Tube, 5000, 10000
EntityFX Tube, 1+8+16
EntityTexture Tube,StarBTex,0,0
EntityTexture Tube,ProjectTex,0,1
EntityAlpha Tube, 0.35
TList_AddLast(T\TubesBot, Tube)
EndIf
; Delete remaining temporary data
Delete Pos:Delete TempVec
Next
End Function
Function UpdateTradelane()
;set test on
TLxTST=0
; Create Camera Vector
Local vCam.TVector = New TVector
Local vGate.TVector = New TVector
Local vTmp.TVector = Null
Local vTmp2.TVector = Null
vCam\X = EntityX(cCamera, 1)
vCam\Y = EntityY(cCamera, 1)
vCam\Z = EntityZ(cCamera, 1)
For TL.Tradelane = Each Tradelane
; Rings
TList_Reset(TL\RingsTop):TList_Reset(TL\RingsInnerTop)
TList_Reset(TL\RingsBot):TList_Reset(TL\RingsInnerBot)
TList_Reset(TL\Gates)
While TList_HasNext(TL\Gates)
Local RT = TList_Next(TL\RingsTop)
Local RTI = TList_Next(TL\RingsInnerTop)
Local RB = TList_Next(TL\RingsBot)
Local RBI = TList_Next(TL\RingsInnerBot)
Local Gate = TList_Next(TL\Gates)
TurnEntity RT, 0, 0, -.1
TurnEntity RB, 0, 0, .1
vGate\X = EntityX(Gate, 1)
vGate\Y = EntityY(Gate, 1)
vGate\Z = EntityZ(Gate, 1)
vTmp = TVector_Subtract(vGate, vCam)
vTmp2 = TVector_Normalize(vTmp):Delete vTmp
Local Dot# = TVector_Dot(TL\Dir, vTmp2):Delete vTmp2
If Dot >= 0 Then
EntityColor RT, 64, 198, 255
EntityColor RB, 255, 0, 0
Else
EntityColor RB, 64, 198, 255
EntityColor RT, 255, 0, 0
EndIf
Wend
; Traveling
If EntityInOBB(TL\OBBa,pvShip)
AlignToVector pvShip, TL\Dir\X, TL\Dir\Y, TL\Dir\Z, 0, Tradelane_Force
ShipSpeedZ = (ShipSpeedZ * (1-Tradelane_SpeedForce)) + (Tradelane_Speed * Tradelane_SpeedForce)
TLxTST=1
EndIf
If EntityInOBB(TL\OBBB,pvShip)
AlignToVector pvShip, -TL\Dir\X, -TL\Dir\Y, -TL\Dir\Z, 0, Tradelane_Force
ShipSpeedZ = (ShipSpeedZ * (1-Tradelane_SpeedForce)) + (Tradelane_Speed * Tradelane_SpeedForce)
TLxTST=1
EndIf
Next
Delete vCam:Delete vGate
PositionTexture StarBTex, Sin(MilliSecs() / 10000.0), (MilliSecs() / 10000.0) Mod 1
End Function
;~IDEal Editor Parameters:
+51
View File
@@ -0,0 +1,51 @@
Type TrueMotion
Field Camera% = 0
Field Mesh% = 0
End Type
Function TrueMotion_Create.TrueMotion(Camera%)
;Create TrueMotion Instance
tInstance.TrueMotion = New TrueMotion
; Camera can't be Null or invalid
If Camera = 0 Then
RuntimeError "TrueMotion: Camera is Null."
Else
If EntityClass(Camera) <> "Camera" Then
RuntimeError "TrueMotion: Camera is not of type <Camera>."
Else
tInstance\Camera = Camera
EndIf
EndIf
; Create Mesh
tInstance\Mesh = CreateMesh(tInstance\Camera)
sSurface = CreateSurface(tInstance\Mesh)
AddVertex(sSurface, -1, 1, 0, 0, 0)
AddVertex(sSurface, 1, 1, 0, 1, 0)
AddVertex(sSurface, 1, -1, 0, 1, 1)
AddVertex(sSurface, -1, -1, 0, 0, 1)
AddTriangle(sSurface, 0, 1, 2)
AddTriangle(sSurface, 0, 2, 3)
EntityOrder(tInstance\Mesh, -1)
EntityColor(tInstance\Mesh, 0, 0, 0)
PositionEntity(tInstance\Mesh, 0, 0, 1)
HideEntity(tInstance\Mesh)
Return tInstance
End Function
; Call this before after you have done your changes. It is a good practice to only let this effect affect nearby entities.
Function TrueMotion_RenderWorld(tInstance.TrueMotion, Steps%=12)
ShowEntity(tInstance\Mesh)
EntityAlpha(tInstance\Mesh, 1.0/Steps)
CameraClsMode(tInstance\Camera, 0, 1)
For curStep = 0 To Steps - 1
RenderWorld curStep/Float(Steps)
Next
HideEntity(tInstance\Mesh)
RenderWorld 1
CameraClsMode(tInstance\Camera, 1, 1)
CaptureWorld
End Function
+161
View File
@@ -0,0 +1,161 @@
;VectorMath.bb
Type TVector
Field X#,Y#,Z#
End Type
Global VectorForward.TVector = TVector_Create( 0, 0, 1)
Global VectorBackward.TVector = TVector_Create( 0, 0, -1)
Global VectorLeft.TVector = TVector_Create(-1, 0, 0)
Global VectorRight.TVector = TVector_Create( 1, 0, 0)
Global VectorUp.TVector = TVector_Create( 0, 1, 0)
Global VectorDown.TVector = TVector_Create( 0, -1, 0)
Function TVector_Create.TVector(X#,Y#,Z#)
Local R.TVector = New TVector
R\X = X
R\Y = Y
R\Z = Z
Return R
End Function
Function TVector_Copy.TVector(A.TVector)
Return TVector_Create(A\X,A\Y,A\Z)
End Function
Function TVector_Add.TVector(A.TVector, B.TVector)
Local R.TVector = New TVector
R\X = A\X + B\X
R\Y = A\Y + B\Y
R\Z = A\Z + B\Z
Return R
End Function
Function TVector_AddScalar.TVector(A.TVector, B#)
Local R.TVector = New TVector
R\X = A\X + B
R\Y = A\Y + B
R\Z = A\Z + B
Return R
End Function
Function TVector_Subtract.TVector(A.TVector, B.TVector)
Local R.TVector = New TVector
R\X = A\X - B\X
R\Y = A\Y - B\Y
R\Z = A\Z - B\Z
Return R
End Function
Function TVector_SubtractScalar.TVector(A.TVector, B#)
Local R.TVector = New TVector
R\X = A\X - B
R\Y = A\Y - B
R\Z = A\Z - B
Return R
End Function
Function TVector_Multiply.TVector(A.TVector, B.TVector)
Local R.TVector = New TVector
R\X = A\X * B\X
R\Y = A\Y * B\Y
R\Z = A\Z * B\Z
Return R
End Function
Function TVector_MultiplyScalar.TVector(A.TVector, B#)
Local R.TVector = New TVector
R\X = A\X * B
R\Y = A\Y * B
R\Z = A\Z * B
Return R
End Function
Function TVector_Divide.TVector(A.TVector, B.TVector)
Local R.TVector = New TVector
R\X = A\X / B\X
R\Y = A\Y / B\Y
R\Z = A\Z / B\Z
Return R
End Function
Function TVector_DivideScalar.TVector(A.TVector, B#)
Local R.TVector = New TVector
R\X = A\X / B
R\Y = A\Y / B
R\Z = A\Z / B
Return R
End Function
Function TVector_Normalize.TVector(A.TVector, MultiPass%=True)
Local R1.TVector, R.TVector
R = TVector_DivideScalar(A, TVector_Length(A))
If MultiPass Then
R1 = R
R = TVector_DivideScalar(R1, TVector_Length(R1))
Delete R1
EndIf
Return R
End Function
Function TVector_Rotate.TVector(A.TVector, Pitch#, Yaw#, Roll#)
Local M1.TVector = TVector_Create(Cos(Roll) * Cos(Yaw), -Sin(Roll), Sin(Yaw))
Local M2.TVector = TVector_Create(Sin(Roll), Cos(Roll) * Cos(Pitch), -Sin(Pitch))
Local M3.TVector = TVector_Create(-Sin(Yaw), Sin(Pitch), Cos(Yaw) * Cos(Pitch))
Local R.TVector = New TVector
R\X = (A\X * M1\X) + (A\Y * M1\Y) + (A\Z * M1\Z)
R\Y = (A\X * M2\X) + (A\Y * M2\Y) + (A\Z * M2\Z)
R\Z = (A\X * M3\X) + (A\Y * M3\Y) + (A\Z * M3\Z)
Delete M1:Delete M2:Delete M3:Return R
End Function
Function TVector_RotateAround.TVector(A.TVector, B.TVector, Pitch#, Yaw#, Roll#)
Local R1.TVector = TVector_Subtract(A, B)
Local R2.TVector = TVector_Rotate(R1, Pitch, Yaw, Roll)
Local R3.TVector = TVector_Add(R2, B)
Delete R1:Delete R2:Return R3
End Function
Function TVector_RotateAroundScalar.TVector(A.TVector, X#, Y#, Z#, Pitch#, Yaw#, Roll#)
Local B.TVector = TVector_Create(X,Y,Z)
Local R.TVector = TVector_RotateAround(A, B, Pitch, Yaw, Roll)
Delete B:Return R
End Function
Function TVector_Dot#(A.TVector, B.TVector)
Return ((A\X*B\X)+(A\Y*B\Y)+(A\Z*B\Z))
End Function
Function TVector_Cross.TVector(A.TVector, B.TVector)
Local R.TVector = New TVector
R\X = (A\Y*B\Z) - (A\Z*B\Y)
R\Y = (A\Z*B\X) - (A\X*B\Z)
R\Z = (A\X*B\Y) - (A\Y*B\X)
Return R
End Function
Global TVector_Pitch#, TVector_Yaw#
Function TVector_Angle(A.TVector) ; X
TVector_Pitch = VectorPitch(A\X, A\Y, A\Z);-ATan2(A\Y, Sqr((A\X*A\X) + (A\Z*A\Z))) + 90
TVector_Yaw# = VectorYaw(A\X, A\Y, A\Z);ATan2(A\Z, A\X) - 90
End Function
Function TVector_PitchFrom#(A.TVector, B.TVector) ; X
;Return ATan2(A\Y-B\Y, A\Z-B\Z)
Return VectorPitch(A\X-B\X, A\Y-B\Y, A\Z-B\Z)
End Function
Function TVector_YawFrom#(A.TVector, B.TVector) ; Y
;Return ATan2(A\Z-B\Z, A\X-B\X)
Return VectorYaw(A\X-B\X, A\Y-B\Y, A\Z-B\Z)
End Function
;Function TVector_RollFrom#(A.TVector, B.TVector) ; Z
; Return ATan2(A\Y-B\Y, A\X-B\X)
;End Function
Function TVector_Length#(A.TVector)
Return Sqr((A\X*A\X)+(A\Y*A\Y)+(A\Z*A\Z))
End Function
Function TVector_Distance#(A.TVector, B.TVector)
Local X# = (A\X-B\X)
Local Y# = (A\Y-B\Y)
Local Z# = (A\Z-B\Z)
Return Sqr(X*X+Y*Y+Z*Z)
End Function
Function TVector_ToString$(A.TVector)
Return "{X:"+A\X+";Y:"+A\Y+";Z:"+A\Z+"}"
End Function
;~IDEal Editor Parameters:
;~C#Blitz3D
@@ -0,0 +1,8 @@
Sirius Online Inventory
=======================
This was ment to be in the Sirius Online project, but the lead devloper never got further than complaining. So it has the side-effect of not working.I planned to optimize it to use as little memory and network bandwidth as possible, but the project was abandoned before I could go that far. Right now, it probably doesn't even work.
License
=======
Sirius Online Inventory by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
@@ -0,0 +1,407 @@
;----------------------------------------------------------------
;-- Constants
;----------------------------------------------------------------
Const ITEM_MAXIMUMID = 65535
; Item Classes
Const ITEM_CLASS_WEAPON = 1
Const ITEM_CLASS_SHIELD = 2
Const ITEM_CLASS_ARMOR = 3
Const ITEM_CLASS_ENGINE = 4
Const ITEM_CLASS_POWERCORE = 5
Const ITEM_CLASS_RESOURCE = 6
Const ITEM_CLASS_UPGRADE = 7
Const ITEM_CLASS_MININGMODULE = 8
Const ITEM_CLASS_ELITIUM = 255
; Return Codes
Const INVENTORY_RC_OK = 0
Const INVENTORY_RC_INVALIDID = -1
Const INVENTORY_RC_INVALIDAMOUNT = -2
Const INVENTORY_RC_UNKNOWNITEM = -3
Const INVENTORY_RC_ITEMTOOBIG = -4
Const INVENTORY_RC_ITEMNOTFOUND = -5
;----------------------------------------------------------------
;-- Types
;----------------------------------------------------------------
; Item Definition
Type TItem
Field ID%
Field Name$ ; Name of the Item
Field Description$ ; Description of the Item
Field Image ; Handle of the Image for the Item
Field Size% ; Size in cubic decimeters. Divide by 1000 to get the size in cube meters, which is displayed.
Field Rarity% ; Rarity
Field Class% ; Class of the Item.
Field AttributeID0%
Field AttributeID1%
Field AttributeID2%
Field AttributeID3%
; Attributes for Class: Weapon
; - Short/255 Electric Damage (Attribute 0 High)
; - Short/255 Physical Damage (Attribute 0 Low)
; - Short/255 Rate of Fire (Attribute 1 High)
; - Short Energy (Attribute 3 High)
; - Short/255 CPU (Attribute 3 Low)
; Attributes for Class: Shield
; - Int Shield Maximum (Attribute 0)
; - Short/255 Electric Resist (Attribute 1 High)
; - Short/255 Physical Resist (Attribute 1 Low)
; - Short Recharge Amount (Attribute 2 High)
; - Short Recharge Rate (Attribute 2 Low)
; - Short/255 CPU (Attribute 3 Low)
; Attributes for Class: Armor
; - Int Armor Maximum (Attribute 0)
; - Short/255 Speed Modifier (Attribute 1 High)
; - Short/255 Turn Modifier (Attribute 1 Low)
; - Short/255 Signature Mod. (Attribute 2 High)
; Attributes for Class: Engine
; - Short/255 Maximum Speed (Attribute 0 High)
; - Short/255 Maximum Boost (Attribute 0 Low)
; - Short Trace Type (Attribute 2 High)
; - Short/255 Trace Threshold (Attribute 2 Low)
; - Short Energy (Attribute 3 High)
; - Short/255 CPU (Attribute 3 Low)
; Attributes for Class: PowerCore
; - Int Energy Maximum (Attribute 0)
; - Short Energy Amount (Attribute 1 High)
; - Short Energy Rate (Attribute 1 Low)
; - Byte Elec. Signature (Attribute 2 High 1)
; - Byte Scramble Str. (Attribute 2 High 0)
; - Short/255 CPU (Attribute 3 Low)
; Attributes for Class: Resource
; - Byte Processing Tier (Attribute 0 Low 1)
; - Byte Load Type (Attribute 0 Low 0)
; - Int Half-life Time (Attribute 3)
; Attributes for Class: Upgrade
; - Byte/127 Armor Bonus (Attribute 0 High 1)
; - Byte/127 Shield Bonus (Attribute 0 High 0)
; - Byte/127 Speed Bonus (Attribute 0 Low 1)
; - Byte/127 Cargo Bonus (Attribute 0 Low 0)
; - Byte/127 Elec. Sig. Mod. (Attribute 1 High 1)
; - Byte/127 Grav. Sig. Mod. (Attribute 1 High 0)
; - Byte/127 Elec. Dmg. Mod. (Attribute 1 Low 1)
; - Byte/127 Phys. Dmg. Mod. (Attribute 1 Low 0)
; - Byte/127 El. ShRes Mod. (Attribute 2 High 1)
; - Byte/127 Ph. ShRes Mod. (Attribute 2 High 0)
; - Byte/127 El. ArRes Mod. (Attribute 2 Low 1)
; - Byte/127 Ph. ArRes Mod. (Attribute 2 Low 0)
; - Byte Scramble Str. (Attribute 3 High 1)
; - Byte/127 Yield Bonus (Attribute 3 High 0)
; - Byte Energy Max (Attribute 3 Low 1)
; - Byte/127 CPU Modifier (Attribute 3 Low 0)
; Attributes for Class: Mining Module
; -
; Attributes for Class: Elitium
; -
End Type
Dim Items.TItem(ITEM_MAXIMUMID)
; Inventory
Type TInventory
Field Size% ; Size in cubic meters. Divide by 1000 to get the size in cube meters, which is displayed.
Field Used% ; Used space in cubic decimeters. Divide by 1000 to get the size in cube meters, which is displayed.
; Array containing all Items using their ItemID as index.
Field Items.TInventoryItem[ITEM_MAXIMUMID]
End Type
Type TInventoryItem
Field Amount% ; How many of this Item are stored?
End Type
;----------------------------------------------------------------
;-- Functions
;----------------------------------------------------------------
; Create a new inventory.
Function TInventory_Create.TInventory(Size%)
If Size <= 0 Then RuntimeError "TInventory: Size is equal to or less than 0."
Local lInventory.TInventory = New TInventory
lInventory\Size = Size
lInventory\Used = 0
Return lInventory
End Function
; Safely destroy an existing inventory.
Function TInventory_Destroy(pInventory.TInventory)
If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist."
For lIndex = 0 To (ITEM_MAXIMUMID - 1)
If pInventory\Items[lIndex] <> Null Then
Delete pInventory\Items[lIndex]
pInventory\Items[lIndex] = Null
EndIf
Next
Delete pInventory
End Function
; Retrieve the amount of items in the inventory with the given ItemID.
Function TInventory_GetItemAmount(pInventory.TInventory, ItemID%)
If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist."
If ItemID >= 0 And ItemID < ITEM_MAXIMUMID Then
If Items(ItemID) <> Null Then
If pInventory\Items[ItemID] <> Null
Return pInventory\Items[ItemID]\Amount
Else
Return INVENTORY_RC_ITEMNOTFOUND
EndIf
Else
Return INVENTORY_RC_UNKNOWNITEM
EndIf
Else
Return INVENTORY_RC_INVALIDID
EndIf
End Function
; Set the amount of items in the inventory with the given ItemID.
Function TInventory_SetItemAmount(pInventory.TInventory, ItemID%, Amount%)
If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist."
If Amount < 0 Then Return INVENTORY_RC_INVALIDAMOUNT
If ItemID >= 0 And ItemID < ITEM_MAXIMUMID Then
If Items(ItemID) <> Null Then
; Remove current Amount and Size from Inventory
If pInventory\Items[ItemID] <> Null Then
pInventory\Used = pInventory\Used - (Items(ItemID)\Size * pInventory\Items[ItemID]\Amount)
If Amount = 0 Then
Delete pInventory\Items[ItemID]
pInventory\Items[ItemID] = Null
EndIf
EndIf
If Amount > 0
If pInventory\Items[ItemID] = Null pInventory\Items[ItemID] = New TInventoryItem
Local lAmount = Amount
If pInventory\Used + (Items(ItemID)\Size * lAmount) > PInventory\Size Then lAmount = (pInventory\Size - pInventory\Used) / Items(ItemID)\Size
pInventory\Items[ItemID]\Amount = lAmount
pInventory\Used = pInventory\Used + (Items(ItemID)\Size * lAmount)
Return lAmount
Else
Return INVENTORY_RC_OK
EndIf
If pInventory\Items[ItemID] <> Null Then lSize = lSize - (Items(ItemID)\Size * pInventory\Items[ItemID]\Amount)
Else
Return INVENTORY_RC_UNKNOWNITEM
EndIf
Else
Return INVENTORY_RC_INVALIDID
EndIf
End Function
; Add an item to the inventory.
; Returns the amount of items added or a negative value (error code)
Function TInventory_AddItem(pInventory.TInventory, ItemID%, Amount%=1)
If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist."
If Amount <= 0 Then Return INVENTORY_RC_INVALIDAMOUNT
If ItemID >= 0 And ItemID < ITEM_MAXIMUMID Then
If Items(ItemID ) <> Null Then
Local lAmount = Amount
If pInventory\Used + (lAmount * Items(ItemID)\Size) > pInventory\Size Then lAmount = (pInventory\Size - pInventory\Used) / Items(ItemID)\Size
If lAmount > 0 Then
If pInventory\Items[ItemID] = Null Then pInventory\Items[ItemID] = New TInventoryItem
pInventory\Items[ItemID]\Amount = pInventory\Items[ItemID]\Amount + lAmount
pInventory\Used = pInventory\Used + (lAmount * Items(ItemID)\Size)
EndIf
Return lAmount
Else
Return INVENTORY_RC_UNKNOWNITEM
EndIf
Else
Return INVENTORY_RC_INVALIDID
EndIf
End Function
; Remove an item from the inventory.
; Returns the amount of items removed or a negative value (error code).
Function TInventory_RemoveItem(pInventory.TInventory, ItemID%, Amount%=1)
If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist."
If Amount <= 0 Then Return INVENTORY_RC_INVALIDAMOUNT
If ItemID >= 0 And ItemID < ITEM_MAXIMUMID Then
If Items(ItemID) <> Null Then
If pInventory\Items[ItemID] <> Null Then
Local lAmount = pInventory\Items[ItemID]\Amount
pInventory\Items[ItemID]\Amount = pInventory\Items[ItemID]\Amount - Amount
If pInventory\Items[ItemID]\Amount <= 0 Then
pInventory\Used = pInventory\Used - (lAmount * Items(ItemID)\Size)
; Delete Item Entry (Reduces Memory Usage)
Delete pInventory\Items[ItemID]:pInventory\Items[ItemID] = Null
Return lAmount
Else
pInventory\Used = pInventory\Used - (Amount * Items(ItemID)\Size)
Return Amount
EndIf
Else
Return INVENTORY_RC_ITEMNOTFOUND
EndIf
Else
Return INVENTORY_RC_UNKNOWNITEM
EndIf
Else
Return INVENTORY_RC_INVALIDID
EndIf
End Function
; For when you edit the inventory without using the above functions.
Function TInventory_RecalculateUsedSpace(pInventory.TInventory)
If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist."
pInventory\Used = 0
For lIndex = 0 To (ITEM_MAXIMUMID - 1)
If Items(lIndex) <> Null And pInventory\Items[lIndex] <> Null Then
pInventory\Used = pInventory\Used + (pInventory\Items[lIndex]\Amount * Items(lIndex)\Size)
EndIf
Next
End Function
;----------------------------------------------------------------
;-- Extras - Require 'LinkedListEmulation.bb'!
;----------------------------------------------------------------
;Type TInventoryItemLink
; Field ItemID%
; Field Amount%
;End Type
;
; ; Retrieve a LinkedList containing all items in this inventory.
; ; The returned list must be deleted using TInventory_DeleteItemList(...).
; ; Modifications on this list can only be applied to the inventory using TInventory_SetItemList(...).
;Function TInventory_GetItemList.TList(pInventory.TInventory)
; If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist."
;
; Local lList.TList = TList_Create()
; For lIndex = 0 To (ITEM_MAXIMUMID - 1)
; If Items(lIndex) <> Null And pInventory\Items[lIndex] <> Null Then
; Local lInvItemLink.TInventoryItemLink = New TInventoryItemLink
; lInvItemLink\ItemID = lIndex
; lInvItemLink\Amount = pInventory\Items[lIndex]\Amount
; TList_AddLast(lInvItemLink)
; EndIf
; Next
;
; Return lList
;End Function
;
;Function TInventory_SetItemList(pInventory.TInventory, pList.TList)
; If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist."
; If pList = Null Then RuntimeError "TInventory: List does not exist."
;
; pInventory\Used = 0
; For lIndex = 0 To (ITEM_MAXIMUMID - 1)
; If Items(lIndex) <> Null And pInventory\Items[lIndex] <> Null Then
; Delete pInventory\Items[lIndex]
; pInventory\Items[lIndex] = Null
; EndIf
; Next
;
; Local lInvItemLink.TInventoryItemLink = Object.TInventoryItemLink(TList_First(pList))
; While lInvItemLink <> Null
; If lInvItemLink\ItemID >= 0 And lInvItemLink\ItemID < ITEM_MAXIMUMID Then
; If Items(lInvItemLink\ItemID) <> Null And lInvItemLink\Amount > 0 Then
; pInventory\Items[lInvItemLink\ItemID] = New TInventoryItem
; pInventory\Items[lInvItemLink\ItemID]\Amount = lInvItemLink\Amount
;
; pInventory\Used = pInventory\Used + (lInvItemLink\Amount * Items(lInvItemLink\ItemID)\Size)
; EndIf
; EndIf
; lInvItemLink = Object.TInventoryItemLink(TList_Next(pList))
; Wend
;End Function
;
;Function TInventory_DeleteItemList(pList.TList)
; If pList = Null Then RuntimeError "TInventory: List does not exist."
;
; Local lInvItemLink.TInventoryItemLink = Object.TInventoryItemLink(TList_First(pList))
; While lInvItemLink <> Null
; Delete lInvItemLink
; lInvItemLink = Object.TInventoryItemLink(TList_Delete(pList))
; Wend
;
; TList_Destroy(pList)
;End Function
;----------------------------------------------------------------
;-- Example
;----------------------------------------------------------------
SeedRnd(MilliSecs())
; Test Item
Items(0) = New TItem
Items(0)\Name = "1dm³ Item"
Items(0)\Description = ""
Items(0)\Size = 1
; Test Item
Items(1) = New TItem
Items(1)\Name = "10dm3 Item"
Items(1)\Description = ""
Items(1)\Size = 10
; Test Item
Items(2) = New TItem
Items(2)\Name = "100dm3 Item"
Items(2)\Description = ""
Items(2)\Size = 100
; Test Item
Items(3) = New TItem
Items(3)\Name = "1000dm3 Item"
Items(3)\Description = ""
Items(3)\Size = 1000
Local MyInv.TInventory = TInventory_Create(10000)
While Not KeyHit(1)
Cls
Locate 0,0
PrintInv(MyInv)
If Rand(0,1000) Mod 4 < 2
TInventory_AddItem(MyInv, Rand(0,3), Rand(0,100))
TInventory_RemoveItem(MyInv, Rand(0,3), Rand(0,100))
Else
TInventory_SetItemAmount(MyInv, Rand(0,3), Rand(0,100))
TInventory_SetItemAmount(MyInv, Rand(0,3), Rand(0,100))
EndIf
WaitKey()
Flip 0
Wend
TInventory_Destroy(MyInv)
End
Function PrintInv(Inv.TInventory)
Print "Inventory " + Handle(Inv)
Print " Size: " + (Inv\Size/1000) + "." + (Inv\Size Mod 1000) + ""
Print " Used: " + (Inv\Used/1000) + "." + (Inv\Used Mod 1000) + " m³ / " + Int((Inv\Used/Float(Inv\Size))*100) + "%"
Print " Remaining: " + ((Inv\Size - Inv\Used)/1000) + "." + ((Inv\Size - Inv\Used) Mod 1000) + " m³ / " + Int(((Inv\Size - Inv\Used)/Float(Inv\Size))*100) + "%"
Print " Items:"
For lIndex = 0 To (ITEM_MAXIMUMID - 1)
If Items(lIndex) <> Null And TInventory_GetItemAmount(Inv, lIndex) > 0 Then
Print " - " + Items(lIndex)\Name + " x" + TInventory_GetItemAmount(Inv, lIndex)
EndIf
Next
; Alternatively, using Extras
;Local lList.TList = TInventory_GetItemList(Inv)
;Local lEntry.TInventoryItemLink = Object.TInventoryItemLink(TList_First(lList))
;While lEntry <> Null
; Print " - " + Items(lEntry\ItemID)\Name + " x" + lEntry\Amount
; lEntry = Object.TInventoryItemLink(TList_Next(lList))
;Wend
;TInventory_DestroyItemList(lList)
End Function
@@ -0,0 +1,227 @@
;[Block] Rendering Functions
Global ERTPos#[2], ERTRot#[2]
Const ES_AxisX = 0, ES_AxisY = 1, ES_AxisZ = 2
;[End Block]
Function EntityRenderToImage(iCam, iEnt, iImg)
Local CP#[2], EP#[2], CR#[2], Buffer = GraphicsBuffer(), SX#, SY#, SZ#, Dist#, IW = ImageWidth(iImg), IH = ImageHeight(iImg), IB = ImageBuffer(iImg)
CP[0] = EntityX(iCam):CP[1] = EntityY(iCam):CP[2] = EntityZ(iCam)
CR[0] = EntityPitch(iCam):CR[1] = EntityYaw(iCam):CR[2] = EntityRoll(iCam)
EP[0] = EntityX(iEnt):EP[1] = EntityY(iEnt):EP[2] = EntityZ(iEnt)
SX = EntityScale(iEnt,ES_AxisX):SY = EntityScale(iEnt,ES_AxisY):SZ = EntityScale(iEnt,ES_AxisZ)
Dist# = Sqr((SX*SX)+(SY*SY)+(SZ*SZ))
PositionEntity iCam, ERTPos[0], ERTPos[1], ERTPos[2]
PositionEntity iEnt, ERTPos[0], ERTPos[1], ERTPos[2]+Dist
RotateEntity iCam, 0, 0, 0
EntityParent iEnt, iCam
RotateEntity iCam, ERTRot[0], ERTRot[1], ERTRot[2]
CameraViewport iCam, 0, 0, IW, IH
RenderWorld
CopyRect 0,0,IW,IH,0,0,Buffer,IB
CameraViewport iCam, 0, 0, GraphicsWidth(), GraphicsHeight()
RotateEntity iCam, 0, 0, 0
EntityParent iEnt, 0
PositionEntity iCam, CP[0],CP[1],CP[2]
PositionEntity iEnt, EP[0],EP[1],EP[2]
RotateEntity iCam, CR[0],CR[1],CR[2]
End Function
Function EntityRenderToTexture(iCam, iEnt, iTex)
Local CP#[2], EP#[2], CR#[2], Buffer = GraphicsBuffer(), SX#, SY#, SZ#, Dist#, IW = TextureWidth(iTex), IH = TextureHeight(iTex), IB = TextureBuffer(iTex)
CP[0] = EntityX(iCam):CP[1] = EntityY(iCam):CP[2] = EntityZ(iCam)
CR[0] = EntityPitch(iCam):CR[1] = EntityYaw(iCam):CR[2] = EntityRoll(iCam)
EP[0] = EntityX(iEnt):EP[1] = EntityY(iEnt):EP[2] = EntityZ(iEnt)
SX = EntityScale(iEnt,ES_AxisX):SY = EntityScale(iEnt,ES_AxisY):SZ = EntityScale(iEnt,ES_AxisZ)
Dist# = Sqr((SX*SX)+(SY*SY)+(SZ*SZ))*0.25 + Sqr(Sqr((SX*SX)+(SY*SY)+(SZ*SZ)))*0.75
PositionEntity iCam, ERTPos[0], ERTPos[1], ERTPos[2]
PositionEntity iEnt, ERTPos[0], ERTPos[1], ERTPos[2]+Dist
RotateEntity iCam, 0, 0, 0
EntityParent iEnt, iCam
RotateEntity iCam, ERTRot[0], ERTRot[1], ERTRot[2]
CameraViewport iCam, 0, 0, IW, IH
;SetBuffer IB ;FastEXT only
RenderWorld
CopyRect 0,0,IW,IH,0,0,Buffer,IB
CameraViewport iCam, 0, 0, GraphicsWidth(), GraphicsHeight()
;SetBuffer Buffer ;FastEXT only
RotateEntity iCam, 0, 0, 0
EntityParent iEnt, 0
PositionEntity iCam, CP[0],CP[1],CP[2]
PositionEntity iEnt, EP[0],EP[1],EP[2]
RotateEntity iCam, CR[0],CR[1],CR[2]
End Function
Function EntityScale#( Entity, Axis )
VX# = GetMatElement( Entity, Axis, 0 )
VY# = GetMatElement( Entity, Axis, 1 )
VZ# = GetMatElement( Entity, Axis, 2 )
Return Sqr( VX#*VX# + VY#*VY# + VZ#*VZ# )
End Function
;[Block] Math Functions
Global HSV#[2], RGB#[2]
;[End Block]
Function Math_MaxMin#(Value#, Max#, Min#)
If Value> Max Then Return Max
If Value < Min Then Return Min
Return Value
End Function
Function Math_Max#(Value#, Max#)
If Value> Max Then Return Max
Return Value
End Function
Function Math_Min#(Value#, Min#)
If Value < Min Then Return Min
Return Value
End Function
Function Math_Clip#(Value#, Low#, High#)
Local Out#, Diff#
Diff = High-Low:Out = Value-Low
If (Out >= Diff) Then Out = Out - Floor(Out/Diff)*Diff
If (Out < 0) Then Out = Out - Floor(Out/Diff)*Diff
Return Low+Out
End Function
Function Math_RGBHSV(R,G,B)
Local maxC#, minC#, delta#, dr#, dg#, db#
R = R/255.0:G = G/255.0:B = B/255.0
maxC = Math_Min(Math_Min(R,G),B)
minC = Math_Max(Math_Max(R,G),B)
delta = maxC - minC
HSV[0] = 0:HSV[1] = 0:HSV[2] = maxC
If delta = 0
HSV[0] = 0:HSV[1] = 0
Else
HSV[1] = delta / maxC
dr = 60*(maxC - R)/delta + 180
dg = 60*(maxC - G)/delta + 180
db = 60*(maxC - B)/delta + 180
If R = maxC
HSV[0] = db - dg
ElseIf G = maxC
HSV[0] = 120 + dr - db
Else
HSV[0] = 240 + dg - dr
EndIf
EndIf
HSV[0] = Math_Clp(HSV[0],0,360)
End Function
Function Math_HSVRGB(H#,S#,V#)
Local m#, n#, f#, i
H = Math_Clp(H,0,360)/60.0
If H = S And S = 0
RGB[0] = V
RGB[1] = V
RGB[2] = V
EndIf
i = Floor(H)
f = H - i
If Not (i Mod 2) Then f = 1 - f
m = V * (1-S)
n = V * (1-S*f)
Select i
Case 6,0
RGB[0] = V*255
RGB[1] = n*255
RGB[2] = m*255
Case 1
RGB[0] = n*255
RGB[1] = V*255
RGB[2] = m*255
Case 2
RGB[0] = m*255
RGB[1] = V*255
RGB[2] = n*255
Case 3
RGB[0] = m*255
RGB[1] = n*255
RGB[2] = V*255
Case 4
RGB[0] = n*255
RGB[1] = m*255
RGB[2] = V*255
Case 5
RGB[0] = V*255
RGB[1] = m*255
RGB[2] = n*255
End Select
End Function
;[Block] String Functions
Dim SplittedString$(1)
Global SplitCount
;[End Block]
Function SplitString(In$, StringSplitter$ = "|")
Local InLength% = Len(In)
Local SplitLength% = Len(StringSplitter)
Local CountPos%, InPos%, SplitIndex%
Local SplitTest$, LineText$
; Count how many Lines there are and resize Dim.
SplitCount = 0
For CountPos = 1 To InLength-(SplitLength-1)
SplitTest = Mid(In,CountPos,1)
If SplitTest = StringSplitter Then SplitCount = SplitCount + 1
Next
Dim SplittedString(SplitCount)
; Split the Text onto multiple lines.
While Not InPos = Len(In)
; Increment Position
InPos = InPos + 1
; Grab a piece of the text.
SplitTest = Mid(In, InPos, SplitLength)
Local Char$ = Left(SplitTest, 1)
; Check if the current Text matches the splitter or if we are near the end.
If SplitTest = StringSplitter Or InPos = InLength
; Append the current character if it doesn't match the Splitter.
If InPos = InLength And SplitTest <> StringSplitter Then LineText = LineText + Char
; Store the Line.
SplittedString(SplitIndex) = LineText
; Increment split index.
SplitIndex = SplitIndex + 1
; Reset LineText
LineText = ""
Else
LineText = LineText + Char
EndIf
Wend
End Function
Function SafeText$(sText$)
Local sSafeText$ = sText
For i = 0 To 31
sSafeText = Replace(sSafeText,Chr(i),"["+i+"]")
Next
Return sSafeText
End Function
Function Replace$(S$,F$,T$,CaseSensitive=0)
Local LF = Len(F), Pos
Pos = 1
While Not Pos > Len(S)-LF+1
Local Check$ = Mid(S,Pos,LF)
If Lower(F) = Lower(Check) And (F = Check Or CaseSensitive=0)
S = Left(S,Pos-1)+T+Mid(S,Pos+LF,-1)
Pos = Pos + Len(T)
EndIf
Pos = Pos + 1
Wend
Return S
End Function
@@ -0,0 +1,9 @@
HelpersAndFixes
=======================
A try at adding features to BlitzBasic that didn't exist, without touching C++ or manipulating the DLL file using reverse engineering. Worked quite well, though obviously slower than native code.
Documentation at: http://www.blitzforum.de/forum/viewtopic.php?p=374655#374655
License
=======
HelpersAndFixes by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
@@ -0,0 +1,282 @@
Const CfgMeshToRender$ = "D:\Projekte\Blitz3D\Sirius\GFX\ENV\VINxROIDx001.3ds"
Const CfgDiffuseMap$ = "D:\Projekte\Blitz3D\Sirius\GFX\ENV\VINxROIDx001DIFF.png"
Const CfgDiffuseFlags% = (1+256+512)
Const CfgNormalMap$ = "D:\Projekte\Blitz3D\Sirius\GFX\ENV\VINxROIDx001NORM.png"
Const CfgNormalFlags = (1+256+512)
Const CfgFrameSizeX = 128
Const CfgFrameSizeY = 128
Const CfgPitchMin# = -90
Const CfgPitchMax# = 90
Const CfgPitchFrames = 5
Const CfgYawMin# = 0
Const CfgYawMax# = 360
Const CfgYawFrames = 16
Const CfgDistance# = 120
; Includes
Include "FreeImage.bb"
Include "FastExt.bb"
Include "../Advanced Text (Library)/AdvText.bb"
Include "Impostor.bb"
; Set up 3D Scene
Graphics3D 1024, 1024, 32, 2:InitExt()
SetBuffer_ BackBuffer()
; Set up Camera
Global CameraPivot = CreatePivot()
Global Camera = CreateCamera(CameraPivot)
MoveEntity Camera, 0, 0, -CfgDistance
AmbientLight 255, 255, 255
; Set up Impostor data
Local ImpostorMesh% = LoadMesh(CfgMeshToRender)
Local ImpostorDiffuse% = LoadTexture(CfgDiffuseMap, CfgDiffuseFlags)
Local ImpostorNormal% = LoadTexture(CfgNormalMap, CfgNormalFlags)
; Set up final image
Local DiffuseSheet% = CreateImage(CfgFrameSizeX, CfgFrameSizeY, CfgYawFrames * CfgPitchFrames)
Local NormalSheet% = CreateImage(CfgFrameSizeX, CfgFrameSizeY, CfgYawFrames * CfgPitchFrames)
; Set up render target
;Const RTSize% = 2048
Local RenderTarget% = CreateTexture(CfgFrameSizeX, CfgFrameSizeY, 1+256+FE_RENDER+FE_ZRENDER)
CameraViewport Camera, 0, 0, CfgFrameSizeX, CfgFrameSizeY
; Render
SetBuffer TextureBuffer(RenderTarget)
Local YawStep# = (CfgYawMax - CfgYawMin) / CfgYawFrames
Local PitchStep# = (CfgPitchMax - CfgPitchMin) / CfgPitchFrames
Local Yaw, Pitch
For Yaw = 0 To CfgYawFrames - 1
Local RealYaw# = CfgYawMin + (YawStep * Yaw)
For Pitch = 0 To CfgPitchFrames - 1
Local RealPitch# = CfgPitchMin + (PitchStep * Pitch)
Local Frame = Pitch * CfgYawFrames + Yaw
RotateEntity CameraPivot, RealPitch, RealYaw, 0, 1
; Render Diffuse
Cls:EntityTexture ImpostorMesh, ImpostorDiffuse:RenderWorld:CopyRectStretch(0, 0, CfgFrameSizeX, CfgFrameSizeY, 0, 0, CfgFrameSizeX, CfgFrameSizeY, TextureBuffer(RenderTarget), ImageBuffer(DiffuseSheet, Frame))
; Render Normal
Cls:EntityTexture ImpostorMesh, ImpostorNormal:RenderWorld:CopyRectStretch(0, 0, CfgFrameSizeX, CfgFrameSizeY, 0, 0, CfgFrameSizeX, CfgFrameSizeY, TextureBuffer(RenderTarget), ImageBuffer(NormalSheet, Frame))
Next
Next
SetBuffer BackBuffer()
FreeTexture RenderTarget
Local Stream = WriteFile("Preview.imp")
WriteShort Stream, CfgFrameSizeX
WriteShort Stream, CfgFrameSizeY
WriteByte Stream, CfgPitchFrames
WriteFloat Stream, CfgPitchMin
WriteFloat Stream, CfgPitchMax
WriteByte Stream, CfgYawFrames
WriteFloat Stream, CfgYawMin
WriteFloat Stream, CfgYawMax
CloseFile(Stream)
Stream = WriteFile("PreviewNormal.imp")
WriteShort Stream, CfgFrameSizeX
WriteShort Stream, CfgFrameSizeY
WriteByte Stream, CfgPitchFrames
WriteFloat Stream, CfgPitchMin
WriteFloat Stream, CfgPitchMax
WriteByte Stream, CfgYawFrames
WriteFloat Stream, CfgYawMin
WriteFloat Stream, CfgYawMax
CloseFile(Stream)
Function SaveAnimImageSheet(Image%, File$, FramesX%, FramesY%)
Local x, y, img = CreateImage(ImageWidth(Image) * FramesX, ImageHeight(Image) * FramesY)
For x = 0 To FramesX - 1
For y = 0 To FramesY - 1
Local frame = y * FramesX + x
CopyRect 0, 0, ImageWidth(Image), ImageHeight(Image), x * ImageWidth(Image), y * ImageHeight(Image), ImageBuffer(Image, frame), ImageBuffer(img)
Next
Next
FiSaveImage(img, File)
End Function
SaveAnimImageSheet(DiffuseSheet, "Preview.png", CfgYawFrames, CfgPitchFrames)
SaveAnimImageSheet(NormalSheet, "PreviewNormal.png", CfgYawFrames, CfgPitchFrames)
Global ControlHelp1$
ControlHelp1$ = ControlHelp1$ + "Controls:" + Chr(10)
ControlHelp1$ = ControlHelp1$ + Chr(9) + "1 - Mode: Draw Sheet" + Chr(10)
ControlHelp1$ = ControlHelp1$ + Chr(9) + "2 - Mode: Draw Frame" + Chr(10)
ControlHelp1$ = ControlHelp1$ + Chr(9) + "3 - Mode: 3D Preview" + Chr(10)
Global ControlHelp2$
ControlHelp2$ = ControlHelp2$ + "Sheet Mode Controls:" + Chr(10)
ControlHelp2$ = ControlHelp2$ + Chr(9) + "Q - Sheet: Diffuse" + Chr(10)
ControlHelp2$ = ControlHelp2$ + Chr(9) + "W - Sheet: Normal" + Chr(10)
Global ControlHelp3$
ControlHelp3$ = ControlHelp3$ + "Frame Mode Controls:" + Chr(10)
ControlHelp3$ = ControlHelp3$ + Chr(9) + "Q - Sheet: Diffuse" + Chr(10)
ControlHelp3$ = ControlHelp3$ + Chr(9) + "W - Sheet: Normal" + Chr(10)
ControlHelp3$ = ControlHelp3$ + Chr(9) + "A - Previous Frame" + Chr(10)
ControlHelp3$ = ControlHelp3$ + Chr(9) + "D - Next Frame" + Chr(10)
Global ControlHelp4$
ControlHelp4$ = ControlHelp4$ + "3D Mode Controls:" + Chr(10)
ControlHelp4$ = ControlHelp4$ + Chr(9) + "Q - Sheet: Diffuse" + Chr(10)
ControlHelp4$ = ControlHelp4$ + Chr(9) + "W - Sheet: Normal" + Chr(10)
ControlHelp4$ = ControlHelp4$ + Chr(9) + "Mouse - Rotate Camera" + Chr(10)
Local Timer = CreateTimer(30)
Const DrawModeSheet% = 0
Const DrawModeFrame% = 1
Const DrawMode3D% = 2
Local DrawMode% = DrawModeSheet
Local ModeSheet_Image% = DiffuseSheet
Local ModeSheet_XOff% = 0
Local ModeSheet_YOff% = 0
Local ModeFrame_Image% = DiffuseSheet
Local ModeFrame_Frame% = 0
Local Mode3D_DiffImp.Impostor = Impostor_Load("Preview.imp")
Local Mode3D_NormImp.Impostor = Impostor_Load("PreviewNormal.imp")
Local Mode3D_Pitch# = 0
Local Mode3D_Yaw# = 0
Local Mode3D_Pivot = CreatePivot()
Local Mode3D_Camera = CreateCamera(Mode3D_Pivot)
MoveEntity Mode3D_Camera, 0, 0, -100
EntityTexture ImpostorMesh, ImpostorDiffuse:HideEntity Mode3D_NormImp\Pivot
CameraViewport Camera, 0, 256, 512, 512
CameraViewport Mode3D_Camera, 512, 256, 512, 512
MoveEntity Mode3D_DiffImp\Mesh, 1000, 0, 0
MoveEntity Mode3D_NormImp\Mesh, 1000, 0, 0
ScaleEntity Mode3D_DiffImp\Mesh, CfgDistance, CfgDistance, 1
ScaleEntity Mode3D_NormImp\Mesh, CfgDistance, CfgDistance, 1
MoveEntity Mode3D_Pivot, 1000, 0, 0
CameraRange Camera, 0.1, 500
CameraRange Mode3D_Camera, 0.1, 500
;Local tc = CreateCube(Mode3D_Pivot)
EntityTexture Mode3D_DiffImp\Mesh, Mode3D_DiffImp\Sheet, 0, 0
While Not KeyHit(1)
Cls
; 3D - Render
If DrawMode = DrawMode3D
Impostor_Update(Mode3D_Camera)
;EntityTexture Mode3D_DiffImp\Mesh, Mode3D_DiffImp\Sheet, 0, 0
WireFrame KeyDown(57)
RenderWorld
EndIf
; 2D - Rener
AdvText 0, 0, ControlHelp1, 0, 0, 1
; Show Mode specific data.
Select DrawMode
Case DrawModeSheet
; Control
If MouseDown(1) And MouseHit(1) Then
MoveMouse MouseX(), MouseY()
ElseIf MouseDown(1)
ModeSheet_XOff = ModeSheet_XOff + MouseXSpeed()
ModeSheet_YOff = ModeSheet_YOff + MouseYSpeed()
EndIf
If KeyHit(16) Then ModeSheet_Image = DiffuseSheet
If KeyHit(17) Then ModeSheet_Image = NormalSheet
; Render
Local rw = ImageWidth(ModeSheet_Image) * CfgYawFrames
Local rh = ImageHeight(ModeSheet_Image) * CfgPitchFrames
For p = 0 To CfgPitchFrames - 1
For y = 0 To CfgYawFrames - 1
DrawImage ModeSheet_Image, GraphicsWidth() / 2 - rw / 2 + ModeSheet_XOff + ImageWidth(ModeSheet_Image) * y, GraphicsHeight() / 2 - rh / 2 + ModeSheet_YOff + ImageHeight(ModeSheet_Image) * p, y + p * CfgYawFrames
Next
Next
; Show Help
AdvText 0, 50, ControlHelp2, 0, 0, 1
Case DrawModeFrame
; Control
If KeyHit(16) Then ModeFrame_Image = DiffuseSheet
If KeyHit(17) Then ModeFrame_Image = NormalSheet
If KeyHit(30) Then ModeFrame_Frame = ModeFrame_Frame - 1
If KeyHit(32) Then ModeFrame_Frame = ModeFrame_Frame + 1
If ModeFrame_Frame < 0 Then ModeFrame_Frame = CfgPitchFrames * CfgYawFrames - 1
If ModeFrame_Frame = (CfgPitchFrames * CfgYawFrames) Then ModeFrame_Frame = 0
; Render
DrawImage ModeFrame_Image, GraphicsWidth() / 2 - ImageWidth(ModeFrame_Image) / 2, GraphicsHeight() / 2 - ImageHeight(ModeFrame_Image) / 2, ModeFrame_Frame
; Show Help
AdvText 0, 50, ControlHelp3, 0, 0, 1
Case DrawMode3D
; Control
If KeyHit(16) Then
HideEntity Mode3D_NormImp\Pivot
ShowEntity Mode3D_DiffImp\Pivot
EntityTexture ImpostorMesh, ImpostorDiffuse
EndIf
If KeyHit(17) Then
ShowEntity Mode3D_NormImp\Pivot
HideEntity Mode3D_DiffImp\Pivot
EntityTexture ImpostorMesh, ImpostorNormal
EndIf
If MouseDown(1) And MouseHit(1)
MoveMouse 512, 384
ElseIf MouseDown(1)
Mode3D_Pitch = Math_MaxMin(Mode3D_Pitch + MouseYSpeed() / 15.0, 90, -90)
Mode3D_Yaw = Mode3D_Yaw + MouseXSpeed() / 15.0
RotateEntity Mode3D_Pivot, Mode3D_Pitch, Mode3D_Yaw, 0, 1
RotateEntity CameraPivot, Mode3D_Pitch, Mode3D_Yaw, 0, 1
MoveMouse 512, 384
EndIf
If MouseDown(2) And MouseHit(2)
MoveMouse 512, 384
ElseIf MouseDown(2)
MoveEntity Mode3D_Camera, 0, 0, (MouseXSpeed() - MouseYSpeed()) / 15.0
MoveMouse 512, 384
EndIf
; Show Help
AdvText 0, 50, ControlHelp4, 0, 0, 1
End Select
; Switch Mode Hotkeys
If KeyHit(2) Then DrawMode = DrawModeSheet
If KeyHit(3) Then DrawMode = DrawModeFrame
If KeyHit(4) Then DrawMode = DrawMode3D
Flip 0
WaitTimer Timer
Wend
Function Math_MaxMin#(Value#, Max#, Min#)
If Value> Max Then Return Max
If Value < Min Then Return Min
Return Value
End Function
Function Math_Max#(Value#, Max#)
If Value> Max Then Return Max
Return Value
End Function
Function Math_Min#(Value#, Min#)
If Value < Min Then Return Min
Return Value
End Function
Function Math_Clip#(Value#, Low#, High#)
Local Out#, Diff#
Diff = High-Low:Out = Value-Low
If (Out >= Diff) Then Out = Out - Floor(Out/Diff)*Diff
If (Out < 0) Then Out = Out - Floor(Out/Diff)*Diff
Return Low+Out
End Function
;~IDEal Editor Parameters:
;~C#Blitz3D
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

@@ -0,0 +1,47 @@
Include "Impostor.bb"
Graphics3D 1024, 768, 32, 2
SetBuffer BackBuffer()
Local Timer = CreateTimer(60)
;Camera
Local CamPivot = CreatePivot()
Local Cam = CreateCamera(CamPivot)
MoveEntity Cam, 0, 0, -20
; Impostor
Local MyImp.Impostor = Impostor_Load("Cube.imp")
;EntityFX MyImp\Mesh, 16
MoveEntity MyImp\Mesh, 0, 0, 0
ScaleEntity MyImp\Mesh, 10, 10, 10
; Base Cube
Local Flr = CreateCube()
MoveEntity Flr, 0, -10, 0
ScaleEntity Flr, 10, .001, 10
EntityColor Flr, 51, 51, 51
While Not KeyHit(1)
Cls
WireFrame KeyDown(2)
If MouseDown(1) And MouseHit(1)
MoveMouse 512, 384
ElseIf MouseDown(1)
RotateEntity CamPivot, EntityPitch(CamPivot) + MouseYSpeed() / 15.0, EntityYaw(CamPivot) + MouseXSpeed() / 15.0, 0, 1
MoveMouse 512, 384
EndIf
If MouseDown(2) And MouseHit(2)
MoveMouse 512, 384
ElseIf MouseDown(2)
MoveEntity Cam, 0, 0, (MouseXSpeed() - MouseYSpeed()) / 15.0
MoveMouse 512, 384
EndIf
Impostor_Update(Cam)
RenderWorld
Flip 0:WaitTimer Timer
Wend
;~IDEal Editor Parameters:
;~C#Blitz3D
+496
View File
@@ -0,0 +1,496 @@
; Include file for FastExt v1.17 library
; (c) 2006-2010 created by MixailV aka Monster^Sage [monster-sage@mail.ru] http://www.fastlibs.com
Const FE_VERSION$ = "1.17"
; íîâûå êîíñòàíòû äëÿ ñîçäàíèÿ òåêñòóðû (ôóíêöèÿ CreateTexture)
; New constants for texture creating (CreateTexture function only)
Const FE_ExSIZE = 2048
Const FE_RENDER = 4096
Const FE_ZRENDER = 8192
; íîâûå êîíñòàíòû äëÿ FX ( ôóíêöèè EntityFX èëè BrushFX )
; New constants for brush Fx ( EntityFX or BrushFX functions only)
Const FE_WIRE = 64 ; ðèñóþòñÿ òîëüêî ëèíèè
Const FE_POINT = 128 ; ðèñóþòñÿ òîëüêî òî÷êè
; Êîíñòàíòû äëÿ ôóíêöèè RenderPostprocess
; RenderPostprocess function constants
Const FE_DOF = 1
Const FE_Glow = 2
Const FE_Blur = 4
Const FE_Inverse = 8
Const FE_Grayscale = 16
Const FE_Contrast = 32
Const FE_BlurDirectional = 64
Const FE_BlurZoom = 128
Const FE_BlurSpin = 256
Const FE_BlurMotion = 512
Const FE_Overlay = 1024
Const FE_Posterize = 2048
Const FE_Rays = 4096
; -------------------- DirectX7 constants (only for TextureBlendCustom function) -----------------------
; Control
Const D3DTOP_DISABLE = 1 ; disables stage
Const D3DTOP_SELECTARG1 = 2 ; the Default
Const D3DTOP_SELECTARG2 = 3
; Modulate
Const D3DTOP_MODULATE = 4 ; multiply args together
Const D3DTOP_MODULATE2X = 5 ; multiply And 1 bit
Const D3DTOP_MODULATE4X = 6 ; multiply And 2 bits
; Add
Const D3DTOP_ADD = 7 ; add arguments together
Const D3DTOP_ADDSIGNED = 8 ; add With -0.5 bias
Const D3DTOP_ADDSIGNED2X = 9 ; As above but left 1 bit
Const D3DTOP_SUBTRACT = 10 ; Arg1 - Arg2, With no saturation
Const D3DTOP_ADDSMOOTH = 11 ; add 2 args, subtract product Arg1 + Arg2 - Arg1*Arg2 = Arg1 + (1-Arg1)*Arg2
; Linear alpha blend: Arg1*(Alpha) + Arg2*(1-Alpha)
Const D3DTOP_BLENDDIFFUSEALPHA = 12 ; iterated alpha
Const D3DTOP_BLENDTEXTUREALPHA = 13 ; texture alpha
Const D3DTOP_BLENDFACTORALPHA = 14 ; alpha from D3DRENDERSTATE_TEXTUREFACTOR Linear alpha blend With pre-multiplied arg1 input: Arg1 + Arg2*(1-Alpha)
Const D3DTOP_BLENDTEXTUREALPHAPM = 15 ; texture alpha
Const D3DTOP_BLENDCURRENTALPHA = 16 ; by alpha of current color
; Specular mapping
Const D3DTOP_PREMODULATE = 17 ; modulate With Next texture before use
Const D3DTOP_MODULATEALPHA_ADDCOLOR = 18 ; Arg1.RGB + Arg1.A*Arg2.RGB COLOROP only
Const D3DTOP_MODULATECOLOR_ADDALPHA = 19 ; Arg1.RGB*Arg2.RGB + Arg1.A COLOROP only
Const D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20 ; (1-Arg1.A)*Arg2.RGB + Arg1.RGB COLOROP only
Const D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21 ; (1-Arg1.RGB)*Arg2.RGB + Arg1.A COLOROP only
; Bump mapping
Const D3DTOP_BUMPENVMAP = 22 ; per pixel env map perturbation
Const D3DTOP_BUMPENVMAPLUMINANCE = 23 ; With luminance channel
; This can do either diffuse Or specular bump mapping With correct input.
; Performs the function (Arg1.R*Arg2.R + Arg1.G*Arg2.G + Arg1.B*Arg2.B)
; where each component has been scaled And offset To make it signed.
; The result is replicated into all four (including alpha) channels.
; This is a valid COLOROP only.
Const D3DTOP_DOTPRODUCT3 = 24
Const FETOP_PROJECT = $010000 ; FastExt constant for 2D projective texturing TextureCoords=0 (UV0)
Const FETOP_PROJECT0 = $010000 ; FastExt constant for 2D projective texturing TextureCoords=0 (UV0)
Const FETOP_PROJECT1 = $020000 ; FastExt constant for 2D projective texturing TextureCoords=1 (UV1)
Const FETOP_PROJECT3D = $050000 ; FastExt constant for 3D projective texturing TextureCoords=0 (UV0)
Const FETOP_PROJECT3D0 = $050000 ; FastExt constant for 3D projective texturing TextureCoords=0 (UV0)
Const FETOP_PROJECT3D1 = $060000 ; FastExt constant for 3D projective texturing TextureCoords=1 (UV1)
; -------------------- DirectX7 constants (only for EntityBlendCustom & BrushBlendCustom functions) -----------------------
Const D3DBLEND_ZERO = 1
Const D3DBLEND_ONE = 2
Const D3DBLEND_SRCCOLOR = 3
Const D3DBLEND_INVSRCCOLOR = 4
Const D3DBLEND_SRCALPHA = 5
Const D3DBLEND_INVSRCALPHA = 6
Const D3DBLEND_DESTALPHA = 7
Const D3DBLEND_INVDESTALPHA = 8
Const D3DBLEND_DESTCOLOR = 9
Const D3DBLEND_INVDESTCOLOR = 10
Const D3DBLEND_SRCALPHASAT = 11
Const D3DBLEND_BOTHSRCALPHA = 12
Const D3DBLEND_BOTHINVSRCALPHA = 13
; íîâûå êîíñòàíòû äëÿ òåêñòóðíûõ ñìåøèâàíèé (ôóíêöèÿ TextureBlend)
; New constants for texture stage blending (TextureBlend function)
Const FE_ALPHACURRENT = (D3DTOP_BLENDCURRENTALPHA Shl 8) Or D3DTOP_SELECTARG1 ; = $1002 ïðîçðà÷íîñòü ïðåäûäóùåé òåêñòóðû äëÿ òåêóùåé
Const FE_ALPHAMODULATE = (D3DTOP_MODULATE Shl 8) Or D3DTOP_MODULATE ; = $0404 óìíîæåíèå ïðîçðà÷íîñòè (èñïîëüçóåì åùå è òåêóùóþ ïðîçðà÷íîñòü)
Const FE_BUMP = (D3DTOP_BUMPENVMAP Shl 8) Or D3DTOP_SELECTARG2 ; = $1603 òåêñòóðà èñêàæåíèé
Const FE_BUMPLUM = (D3DTOP_BUMPENVMAPLUMINANCE Shl 8) Or D3DTOP_SELECTARG2 ; = $1703 òåêñòóðà èñêàæåíèé + êàíàë ÿðêîñòè
Const FE_PROJECT = FETOP_PROJECT Or (D3DTOP_MODULATE Shl 8) Or D3DTOP_MODULATE ; = $010404 òåêñòóðà íàêëàäûâàåòñÿ êàê ïðîåêöèÿ (óìíîæåíèåì)
Const FE_PROJECTSMOOTH = FETOP_PROJECT Or (D3DTOP_ADDSMOOTH Shl 8) Or D3DTOP_MODULATE ; = $010B04 òåêñòóðà íàêëàäûâàåòñÿ êàê ïðîåêöèÿ (ïëàâíûì ñëîæåíèåì)
Const FE_MULTIPLY4X = (D3DTOP_MODULATE4X Shl 8)
Const FE_ADDSIGNED = (D3DTOP_ADDSIGNED Shl 8)
Const FE_ADDSIGNED2X = (D3DTOP_ADDSIGNED2X Shl 8)
Const FE_ADDSMOOTH = (D3DTOP_ADDSMOOTH Shl 8)
Const FE_SUB = (D3DTOP_SUBTRACT Shl 8)
Const FE_SPECULAR0 = (D3DTOP_MODULATEALPHA_ADDCOLOR Shl 8)
Const FE_SPECULAR1 = (D3DTOP_MODULATECOLOR_ADDALPHA Shl 8)
Const FE_SPECULAR2 = (D3DTOP_MODULATEINVALPHA_ADDCOLOR Shl 8)
Const FE_SPECULAR3 = (D3DTOP_MODULATEINVCOLOR_ADDALPHA Shl 8)
; íîâûå êîíñòàíòû äëÿ áðàø (åíòèòè) ñìåøèâàíèé (ôóíêöèÿ BrushBlend è EntityBlend)
; New constants for brush (entity) blending (BrushBlend and EntityBlend function)
Const FE_INVALPHA = $010605
Const FE_INVCOLOR = $010406
Const FE_INVCOLORADD = $010402
Const FE_NOALPHA = $000101
; ãëîáàëüíûé òèï äëÿ ïîëó÷åíèÿ âîçìîæíîñòåé âèäåî-äðàéâåðà
; Global type for Gfx-driver capabilities
Type GfxDriverCapsEx_Type
Field BrushBlendsSrc%
Field BrushBlendsDest%
Field TextureCaps%
Field TextureBlends%
Field TextureMaxStages%
Field TextureMaxWidth%
Field TextureMaxHeight%
Field TextureMaxAspectRatio%
Field ClipplanesMax%
Field LightsMax%
Field Bump%
Field BumpLum%
Field AnisotropyMax%
End Type
Global GfxDriverCapsEx.GfxDriverCapsEx_Type = New GfxDriverCapsEx_Type
Type Matrix3D
Field m11#, m12#, m13#, m14#
Field m21#, m22#, m23#, m24#
Field m31#, m32#, m33#, m34#
Field m41#, m42#, m43#, m44#
End Type
; library system vars
Global FE_PivotSys% = 0
Global FE_InitExtFlag% = 0
Global FE_InitPostprocessFlag% = 0
Global FE_PostprocessTexture1% = 0
Global FE_PostprocessTexture2% = 0
Global FE_PostprocessTexture3% = 0
Global FE_PostprocessTexture4% = 0
Global FE_PostprocessTexture5% = 0
; ãëàâíàÿ ôóíêöèÿ èíèöèàëèçàöèè áèáëèîòåêè, îáÿçàòåëüíî çàïóñêàåòñÿ ïîñëå êîìàíäû Graphics3D
; Main function for library initialising, must call after command Graphics3D
Function InitExt% ()
If FE_VERSION<>ExtVersion() Then
RuntimeError "ERROR! FastExstension library - Incorrect versions for FastExt.dll (v"+ExtVersion()+") And FastExt.bb (v"+FE_VERSION+")"
Else
DebugLog "Init FastExtension library v"+FE_VERSION+"successful"
EndIf
If FE_InitExtFlag=0 Then
FE_InitExtFlag = 1
FE_PivotSys = CreatePivot()
DeInitPostprocess()
InitExt_ ( SystemProperty("Direct3DDevice7"), BackBuffer(), GfxDriverCapsEx )
EndIf
End Function
; ôóíêöèÿ äëÿ ðåíäåðèíãà îäíîãî åíòèòè (âñå åãî ÷èëäû òîæå áóäóò îòðåíäåðåíû, åñëè íå ñêðûòû)
; Function for render single entity or entity with childrens
Function RenderEntity% (entity%, camera%, clearViewport%=0, tween#=1.0)
Return RenderEntity_ (entity, camera, tween, clearViewport, FE_PivotSys)
End Function
; ôóíêöèÿ äëÿ ðåíäåðèíãà ãðóïïû åíòèòåé (âñå åãî ÷èëäû òîæå áóäóò îòðåíäåðåíû, åñëè íå ñêðûòû)
; Function for render group of entities (with childrens, if not hidden)
Function RenderGroup% (group%, camera%, clearViewport%=0, tween#=1.0)
Return RenderGroup_ (group, camera, tween, clearViewport, FE_PivotSys)
End Function
Function TextureAnisotropy% (level%=0, index%=-1)
Return TextureAnisotropy_ (level, index)
End Function
Function TextureLodBias% (bias#=-0.2, index%=-1)
Return TextureLodBias_ (bias, index)
End Function
; Äîïîëüíèòåëüíûå ôóíêöèè äëÿ ÊëèïÏëåéíîâ
; Additional functions for ClipPlanes
Function CreateClipplane% (entity%=0, x1#=0, y1#=0, z1#=0, x2#=0, y2#=0, z2#=1, x3#=1, y3#=0, z3#=0)
If entity<>0 Then
TFormPoint 0, 0, 0,entity,0 : x1 = TFormedX() : y1 = TFormedY() : z1 = TFormedZ()
TFormPoint 0, 0, 1,entity,0 : x2 = TFormedX() : y2 = TFormedY() : z2 = TFormedZ()
TFormPoint 1, 0, 0,entity,0 : x3 = TFormedX() : y3 = TFormedY() : z3 = TFormedZ()
EndIf
Return CreateClipplane_ ( x1, y1, z1, x2, y2, z2, x3, y3, z3 )
End Function
Function AlignClipplane% (plane%, entity%=0, x1#=0, y1#=0, z1#=0, x2#=0, y2#=0, z2#=1, x3#=1, y3#=0, z3#=0)
If entity<>0 Then
TFormPoint 0, 0, 0,entity,0 : x1 = TFormedX() : y1 = TFormedY() : z1 = TFormedZ()
TFormPoint 0, 0, 1,entity,0 : x2 = TFormedX() : y2 = TFormedY() : z2 = TFormedZ()
TFormPoint 1, 0, 0,entity,0 : x3 = TFormedX() : y3 = TFormedY() : z3 = TFormedZ()
EndIf
Return AlignClipplane_ ( plane, x1, y1, z1, x2, y2, z2, x3, y3, z3 )
End Function
; Äîïîëüíèòåëüíûå ôóíêöèè äëÿ Êàìåðû
; Additional functions for Camera
Global MirrorCameraLast% = 0
Global MirrorCameraX# = 0
Global MirrorCameraY# = 0
Global MirrorCameraZ# = 0
Global MirrorCameraAX# = 0
Global MirrorCameraAY# = 0
Global MirrorCameraAZ# = 0
Global MirrorCameraParent% = 0
Function MirrorCamera% (camera%=0, entity%=0)
If camera<>0 Then
MirrorCameraLast = camera
MirrorCameraX# = EntityX(camera,1)
MirrorCameraY# = EntityY(camera,1)
MirrorCameraZ# = EntityZ(camera,1)
MirrorCameraAX# = EntityPitch(camera,1)
MirrorCameraAY# = EntityYaw(camera,1)
MirrorCameraAZ# = EntityRoll(camera,1)
If entity<>0 Then
MirrorCameraParent = ParentEntity(camera)
EntityParent camera, entity, 1
PositionEntity camera, EntityX(camera), -EntityY(camera), EntityZ(camera)
RotateEntity camera, -EntityPitch(camera), EntityYaw(camera), -EntityRoll(camera)
EntityParent camera,0,1
Else
PositionEntity camera, MirrorCameraX, -MirrorCameraY, MirrorCameraZ, 1
RotateEntity camera, -MirrorCameraAX, MirrorCameraAY, -MirrorCameraAZ, 1
EndIf
EndIf
End Function
Function RestoreCamera% (camera%=0)
If camera=0 Then camera=MirrorCameraLast
If camera<>0 Then
PositionEntity camera, MirrorCameraX, MirrorCameraY, MirrorCameraZ, 1
RotateEntity camera, MirrorCameraAX, MirrorCameraAY, MirrorCameraAZ, 1
If MirrorCameraParent<>0 Then EntityParent camera, MirrorCameraParent, 1
EndIf
End Function
; ñòàðûå ôóíêöèè òåïåðü ñ íîâûìè âîçìîæíîñòÿìè
; Old functions with NEW capabilities
Function SetBuffer% (buffer%)
Return SetBuffer_ (buffer)
End Function
Function GetBuffer% ()
Return SetBuffer_ (-1)
End Function
Function ClsColor% (red%, green%, blue%, alpha%=$FF, zValue#=1.0)
Return ClsColor_ (red, green, blue, alpha, zValue)
End Function
Function Cls% (clearColor%=1, clearZBuffer%=1)
Return Cls_ (clearColor, clearZBuffer)
End Function
Function WireFrame% (enable%=0)
Return Wireframe_ (enable)
End Function
Function Bump% (enable%=-1)
Return Bump_ (enable)
End Function
Function FreeTexture% (texture%)
If texture<>0 Then
Return FreeTexture_ (texture, TextureBuffer(texture))
Else
Return 0
EndIf
End Function
Function ColorFilter% (red%=1, green%=1, blue%=1, alpha%=1)
Return ColorFilter_ (red, green, blue, alpha)
End Function
Function TextureBlend% (texture%, blend%)
TextureBlend_ texture, blend
End Function
; íîâûå ôóíêöèÿ äëÿ çàäàíèÿ ÑÂÎÈÕ òåêñòóðíûõ ñìåøèâàíèé (èñïîëüçóéòå òîëüêî D3DTOP_* êîíñòàíòû, ñì. èõ íèæå)
; New function for custom texture blending (use D3DTOP_* constans only, see below)
Function TextureBlendCustom% (texture%, color_operation%, alpha_operation%=0, projection_flag%=0)
If color_operation>24 Then color_operation=24
If color_operation<1 Then color_operation=1
If alpha_operation>24 Then alpha_operation=24
If alpha_operation<0 Then alpha_operation=0
projection_flag = projection_flag And $7
TextureBlend texture, (projection_flag Shl 16) Or (color_operation Shl 8) Or alpha_operation
End Function
; íîâûå ôóíêöèè äëÿ ñîçäàíèÿ ÑÂÎÈÕ ñìåøèâàíèé ïðè ðåíäåðå îáúåêòîâ (èñïîëüçóéòå òîëüêî D3DBLEND_* êîíñòàíòû, ñì. èõ íèæå)
; New functions for custom entity (brush) blending (use D3DBLEND_* constans only, see below)
Function EntityBlendCustom% (entity%, source_blend%=1, destination_blend%=1, alphablending_enable%=0)
If source_blend>13 Then source_blend=13
If source_blend<1 Then source_blend=1
If destination_blend>13 Then destination_blend=13
If destination_blend<1 Then destination_blend=1
If alphablending_enable<>0 Then alphablending_enable=1
EntityBlend entity, (alphablending_enable Shl 16) Or (source_blend Shl 8) Or destination_blend
End Function
Function BrushBlendCustom% (brush%, source_blend%=1, destination_blend%=1, alphablending_enable%=0)
If source_blend>13 Then source_blend=13
If source_blend<1 Then source_blend=1
If destination_blend>13 Then destination_blend=13
If destination_blend<1 Then destination_blend=1
If alphablending_enable<>0 Then alphablending_enable=1
BrushBlend brush, (alphablending_enable Shl 16) Or (source_blend Shl 8) Or destination_blend
End Function
Function ExecAndExit% (file$="", command$="", workingDir$="")
ExecAndExit_ file, command, workingDir
End Function
Function InitPostprocess% ()
Local CurrentBuffer%, smallWidth%, smallHeight%
If FE_InitPostprocessFlag=0
smallWidth = GraphicsWidth()/3 : smallHeight = GraphicsHeight()/3
FE_PostprocessTexture1 = CreateTexture ( GraphicsWidth(), GraphicsHeight(), 1 + 256 + FE_ExSIZE + FE_RENDER + FE_ZRENDER )
FE_PostprocessTexture2 = CreateTexture ( smallWidth, smallHeight, 1 + 256 + FE_ExSIZE + FE_RENDER )
FE_PostprocessTexture3 = CreateTexture ( 16, 16, 1 )
FE_PostprocessTexture4 = CreateTexture ( smallWidth, smallHeight, 1 + 256 + FE_ExSIZE + FE_RENDER )
FE_PostprocessTexture5 = CreateTexture ( GraphicsWidth(), GraphicsHeight(), 1 + 256 + FE_ExSIZE ) ; comment this string if MotionBlur not needed (not used)
CurrentBuffer = SetBuffer (TextureBuffer(FE_PostprocessTexture3))
ClsColor 255,255,255 : Cls : SetBuffer BackBuffer()
If InitPostprocess_ (BackBuffer(), TextureBuffer(FE_PostprocessTexture1), TextureBuffer(FE_PostprocessTexture2), TextureBuffer(FE_PostprocessTexture3), TextureBuffer(FE_PostprocessTexture4), TextureBuffer(FE_PostprocessTexture5))<>0 Then
FE_InitPostprocessFlag = 1
Else
If FE_PostprocessTexture1<>0 Then FreeTexture FE_PostprocessTexture1
If FE_PostprocessTexture2<>0 Then FreeTexture FE_PostprocessTexture2
If FE_PostprocessTexture3<>0 Then FreeTexture FE_PostprocessTexture3
If FE_PostprocessTexture4<>0 Then FreeTexture FE_PostprocessTexture4
If FE_PostprocessTexture5<>0 Then FreeTexture FE_PostprocessTexture5
EndIf
SetBuffer CurrentBuffer
EndIf
Return FE_InitPostprocessFlag
End Function
Function DeInitPostprocess% ()
If FE_InitPostprocessFlag<>0 Then
If FE_PostprocessTexture1<>0 Then FreeTexture FE_PostprocessTexture1
If FE_PostprocessTexture2<>0 Then FreeTexture FE_PostprocessTexture2
If FE_PostprocessTexture3<>0 Then FreeTexture FE_PostprocessTexture3
If FE_PostprocessTexture4<>0 Then FreeTexture FE_PostprocessTexture4
If FE_PostprocessTexture5<>0 Then FreeTexture FE_PostprocessTexture5
FE_InitPostprocessFlag = 0
EndIf
End Function
Function RenderPostprocess% (flags%=0, x%=0, y%=0, width%=0, height%=0)
If InitPostprocess()<>0 Then RenderPostprocess_ flags, x, y, width, height
End Function
Function CustomPostprocessDOF% (near#=10.0, far#=100.0, direction%=1, level%=3, blurRadius#=0.35, quality%=1)
CustomPostprocessDOF_ near, far, direction, level, blurRadius, quality
End Function
Function CustomPostprocessGlow% (alpha#=1.0, darkPasses%=2, blurPasses%=4, blurRadius#=0.35, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0)
CustomPostprocessGlow_ alpha, darkPasses, blurPasses, blurRadius, quality, red, green, blue, alphaTexture
End Function
Function CustomPostprocessBlur% (alpha#=1.0, blurPasses%=4, blurRadius#=0.35, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0)
CustomPostprocessBlur_ alpha, blurPasses, blurRadius, quality, red, green, blue, alphaTexture
End Function
Function CustomPostprocessInverse% (alpha#=1.0, red%=255, green%=255, blue%=255, alphaTexture%=0)
CustomPostprocessInverse_ alpha, red, green, blue, alphaTexture
End Function
Function CustomPostprocessGrayscale% (alpha#=1.0, brightness#=1.0, inverse%=0, alphaTexture%=0)
CustomPostprocessGrayscale_ alpha, brightness, inverse, alphaTexture
End Function
Function CustomPostprocessContrast% (alpha#=1.0, method%=0, red%=255, green%=255, blue%=255, alphaTexture%=0)
CustomPostprocessContrast_ alpha#, method, red, green, blue, alphaTexture
End Function
Function CustomPostprocessBlurDirectional% (angle#=0, alpha#=1, blurPasses%=4, blurRadius#=0.35, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0)
CustomPostprocessBlurDirectional_ angle, alpha, blurPasses, blurRadius, quality, red, green, blue, alphaTexture
End Function
Function CustomPostprocessBlurZoom% (x#=0.5, y#=0.5, zoomFactor#=105, alpha#=1, blurPasses%=4, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0)
CustomPostprocessBlurZoom_ x, y, zoomFactor, alpha, blurPasses, quality, red, green, blue, alphaTexture
End Function
Function CustomPostprocessBlurSpin% (x#=0.5, y#=0.5, spinAngle#=4, alpha#=1, blurPasses%=4, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0)
CustomPostprocessBlurSpin_ x, y, spinAngle, alpha, blurPasses, quality, red, green, blue, alphaTexture
End Function
Function CustomPostprocessBlurMotion% (alpha#=0.9, originX#=0, originY#=0, handleX#=0.5, handleY#=0.5, scaleX#=100, scaleY#=100, angle#=0, blend%=0, red%=255, green%=255, blue%=255, alphaTexture%=0)
CustomPostprocessBlurMotion_ alpha, originX, originY, handleX, handleY, scaleX, scaleY, angle, blend, red, green, blue, alphaTexture
End Function
Function CustomPostprocessOverlay% (alpha#=0.5, blend%=0, red%=255, green%=255, blue%=255, alphaTexture%=0)
CustomPostprocessOverlay_ alpha, blend, red, green, blue, alphaTexture
End Function
Function CustomPostprocessRays% (centerX#=0.5, centerY#=0.5, zoomFactor#=105, alpha#=1, darkPasses%=2, blurPasses%=4, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0)
CustomPostprocessRays_% (centerX, centerY, zoomFactor, alpha, darkPasses, blurPasses, quality, red, green, blue, alphaTexture)
End Function
Function DeInitExt% ()
If FE_InitExtFlag<>0 Then
FE_InitExtFlag = 0
SetBuffer BackBuffer()
FreeEntity FE_PivotSys
DeInitPostprocess
DeInitExt_
EndIf
End Function
File diff suppressed because it is too large Load Diff
+122
View File
@@ -0,0 +1,122 @@
Const ImpostorVariant = 0
Type Impostor
Field Frames%
Field FrameWidth%, FrameHeight%
Field PitchFrames%, PitchMin#, PitchMax#
Field YawFrames%, YawMin#, YawMax#
Field Sheet%
Field Pivot%, Parent%
Field Mesh%, Surface%
Field YawStep#, PitchStep#
End Type
Function Impostor_Init.Impostor(Parent%=0)
Local Instance.Impostor = New Impostor
Instance\Pivot = CreatePivot(Parent)
Instance\Mesh = CreateMesh(Instance\Pivot)
Instance\Surface = CreateSurface(Instance\Mesh)
Local V0,V1,V2,V3
V0 = AddVertex(Instance\Surface, -1, 1, 0, 1, 0, 0)
V1 = AddVertex(Instance\Surface, 1, 1, 0, 0, 0, 0)
V2 = AddVertex(Instance\Surface, -1, -1, 0, 1, 1, 0)
V3 = AddVertex(Instance\Surface, 1, -1, 0, 0, 1, 0)
AddTriangle Instance\Surface, V0, V2, V1
AddTriangle Instance\Surface, V1, V2, V3
Return Instance
End Function
Function Impostor_Load.Impostor(Path$, Flags%=1+4+16+32+256+512, Parent%=0)
If FileType(Path) <> 1 Then
RuntimeError "Impostor: Given <Path$> is not a file."
Else
Local Stream = ReadFile(Path)
If Stream = 0 Then
RuntimeError "Impostor: Unable to open given <Path$>."
Else
Local Instance.Impostor = Impostor_Init(Parent)
Instance\FrameWidth = ReadShort(Stream)
Instance\FrameHeight = ReadShort(Stream)
Instance\PitchFrames = ReadByte(Stream)
Instance\PitchMin = ReadFloat(Stream)
Instance\PitchMax = ReadFloat(Stream)
Instance\YawFrames = ReadByte(Stream)
Instance\YawMin = ReadFloat(Stream)
Instance\YawMax = ReadFloat(Stream)
Local BaseName$ = Impostor_StripExtension(Path)
Instance\Sheet = LoadAnimTexture(BaseName + "png", Flags, Instance\FrameWidth, Instance\FrameHeight, 0, Instance\PitchFrames * Instance\YawFrames)
If Instance\Sheet = 0 Then RuntimeError "Impostor: Unable to open texture for given <Path$>."
Instance\YawStep = (Instance\YawMax - Instance\YawMin) / Instance\YawFrames
Instance\PitchStep = (Instance\PitchMax - Instance\PitchMin) / Instance\PitchFrames
Return Instance
EndIf
EndIf
End Function
Function Impostor_Create.Impostor(Mesh%, Diffuse%)
End Function
Function Impostor_Update(Camera%)
Local Instance.Impostor = Null
For Instance = Each Impostor
Impostor_UpdateSingle(Camera, Instance)
Next
End Function
Function Impostor_UpdateSingle(Camera%, Impostor.Impostor)
; Calculate current Yaw frame and Pitch frame.
PointEntity Impostor\Mesh, Camera, 0
Local Yaw# = Impostor_Math_MaxMin(EntityYaw(Impostor\Mesh), Impostor\YawMax, Impostor\YawMin) - Impostor\YawMin
Local Pitch# = Impostor_Math_MaxMin(EntityPitch(Impostor\Mesh), Impostor\PitchMax, Impostor\PitchMin) - Impostor\PitchMin
Local YawFrame = Int(Yaw / Impostor\YawStep)
Local PitchFrame = Floor(Pitch / Impostor\PitchStep)
DebugLog YawFrame
EntityTexture Impostor\Mesh, Impostor\Sheet, PitchFrame * Impostor\YawFrames + YawFrame, 0
EntityFX Impostor\Mesh, 16
RotateEntity Impostor\Mesh, Impostor\PitchMin - PitchFrame * Impostor\PitchStep, 180 + Impostor\YawMin + YawFrame * Impostor\YawStep, 0
End Function
Function Impostor_StripExtension$(Path$)
Local RPath$ = Path$
For temp_Pos = Len(Path)-1 To 1 Step -1
If Mid(Path, temp_Pos, 1) = "."
RPath = Left(Path, temp_Pos)
Exit
EndIf
Next
Return RPath
End Function
Function Impostor_Math_MaxMin#(Value#, Max#, Min#)
If Value> Max Then Return Max
If Value < Min Then Return Min
Return Value
End Function
Function Impostor_Math_Max#(Value#, Max#)
If Value> Max Then Return Max
Return Value
End Function
Function Impostor_Math_Min#(Value#, Min#)
If Value < Min Then Return Min
Return Value
End Function
Function Impostor_Math_Clip#(Value#, Low#, High#)
Local Out#, Diff#
Diff = High-Low:Out = Value-Low
If (Out >= Diff) Then Out = Out - Floor(Out/Diff)*Diff
If (Out < 0) Then Out = Out - Floor(Out/Diff)*Diff
Return Low+Out
End Function
;~IDEal Editor Parameters:
;~C#Blitz3D
+18
View File
@@ -0,0 +1,18 @@
[IDEal Project file]
<Settings>
Version="1"
Expanded="True"
Icon=""
MainFile="CreateImpostorTextures.bb"
Compiler="Blitz3D"
CommandLine=""
</Settings>
<Folders>
</Folders>
<Files>
AbsPath="\CreateImpostorTextures.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
AbsPath="\Example01_Cube.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
AbsPath="\FastExt.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
AbsPath="\FreeImage.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
AbsPath="\Impostor.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
</Files>
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

+9
View File
@@ -0,0 +1,9 @@
Impostor
=======================
You know those distant objects that don't quite seem like a 3D object, but still turn with the view? That's an impostor, and this was supposed to be a Blitz3D implementation of that. Didn't work out as planned though, so here's the broken version that used FastExt to do its work.
If you don't know where to get FastExt, google will help you.
License
=======
Impostor by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
@@ -0,0 +1,41 @@
Include "LevelOfDetail.bb"
Graphics3D 1024, 768, 0, 2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
Timer = CreateTimer(60)
Local eCamera = CreateCamera()
LoD_Initialize()
Local L0 = CreateSphere(16):HideEntity L0
Local L1 = CreateSphere(8):HideEntity L1
Local L2 = CreateSphere(4):HideEntity L2
Local L3 = CreateSphere(2):HideEntity L3
Local L4 = CreateSprite():HideEntity L4
For X = -10 To 10
For Y = -10 To 10
For Z = -10 To 10
Local tEnt.LoDEntity = LoD_Create(L0, L1, L2, L3, L4)
PositionEntity tEnt\Pivot, X*3, Y*3, Z*3
LoD_EntityColor tEnt, Rand(0, 255), Rand(0, 255), Rand(0, 255)
Next
Next
Next
While Not KeyHit(1)
MoveEntity eCamera, KeyDown(32) - KeyDown(30), 0, KeyDown(17) - KeyDown(31)
If MouseDown(1) Then RotateEntity eCamera, EntityPitch(eCamera) + MouseYSpeed()/4.0, EntityYaw(eCamera) -MouseXSpeed()/4.0, 0:MoveMouse 512,384
WireFrame MouseDown(2)
RenderWorld
LoD_Update(eCamera)
Text 0, 0, TrisRendered()
Flip False
; WaitTimer(Timer)
Wend
@@ -0,0 +1,163 @@
Global LoD_Dist_Lv0# = 32, LoD_Dist_Lv1# = 64, LoD_Dist_Lv2# = 128, LoD_Dist_Lv3# = 256, LoD_Dist_Lv4# = 512
Global LoD_Range# = 8
Type LoDEntity
Field Pivot% = 0
; Levels
Field LoDs%[5]
; Temporary Values
Field Visible%[5]
Field Fade#[5]
End Type
Function LoD_Initialize(Dist_Range# = 8, Dist_Lv0# = 32, Dist_Lv1# = 64, Dist_Lv2# = 128, Dist_Lv3# = 256, Dist_Lv4# = 512)
LoD_Range = Dist_Range
; Distance Limits
LoD_Dist_Lv0 = Dist_Lv0
LoD_Dist_Lv1 = Dist_Lv1
LoD_Dist_Lv2 = Dist_Lv2
LoD_Dist_Lv3 = Dist_Lv3
LoD_Dist_Lv4 = Dist_Lv4
End Function
Function LoD_Create.LoDEntity(Lv0, Lv1, Lv2, Lv3, Lv4)
Local tInstance.LoDEntity = New LoDEntity
tInstance\Pivot = CreatePivot()
; Copy Entities
tInstance\LoDs[0] = CopyEntity(Lv0, tInstance\Pivot):HideEntity tInstance\LoDs[0]
tInstance\LoDs[1] = CopyEntity(Lv1, tInstance\Pivot):HideEntity tInstance\LoDs[1]
tInstance\LoDs[2] = CopyEntity(Lv2, tInstance\Pivot):HideEntity tInstance\LoDs[2]
tInstance\LoDs[3] = CopyEntity(Lv3, tInstance\Pivot):HideEntity tInstance\LoDs[3]
tInstance\LoDs[4] = CopyEntity(Lv4, tInstance\Pivot):HideEntity tInstance\LoDs[4]
Return tInstance
End Function
Function LoD_EntityAlpha(tInstance.LoDEntity, Alpha#, Level=-1)
If (Level = -1) Then
EntityAlpha tInstance\LoDs[0], Alpha
EntityAlpha tInstance\LoDs[1], Alpha
EntityAlpha tInstance\LoDs[2], Alpha
EntityAlpha tInstance\LoDs[3], Alpha
EntityAlpha tInstance\LoDs[4], Alpha
Else
EntityAlpha tInstance\LoDs[Level], Alpha
EndIf
End Function
Function LoD_EntityBlend(tInstance.LoDEntity, Mode%, Level=-1)
If (Level = -1) Then
EntityBlend tInstance\LoDs[0], Mode
EntityBlend tInstance\LoDs[1], Mode
EntityBlend tInstance\LoDs[2], Mode
EntityBlend tInstance\LoDs[3], Mode
EntityBlend tInstance\LoDs[4], Mode
Else
EntityBlend tInstance\LoDs[Level], Mode
EndIf
End Function
Function LoD_EntityColor(tInstance.LoDEntity, Red#, Green#, Blue#, Level=-1)
If (Level = -1) Then
EntityColor tInstance\LoDs[0], Red, Green, Blue
EntityColor tInstance\LoDs[1], Red, Green, Blue
EntityColor tInstance\LoDs[2], Red, Green, Blue
EntityColor tInstance\LoDs[3], Red, Green, Blue
EntityColor tInstance\LoDs[4], Red, Green, Blue
Else
EntityColor tInstance\LoDs[Level], Red, Green, Blue
EndIf
End Function
Function LoD_EntityFX(tInstance.LoDEntity, FX%, Level=-1)
If (Level = -1) Then
EntityFX tInstance\LoDs[0], FX
EntityFX tInstance\LoDs[1], FX
EntityFX tInstance\LoDs[2], FX
EntityFX tInstance\LoDs[3], FX
EntityFX tInstance\LoDs[4], FX
Else
EntityFX tInstance\LoDs[Level], FX
EndIf
End Function
Function LoD_EntityShininess(tInstance.LoDEntity, Shininess#, Level=-1)
If (Level = -1) Then
EntityShininess tInstance\LoDs[0], Shininess
EntityShininess tInstance\LoDs[1], Shininess
EntityShininess tInstance\LoDs[2], Shininess
EntityShininess tInstance\LoDs[3], Shininess
EntityShininess tInstance\LoDs[4], Shininess
Else
EntityShininess tInstance\LoDs[Level], Shininess
EndIf
End Function
Function LoD_EntityTexture(tInstance.LoDEntity, Texture%, Frame%=0, Index%=0, Level=-1)
If (Level = -1) Then
EntityTexture tInstance\LoDs[0], Texture, Frame, Index
EntityTexture tInstance\LoDs[1], Texture, Frame, Index
EntityTexture tInstance\LoDs[2], Texture, Frame, Index
EntityTexture tInstance\LoDs[3], Texture, Frame, Index
EntityTexture tInstance\LoDs[4], Texture, Frame, Index
Else
EntityTexture tInstance\LoDs[Level], Texture, Frame, Index
EndIf
End Function
Function LoD_EntityLoD(tInstance.LoDEntity)
For Level = 0 To 4
If (tInstance\Visible[Level]) Then Return Level
Next
Return 5
End Function
Function LoD_Update(eCamera, bDoFadeOut=False)
For tInstance.LoDEntity = Each LoDEntity
Local Dist# = EntityDistance(eCamera, tInstance\Pivot)
; LoD Level 1 (Very High)
If (Dist > 0) And ((bDoFadeOut And (Dist < LoD_Dist_Lv0 + LoD_Range)) Or (bDoFadeOut = False And (Dist < LoD_Dist_Lv0))) Then
If tInstance\Visible[0] = False Then tInstance\Visible[0] = True:ShowEntity tInstance\LoDs[0]
If bDoFadeOut = True And (Dist > LoD_Dist_Lv0) Then EntityAlpha tInstance\LoDs[0], 1.0 - (Dist - LoD_Dist_Lv0) / LoD_Range
Else
If tInstance\Visible[0] = True Then tInstance\Visible[0] = False:HideEntity tInstance\LoDs[0]
EndIf
; LoD Level 2 (High)
If (Dist > LoD_Dist_Lv0) And ((bDoFadeOut And (Dist < LoD_Dist_Lv1 + LoD_Range)) Or (bDoFadeOut = False And (Dist < LoD_Dist_Lv1))) Then
If tInstance\Visible[1] = False Then tInstance\Visible[1] = True:ShowEntity tInstance\LoDs[1]
If bDoFadeOut = True And (Dist > LoD_Dist_Lv1) Then EntityAlpha tInstance\LoDs[1], 1.0 - (Dist - LoD_Dist_Lv1) / LoD_Range
Else
If tInstance\Visible[1] = True Then tInstance\Visible[1] = False:HideEntity tInstance\LoDs[1]
EndIf
; LoD Level 3 (Normal)
If (Dist > LoD_Dist_Lv1) And ((bDoFadeOut And (Dist < LoD_Dist_Lv2 + LoD_Range)) Or (bDoFadeOut = False And (Dist < LoD_Dist_Lv2))) Then
If tInstance\Visible[2] = False Then tInstance\Visible[2] = True:ShowEntity tInstance\LoDs[2]
If bDoFadeOut = True And (Dist > LoD_Dist_Lv2) Then EntityAlpha tInstance\LoDs[2], 1.0 - (Dist - LoD_Dist_Lv2) / LoD_Range
Else
If tInstance\Visible[2] = True Then tInstance\Visible[2] = False:HideEntity tInstance\LoDs[2]
EndIf
; LoD Level 4 (Low)
If (Dist > LoD_Dist_Lv2) And ((bDoFadeOut And (Dist < LoD_Dist_Lv3 + LoD_Range)) Or (bDoFadeOut = False And (Dist < LoD_Dist_Lv3))) Then
If tInstance\Visible[3] = False Then tInstance\Visible[3] = True:ShowEntity tInstance\LoDs[3]
If bDoFadeOut = True And (Dist > LoD_Dist_Lv3) Then EntityAlpha tInstance\LoDs[3], 1.0 - (Dist - LoD_Dist_Lv3) / LoD_Range
Else
If tInstance\Visible[3] = True Then tInstance\Visible[3] = False:HideEntity tInstance\LoDs[3]
EndIf
; LoD Level 5 (Very Low) (Usually a Sprite)
If (Dist > LoD_Dist_Lv3) And ((bDoFadeOut And (Dist < LoD_Dist_Lv4 + LoD_Range)) Or (bDoFadeOut = False And (Dist < LoD_Dist_Lv4))) Then
If tInstance\Visible[4] = False Then tInstance\Visible[4] = True:ShowEntity tInstance\LoDs[4]
If bDoFadeOut = True And (Dist > LoD_Dist_Lv4) Then EntityAlpha tInstance\LoDs[4], 1.0 - (Dist - LoD_Dist_Lv4) / LoD_Range
Else
If tInstance\Visible[4] = True Then tInstance\Visible[4] = False:HideEntity tInstance\LoDs[4]
EndIf
Next
End Function
@@ -0,0 +1,8 @@
Level of Detail
=======================
A library originally ment to add level of detail to Sirius Online, back when it was still using Blitz3D. Works somewhat okay, might require some tweaking. Oct-Tree solutions will work better in most cases, so use at your own risk.
License
=======
Level of Detail by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+8
View File
@@ -0,0 +1,8 @@
Motion Blur
=======================
This was a test at how good I could make a motion blur effect in Blitz3D, without much success in actual use. Blitz3D likes to resend all data instead of reuse, so frametime increased a lot. Still looks nice on single objects that require such types of blur.
License
=======
Motion Blur by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
@@ -0,0 +1,42 @@
AppTitle "TrueMotion"
Include "TrueMotion.bb"
Graphics3D 1024,768,0,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
Local eCamera = CreateCamera()
Local tCube = CreateTexture(128,128)
SetBuffer TextureBuffer(tCube)
Color 255, 255, 0
Rect 0, 0, 64, 64
Rect 64, 64, 64, 64
Color 0, 127, 255
Rect 64, 0, 64, 64
Rect 0, 64, 64, 64
SetBuffer BackBuffer()
Local eCube = CreateCube()
PositionEntity eCube, 0, 0, 3
EntityTexture eCube, tCube
Local tInstance.TrueMotion = TrueMotion_Create(eCamera)
Timer = CreateTimer(60)
Global Msec
While Not KeyHit(1)
Cls
Msec = Msec + 10
RotateEntity eCube, Cos(Msec/4.0)*30, 0, EntityRoll(eCube) + 16
PositionEntity eCube, 0, Sin(Msec/4.0)*2, 4
TrueMotion_RenderWorld(tInstance, 32)
Flip
WaitTimer(Timer)
Wend
End
@@ -0,0 +1,51 @@
Type TrueMotion
Field Camera% = 0
Field Mesh% = 0
End Type
Function TrueMotion_Create.TrueMotion(Camera%)
;Create TrueMotion Instance
tInstance.TrueMotion = New TrueMotion
; Camera can't be Null or invalid
If Camera = 0 Then
RuntimeError "TrueMotion: Camera is Null."
Else
If EntityClass(Camera) <> "Camera" Then
RuntimeError "TrueMotion: Camera is not of type <Camera>."
Else
tInstance\Camera = Camera
EndIf
EndIf
; Create Mesh
tInstance\Mesh = CreateMesh(tInstance\Camera)
sSurface = CreateSurface(tInstance\Mesh)
AddVertex(sSurface, -1, 1, 0, 0, 0)
AddVertex(sSurface, 1, 1, 0, 1, 0)
AddVertex(sSurface, 1, -1, 0, 1, 1)
AddVertex(sSurface, -1, -1, 0, 0, 1)
AddTriangle(sSurface, 0, 1, 2)
AddTriangle(sSurface, 0, 2, 3)
EntityOrder(tInstance\Mesh, -1)
EntityColor(tInstance\Mesh, 0, 0, 0)
PositionEntity(tInstance\Mesh, 0, 0, 1)
HideEntity(tInstance\Mesh)
Return tInstance
End Function
; Call this before after you have done your changes. It is a good practice to only let this effect affect nearby entities.
Function TrueMotion_RenderWorld(tInstance.TrueMotion, Steps%=12)
ShowEntity(tInstance\Mesh)
EntityAlpha(tInstance\Mesh, 1.0/Steps)
CameraClsMode(tInstance\Camera, 0, 1)
For curStep = 0 To Steps - 1
RenderWorld curStep/Float(Steps)
Next
HideEntity(tInstance\Mesh)
RenderWorld 1
CameraClsMode(tInstance\Camera, 1, 1)
CaptureWorld
End Function
@@ -0,0 +1,42 @@
AppTitle "TrueMotion"
Include "TrueMotion.bb"
Graphics3D 1024,768,0,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
Local eCamera = CreateCamera()
Local tCube = CreateTexture(128,128)
SetBuffer TextureBuffer(tCube)
Color 255, 255, 0
Rect 0, 0, 64, 64
Rect 64, 64, 64, 64
Color 0, 127, 255
Rect 64, 0, 64, 64
Rect 0, 64, 64, 64
SetBuffer BackBuffer()
Local eCube = CreateCube()
PositionEntity eCube, 0, 0, 3
EntityTexture eCube, tCube
Local tInstance.TrueMotion = TrueMotion_Create(eCamera, 32)
Timer = CreateTimer(60)
Global Msec
While Not KeyHit(1)
Cls
Msec = Msec + 10
RotateEntity eCube, Cos(Msec/4.0)*30, 0, EntityRoll(eCube) + 16
PositionEntity eCube, 0, Sin(Msec/4.0)*2, 4
TrueMotion_RenderWorld(tInstance)
Flip
WaitTimer(Timer)
Wend
End
@@ -0,0 +1,82 @@
Const TRUEMOTION_STEPS_MAX = 32
Type TrueMotion
Field Camera% = 0
; Settings
Field Steps% = 6
Field SizeW% = 128
Field SizeH% = 128
; Core Stuff
Field Texture% = 0
Field Mesh% = 0
End Type
Function TrueMotion_Create.TrueMotion(Camera%, Steps%=12);, SizeW%=128, SizeH%=128, Steps%=5)
;Create TrueMotion Instance
tInstance.TrueMotion = New TrueMotion
; Camera can't be Null or invalid
If Camera = 0 Then
RuntimeError "TrueMotion: Camera is Null."
Else
If EntityClass(Camera) <> "Camera" Then
RuntimeError "TrueMotion: Camera is not of type <Camera>."
Else
tInstance\Camera = Camera
EndIf
EndIf
; Limit <Steps> into 1-TRUEMOTION_STEPS_MAX to prevent too high values.
If Steps < 1 Then
tInstance\Steps = 1
ElseIf Steps > TRUEMOTION_STEPS_MAX Then
tInstance\Steps = TRUEMOTION_STEPS_MAX
Else
tInstance\Steps = Steps
EndIf
; Limit <SizeW/H> to be 2^n and still below GraphicsWidth and -Height.
If SizeW < 1 Then SizeW = 1
If SizeW > GraphicsWidth() Then SizeW = GraphicsWidth()
tInstance\SizeW = 2^Floor(Log(SizeW)/Log(2))
If SizeH < 1 Then SizeH = 1
If SizeH > GraphicsWidth() Then SizeH = GraphicsHeight()
tInstance\SizeH = 2^Floor(Log(SizeH)/Log(2))
; Create Texture
tInstance\Texture = CreateTexture(tInstance\SizeW, tInstance\SizeH, 305, tInstance\Steps)
; Create Mesh
tInstance\Mesh = CreateMesh(tInstance\Camera)
sSurface = CreateSurface(tInstance\Mesh)
AddVertex(sSurface, -1, 1, 0, 0, 0)
AddVertex(sSurface, 1, 1, 0, 1, 0)
AddVertex(sSurface, 1, -1, 0, 1, 1)
AddVertex(sSurface, -1, -1, 0, 0, 1)
AddTriangle(sSurface, 0, 1, 2)
AddTriangle(sSurface, 0, 2, 3)
EntityFX(tInstance\Mesh, 8)
EntityTexture(tInstance\Mesh, tInstance\Texture, 0)
EntityOrder(tInstance\Mesh, -1)
EntityColor(tInstance\Mesh, 0, 0, 0)
EntityAlpha(tInstance\Mesh, (1.0/(tInstance\Steps)))
PositionEntity(tInstance\Mesh, 0, 0, 1)
HideEntity(tInstance\Mesh)
Return tInstance
End Function
; Call this before after you have done your changes. It is a good practice to only let this effect affect nearby entities.
Function TrueMotion_RenderWorld(tInstance.TrueMotion)
HideEntity(tInstance\Mesh)
CameraClsMode(tInstance\Camera, 1, 1)
For curStep = 0 To tInstance\Steps - 1
RenderWorld curStep/Float(tInstance\Steps)
Next
ShowEntity(tInstance\Mesh)
RenderWorld 1
CaptureWorld
End Function
+267
View File
@@ -0,0 +1,267 @@
;--------------------------------------------
; Example
;--------------------------------------------
Include "../Advanced Text (Library)/AdvText.bb"
Include "TiledSprite.bb"
Graphics3D 1280,720,32,2
SetBuffer BackBuffer()
; Background
Local FPlane = CreatePlane(16)
RotateEntity FPlane, 270, 0, 0
PositionEntity FPlane, 0, 0, 256, True
EntityColor FPlane, 128, 128, 128
Local BPlane = CreatePlane(16)
RotateEntity BPlane, 90, 0, 0
PositionEntity BPlane, 0, 0, -256, True
EntityColor BPlane, 0, 128, 190
Local LPlane = CreatePlane(16)
RotateEntity LPlane, 90, 90, 0
PositionEntity LPlane, 256, 0, 0, True
EntityColor LPlane, 0, 128, 190
Local RPlane = CreatePlane(16)
RotateEntity RPlane, 90, 270, 0
PositionEntity RPlane, -256, 0, 0, True
EntityColor RPlane, 0, 128, 190
Local DPlane = CreatePlane(16)
RotateEntity DPlane, 0, 0, 0
PositionEntity DPlane, 0, -256, 0, True
EntityColor DPlane, 0, 128, 0
Local UPlane = CreatePlane(16)
RotateEntity UPlane, 180, 0, 0
PositionEntity UPlane, 0, 256, 0, True
EntityColor UPlane, 0, 128, 190
; Camera
Local eCameraPitch# = 0
Local eCameraYaw# = 0
Local eCameraZoom# = 1
Local eCameraFOV# = 90.0
Local eCameraFOVValue# = Tan( eCameraFOV / 2.0 )
Local eCameraCenter = CreatePivot()
Local eCamera = CreateCamera(eCameraCenter)
Local eCameraLight = CreateLight(3, eCamera)
PositionEntity eCamera, 0, 0, -eCameraZoom, False
CameraRange eCamera, 0.1, 1024
CameraZoom eCamera, 1.0 / eCameraFOVValue
LightConeAngles eCameraLight, 10, 60
LightColor eCameraLight, 64, 128, 255
; Sprite Texture Creation
Global InvTex = LoadTexture("TiledSprite_Test01.fw.png", 1+2+8+16+32+256)
Global InvBrush = CreateBrush(255.0, 255.0, 255.0)
BrushTexture InvBrush, InvTex, 0, 0
BrushFX InvBrush, 1+4+8
; Main Mesh
Global InvMesh = CreateMesh(eCamera)
PositionEntity InvMesh, 0, 0, 1
EntityFX InvMesh, 1+4+8
; Scale the Mesh according to ScreenWidth and FOV(Tan(FOV/2.0)).
Local InvMeshScale# = (1 / (GraphicsWidth()/2.0)) * eCameraFOVValue
ScaleEntity InvMesh, InvMeshScale, InvMeshScale, 1, True
;Hint: Order of Creation is Important for Sprites not sharing a mesh or a surface. If only sharing the surface, order of fill is important.
; Foreground Sprite
Local InvFGSpriteBuilder.TSpriteBuilder = TSpriteBuilder_Create()
TSpriteBuilder_Mesh(InvFGSpriteBuilder, InvMesh)
TSpriteBuilder_Brush(InvFGSpriteBuilder, InvBrush)
TSpriteBuilder_BrushSize(InvFGSpriteBuilder, 256, 256)
TSpriteBuilder_Scale(InvFGSpriteBuilder, 0.5, 0.5)
TSpriteBuilder_Padding(InvFGSpriteBuilder, 0, 0, 128, 128)
TSpriteBuilder_Border(InvFGSpriteBuilder, 32, 32, 32, 32)
TSpriteBuilder_BorderScale(InvFGSpriteBuilder, 0.5, 0.5)
Local InvFGSprite.TSprite = TSprite_Create(InvFGSpriteBuilder)
; Inverted Gradient Sprite
Local InvGradientSpriteBuilder.TSpriteBuilder = TSpriteBuilder_Create()
TSpriteBuilder_Mesh(InvGradientSpriteBuilder, InvMesh)
TSpriteBuilder_Brush(InvGradientSpriteBuilder, InvBrush)
TSpriteBuilder_BrushSize(InvGradientSpriteBuilder, 256, 256)
TSpriteBuilder_Scale(InvGradientSpriteBuilder, 0.5, 0.5)
TSpriteBuilder_Padding(InvGradientSpriteBuilder, 128, 128, 0, 0)
TSpriteBuilder_Border(InvGradientSpriteBuilder, 32, 32, 32, 32)
TSpriteBuilder_BorderScale(InvGradientSpriteBuilder, 0.5, 0.5)
Local InvGradientSprite.TSprite = TSprite_Create(InvGradientSpriteBuilder)
; Gradient Sprite
Local GradientSpriteBuilder.TSpriteBuilder = TSpriteBuilder_Create()
TSpriteBuilder_Mesh(GradientSpriteBuilder, InvMesh)
TSpriteBuilder_Brush(GradientSpriteBuilder, InvBrush)
TSpriteBuilder_BrushSize(GradientSpriteBuilder, 256, 256)
TSpriteBuilder_Scale(GradientSpriteBuilder, 0.5, 0.5)
TSpriteBuilder_Padding(GradientSpriteBuilder, 0, 128, 128, 0)
TSpriteBuilder_Border(GradientSpriteBuilder, 32, 32, 32, 32)
TSpriteBuilder_BorderScale(GradientSpriteBuilder, 0.5, 0.5)
Local GradientSprite.TSprite = TSprite_Create(GradientSpriteBuilder)
; Background Sprite
Local InvBGSpriteBuilder.TSpriteBuilder = TSpriteBuilder_Create()
TSpriteBuilder_Mesh(InvBGSpriteBuilder, InvMesh, 0, True)
TSpriteBuilder_Brush(InvBGSpriteBuilder, InvBrush)
TSpriteBuilder_BrushSize(InvBGSpriteBuilder, 256, 256)
TSpriteBuilder_Scale(InvBGSpriteBuilder, 0.5, 0.5)
TSpriteBuilder_Padding(InvBGSpriteBuilder, 128, 0, 0, 128)
TSpriteBuilder_Border(InvBGSpriteBuilder, 16, 16, 16, 16)
TSpriteBuilder_BorderScale(InvBGSpriteBuilder, 0.5, 0.5)
Local InvBGSprite.TSprite = TSprite_Create(InvBGSpriteBuilder)
; Other
Global FPSTimer = CreateTimer(30)
Local SpriteFillFlags = TSPRITE_BORDER_LFT + TSPRITE_BORDER_RGT + TSPRITE_BORDER_TOP + TSPRITE_BORDER_BTM
Local X#=256,Y#=256,W#=128,H#=128, Change = True
; Loop
While Not KeyHit(1)
Local MsX = MouseX(), MsY = MouseY(), MsZ = MouseZ()
Cls
If Change = True Then
TSprite_Fill(GradientSprite, -GraphicsWidth()/2 + X, -GraphicsHeight()/2 +Y, W, H, 0, SpriteFillFlags)
TSprite_Fill(InvGradientSprite, -GraphicsWidth()/2 + X + 4, -GraphicsHeight()/2 +Y + 4, W - 8, H - 8, 0, SpriteFillFlags)
Change = False
EndIf
WireFrame KeyDown(31)
RenderWorld
; Camera Movement
If MouseDown(1)
If MouseHit(1) Then
MoveMouse GraphicsWidth()/2, GraphicsHeight()/2
Else
eCameraPitch = eCameraPitch + (MouseYSpeed()/4.0)
eCameraYaw = eCameraYaw - (MouseXSpeed()/4.0)
EndIf
RotateEntity eCameraCenter, eCameraPitch, eCameraYaw, 0, True
EndIf
If MouseDown(2)
If MouseHit(2) Then
MoveMouse GraphicsWidth()/2, GraphicsHeight()/2
Else
eCameraZoom = eCameraZoom + (MouseYSpeed()/4.0) + (MouseXSpeed()/4.0)
If eCameraZoom < 1.0 Then eCameraZoom = 1.0
EndIf
PositionEntity eCamera, 0, 0, -eCameraZoom, False
EndIf
; Position & Size
If KeyDown(30) Then
X = MsX
Y = MsY
Change = True
EndIf
If KeyDown(32) Then
If MsX < X+8 Then X = MsX-8
If MsY < Y+8 Then Y = MsY-8
W = MsX - X
H = MsY - Y
If W < 16 Then W = 16
If H < 16 Then H = 16
Change = True
EndIf
; Update Status
If KeyHit(2) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_BORDER_LFT:Change = True
If KeyHit(3) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_BORDER_RGT:Change = True
If KeyHit(4) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_BORDER_TOP:Change = True
If KeyHit(5) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_BORDER_BTM:Change = True
If KeyHit(16) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_BORDEROUT_LFT:Change = True
If KeyHit(17) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_BORDEROUT_RGT:Change = True
If KeyHit(18) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_BORDEROUT_TOP:Change = True
If KeyHit(19) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_BORDEROUT_BTM:Change = True
If KeyHit(6) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_ROUNDDOWN_HORZ:Change = True
If KeyHit(7) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_ROUNDDOWN_VERT:Change = True
If KeyHit(20) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_PARTIAL_HORZ:Change = True
If KeyHit(21) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_PARTIAL_VERT:Change = True
If KeyHit(34) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_PARTIALCUT_HORZ:Change = True
If KeyHit(35) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_PARTIALCUT_VERT:Change = True
If KeyHit(47) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_FORCESINGLE_HORZ:Change = True
If KeyHit(48) Then SpriteFillFlags = SpriteFillFlags Xor TSPRITE_FORCESINGLE_VERT:Change = True
; Show Boundaries
If KeyDown(57)
Color 255,128,0
Rect X, Y, W, H, 0
Color 0,128,255
Rect X+8,Y+8,W-16,H-16,0
Color 255,255,255
EndIf
; Draw Some shit
Viewport X+8, Y+8, W-16, H-16
Local GUIText$ = "This simple technique allows you to fast transparent backgrounds." + Chr(10)
GUIText = GUIText + "I saw this being used in Unity3D to reduce drawcalls made and " + Chr(10)
GUIText = GUIText + "thought it would be a good idea to enhance it in a prototype " + Chr(10)
GUIText = GUIText + "before i reimplement it using new features." + Chr(10) + Chr(10)
GUIText = GUIText + "Maybe this is already used in Draw3D or will be integrated now." + Chr(10)
GUIText = GUIText + "Doesn't matter to me, have fun with this piece of code!" + Chr(10)
AdvText(X+8, Y+8, GUIText)
Viewport 0, 0, GraphicsWidth(), GraphicsHeight()
; Draw Status
If KeyDown(59) Then
Local HelpText$ = "Key Function Status" + Chr(10)
HelpText = HelpText + "-------------------------------" + Chr(10)
HelpText = HelpText + "LMB Move Camera: " + RSet(Int(eCameraPitch*10)/10.0, 8) + ", " + RSet(Int(eCameraYaw*10)/10.0, 8) + Chr(10)
HelpText = HelpText + "RMB Zoom Camera: " + RSet(Int(eCameraZoom*10)/10.0, 8) + Chr(10)
HelpText = HelpText + "Spc Show Boundaries" + Chr(10)
HelpText = HelpText + "A Set Position" + Chr(10)
HelpText = HelpText + "D Set Size" + Chr(10)
HelpText = HelpText + "S Show Wireframe" + Chr(10)
HelpText = HelpText + "1 Border-Lft: "
If SpriteFillFlags And TSPRITE_BORDER_LFT Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "2 Border-Rgt: "
If SpriteFillFlags And TSPRITE_BORDER_RGT Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "3 Border-Top: "
If SpriteFillFlags And TSPRITE_BORDER_TOP Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "4 Border-Btm: "
If SpriteFillFlags And TSPRITE_BORDER_BTM Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "Q BorderOut-Lft: "
If SpriteFillFlags And TSPRITE_BORDEROUT_LFT Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "W BorderOut-Rgt: "
If SpriteFillFlags And TSPRITE_BORDEROUT_RGT Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "E BorderOut-Top: "
If SpriteFillFlags And TSPRITE_BORDEROUT_TOP Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "R BorderOut-Btm: "
If SpriteFillFlags And TSPRITE_BORDEROUT_BTM Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "5 RoundDown-Horz: "
If SpriteFillFlags And TSPRITE_ROUNDDOWN_HORZ Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "6 RoundDown-Vert: "
If SpriteFillFlags And TSPRITE_ROUNDDOWN_VERT Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "T Partial-Horz: "
If SpriteFillFlags And TSPRITE_PARTIAL_HORZ Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "Z Partial-Vert: "
If SpriteFillFlags And TSPRITE_PARTIAL_VERT Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "G PartialCut-Horz: "
If SpriteFillFlags And TSPRITE_PARTIALCUT_HORZ Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "H PartialCut-Vert: "
If SpriteFillFlags And TSPRITE_PARTIALCUT_VERT Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "V ForceSingle-Horz: "
If SpriteFillFlags And TSPRITE_FORCESINGLE_HORZ Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
HelpText = HelpText + "B ForceSingle-Vert: "
If SpriteFillFlags And TSPRITE_FORCESINGLE_VERT Then HelpText = HelpText + "|f00FF00On|f-1-1-1" + Chr(10) Else HelpText = HelpText + "|fFF0000Off|f-1-1-1" + Chr(10)
AdvText(10, 0, HelpText)
Else
Text 0, 0, "F1 to show Help"
EndIf
WaitTimer FPSTimer:Flip 0
Wend
;~IDEal Editor Parameters:
;~C#Blitz3D
+9
View File
@@ -0,0 +1,9 @@
TiledSprite
=======================
Blitz3D didn't have a UI solution that worked well. There was Draw3D (& Draw3D2) which claimed to solve it, but in turn caused more issues than I had before it. Mainly the stupid Z-Ordering in Draw3D was annoying, as it didn't solve anything except add more data into RAM and VRAM. And it didn't work well for many things, such as skinned windows with stretched or repeating background, etc.
This library adds some neat little functions that allow you to create a "Tiled Sprite". It does that by cutting up the original texture using new vertices instead of adding more textures to memory or using a fancy shader.
License
=======
TiledSprite by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
@@ -0,0 +1,537 @@
;--------------------------------------------
; Constants
;--------------------------------------------
Const TSPRITE_BORDER_LFT% = 1 ; Enable border on the left side.
Const TSPRITE_BORDER_RGT% = 2 ; Enable border on the right side.
Const TSPRITE_BORDER_TOP% = 4 ; Enable border on the top side.
Const TSPRITE_BORDER_BTM% = 8 ; Enable border on the bottom side.
Const TSPRITE_BORDEROUT_LFT% = 16 ; Push the border outside the boundaries on the left side.
Const TSPRITE_BORDEROUT_RGT% = 32 ; Push the border outside the boundaries on the right side.
Const TSPRITE_BORDEROUT_TOP% = 64 ; Push the border outside the boundaries on the top side.
Const TSPRITE_BORDEROUT_BTM% = 128 ; Push the border outside the boundaries on the bottom side.
Const TSPRITE_ROUNDDOWN_HORZ% = 256 ; Round down instead of up horizontally (Disabled by TSPRITE_PARTIAL_HORZ).
Const TSPRITE_ROUNDDOWN_VERT% = 512 ; Round down instead of up vertically (Disabled by TSPRITE_PARTIAL_VERT).
Const TSPRITE_PARTIAL_HORZ% = 1024 ; Allow Partial scaling (last-element) instead of scaling all elements horizontally.
Const TSPRITE_PARTIAL_VERT% = 2048 ; Allow Partial scaling (last-element) instead of scaling all elements vertically.
Const TSPRITE_PARTIALCUT_HORZ% = 4096 ; Changes the mode of the Partial modifier to cutting, so that it doesn't scale horizontally.
Const TSPRITE_PARTIALCUT_VERT% = 8192 ; Changes the mode of the Partial modifier to cutting, so that it doesn't scale vertically.
Const TSPRITE_FORCESINGLE_HORZ% = 16384 ; Force to use only a single tile horizontally (for gradients and such).
Const TSPRITE_FORCESINGLE_VERT% = 32768 ; Force to use only a single tile vertically (for gradients and such).
Const HINT_LEFT% = 0
Const HINT_TOP% = 1
Const HINT_RIGHT% = 2
Const HINT_BOTTOM% = 3
;--------------------------------------------
; Types
;--------------------------------------------
Type TSprite
; Texture (Use this for animations).
Field mTexture% = 0
Field mTextureBrush% = 0
; Mesh & Surface
Field mMesh% = 0
Field mSurface% = 0
Field mShareSurface% = False
; Padding & Border
Field mPadding%[4]
Field mBorder%[4]
; Outer & Inner Coordinates in Pixels
Field mOuter%[4] ; Relative to mTexture in Pixels
Field mInner%[4] ; Relative to mTexture in Pixels
; Outer & Inner UV Coordinates in Texels
Field mOuterUV#[4] ;Relative to mTexture in Texels
Field mInnerUV#[4] ;Relative to mTexture in Texels
; Scale
Field mScale#[2]
Field mBorderScale#[2]
End Type
Type TSpriteBuilder
; Texture
Field Width% = 0
Field Height% = 0
Field TextureBrush% = 0
; Mesh & Surface
Field Mesh% = 0
Field MeshSurface% = 0
Field SharedSurface% = False
; Padding
Field PaddingLeft% = 0
Field PaddingTop% = 0
Field PaddingRight% = 0
Field PaddingBottom% = 0
; Border
Field BorderLeft% = 0
Field BorderTop% = 0
Field BorderRight% = 0
Field BorderBottom% = 0
; Scale
Field ScaleX# = 1
Field ScaleY# = 1
Field BorderScaleX# = 1
Field BorderScaleY# = 1
; Internal Flags
Field OwnBrush% = True
Field OwnMesh% = True
Field OwnMeshSurface% = True
End Type
;--------------------------------------------
; Functions
;--------------------------------------------
; TSpriteBuilder
Function TSpriteBuilder_Create.TSpriteBuilder()
Local SpriteBuilder.TSpriteBuilder = New TSpriteBuilder
SpriteBuilder\TextureBrush = CreateBrush(1.0, 1.0, 1.0)
SpriteBuilder\Mesh = CreateMesh()
SpriteBuilder\MeshSurface = CreateSurface(SpriteBuilder\Mesh)
Return SpriteBuilder
End Function
Function TSpriteBuilder_Padding.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, PaddingLeft%, PaddingTop%, PaddingRight%, PaddingBottom%)
If SpriteBuilder <> Null Then
SpriteBuilder\PaddingLeft = PaddingLeft
SpriteBuilder\PaddingTop = PaddingTop
SpriteBuilder\PaddingRight = PaddingRight
SpriteBuilder\PaddingBottom = PaddingBottom
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_Scale.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, ScaleX#, ScaleY#)
If SpriteBuilder <> Null Then
SpriteBuilder\ScaleX = ScaleX
SpriteBuilder\ScaleY = ScaleY
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_Border.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, BorderLeft%, BorderTop%, BorderRight%, BorderBottom%)
If SpriteBuilder <> Null Then
SpriteBuilder\BorderLeft = BorderLeft
SpriteBuilder\BorderTop = BorderTop
SpriteBuilder\BorderRight = BorderRight
SpriteBuilder\BorderBottom = BorderBottom
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_BorderScale.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, BorderScaleX#, BorderScaleY#)
If SpriteBuilder <> Null Then
SpriteBuilder\BorderScaleX = BorderScaleX
SpriteBuilder\BorderScaleY = BorderScaleY
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_Brush.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, Brush%)
If SpriteBuilder <> Null And Brush <> 0 Then
If SpriteBuilder\OwnBrush = True And SpriteBuilder\TextureBrush <> 0 Then FreeBrush SpriteBuilder\TextureBrush
SpriteBuilder\TextureBrush = Brush
If SpriteBuilder\MeshSurface <> 0 Then PaintSurface SpriteBuilder\MeshSurface, SpriteBuilder\TextureBrush
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_BrushSize.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, BrushW%, BrushH%)
If SpriteBuilder <> Null And SpriteBuilder\TextureBrush <> 0 Then
SpriteBuilder\Width = BrushW
SpriteBuilder\Height = BrushH
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_BrushAlpha.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, Alpha#)
If SpriteBuilder <> Null And SpriteBuilder\TextureBrush <> 0 Then
BrushAlpha SpriteBuilder\TextureBrush, Alpha
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_BrushBlend.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, Blend%)
If SpriteBuilder <> Null And SpriteBuilder\TextureBrush <> 0 Then
BrushBlend SpriteBuilder\TextureBrush, Blend
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_BrushColor.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, Red#, Green#, Blue#)
If SpriteBuilder <> Null And SpriteBuilder\TextureBrush <> 0 Then
BrushColor SpriteBuilder\TextureBrush, Red, Green, Blue
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_BrushFX.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, FX%)
If SpriteBuilder <> Null And SpriteBuilder\TextureBrush <> 0 Then
BrushFX SpriteBuilder\TextureBrush, FX
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_BrushShininess.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, Shininess#)
If SpriteBuilder <> Null And SpriteBuilder\TextureBrush <> 0 Then
BrushShininess SpriteBuilder\TextureBrush, Shininess
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_BrushTexture.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, Texture%, Frame% = 0, Index% = 0)
If SpriteBuilder <> Null And Texture <> 0 Then
BrushTexture SpriteBuilder\TextureBrush, Texture, Frame, Index
SpriteBuilder\Width = TextureWidth(Texture)
SpriteBuilder\Height = TextureHeight(Texture)
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_Mesh.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, Mesh% = 0, MeshSurface% = 0, ShareSurface = False)
If SpriteBuilder <> Null Then
If SpriteBuilder\OwnMesh Then FreeEntity SpriteBuilder\Mesh
If Mesh = 0 Then
SpriteBuilder\Mesh = CreateMesh()
SpriteBuilder\OwnMesh = True
Else
SpriteBuilder\Mesh = Mesh
SpriteBuilder\OwnMesh = False
EndIf
TSpriteBuilder_MeshSurface(SpriteBuilder, MeshSurface, ShareSurface)
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_MeshSurface.TSpriteBuilder(SpriteBuilder.TSpriteBuilder, MeshSurface% = 0, ShareSurface% = False)
If SpriteBuilder <> Null And SpriteBuilder\Mesh <> 0 Then
If MeshSurface = 0 Then
If SpriteBuilder\OwnMeshSurface = False Then SpriteBuilder\MeshSurface = CreateSurface(SpriteBuilder\Mesh, SpriteBuilder\TextureBrush)
SpriteBuilder\OwnMeshSurface = True
ElseIf MeshSurface <> 0 Then
SpriteBuilder\MeshSurface = MeshSurface
SpriteBuilder\OwnMeshSurface = False
EndIf
If SpriteBuilder\TextureBrush <> 0 Then PaintSurface SpriteBuilder\MeshSurface, SpriteBuilder\TextureBrush
SpriteBuilder\SharedSurface = ShareSurface
Return SpriteBuilder
EndIf
Return Null
End Function
Function TSpriteBuilder_Reset.TSpriteBuilder(SpriteBuilder.TSpriteBuilder)
If SpriteBuilder <> Null Then
If SpriteBuilder\OwnMesh Then FreeEntity SpriteBuilder\Mesh
If SpriteBuilder\OwnBrush Then FreeBrush SpriteBuilder\TextureBrush
Delete SpriteBuilder
Return New TSpriteBuilder
EndIf
End Function
; TSprite
Function TSprite_Create.TSprite(SpriteBuilder.TSpriteBuilder)
If SpriteBuilder <> Null And SpriteBuilder\Mesh <> 0 And SpriteBuilder\MeshSurface <> 0 And SpriteBuilder\TextureBrush <> 0 Then
Local Sprite.TSprite = New TSprite
Local Width# = SpriteBuilder\Width
Local Height# = SpriteBuilder\Height
; Mesh & Surface.
Sprite\mMesh = SpriteBuilder\Mesh
Sprite\mSurface = SpriteBuilder\MeshSurface
Sprite\mShareSurface = SpriteBuilder\SharedSurface
; Texture.
Sprite\mTextureBrush = SpriteBuilder\TextureBrush
; Padding.
Sprite\mPadding[0] = SpriteBuilder\PaddingLeft
Sprite\mPadding[1] = SpriteBuilder\PaddingTop
Sprite\mPadding[2] = SpriteBuilder\PaddingRight
Sprite\mPadding[3] = SpriteBuilder\PaddingBottom
; Border.
Sprite\mBorder[0] = SpriteBuilder\BorderLeft
Sprite\mBorder[1] = SpriteBuilder\BorderTop
Sprite\mBorder[2] = SpriteBuilder\BorderRight
Sprite\mBorder[3] = SpriteBuilder\BorderBottom
; Scale.
Sprite\mScale[0] = SpriteBuilder\ScaleX
Sprite\mScale[1] = SpriteBuilder\ScaleY
Sprite\mBorderScale[0] = SpriteBuilder\BorderScaleX
Sprite\mBorderScale[1] = SpriteBuilder\BorderScaleY
; Calculate Outer Limits.
Sprite\mOuter[0] = Sprite\mPadding[0]
Sprite\mOuter[1] = Sprite\mPadding[1]
Sprite\mOuter[2] = Width - Sprite\mPadding[2]
Sprite\mOuter[3] = Height - Sprite\mPadding[3]
; Calculate Inner Limits.
Sprite\mInner[0] = Sprite\mOuter[0] + Sprite\mBorder[0]
Sprite\mInner[1] = Sprite\mOuter[1] + Sprite\mBorder[1]
Sprite\mInner[2] = Sprite\mOuter[2] - Sprite\mBorder[2]
Sprite\mInner[3] = Sprite\mOuter[3] - Sprite\mBorder[3]
; Convert Outer Limits to valid UV coordinates.
Sprite\mOuterUV[0] = Sprite\mOuter[0] / Width
Sprite\mOuterUV[1] = Sprite\mOuter[1] / Height
Sprite\mOuterUV[2] = Sprite\mOuter[2] / Width
Sprite\mOuterUV[3] = Sprite\mOuter[3] / Height
; Convert Inner Limits to valid UV coordinates.
Sprite\mInnerUV[0] = Sprite\mInner[0] / Width
Sprite\mInnerUV[1] = Sprite\mInner[1] / Height
Sprite\mInnerUV[2] = Sprite\mInner[2] / Width
Sprite\mInnerUV[3] = Sprite\mInner[3] / Height
Return Sprite
EndIf
Return Null
End Function
Function TSprite_Fill(Sprite.TSprite, X#, Y#, Width#, Height#, Z#=0, Modes%=0)
Local TileX%, TileXPos#, TileXPosE#, TileWidth#, TileHMult#, TileCountH#, TileCountH2, TempHMult#, TileUVLeft#, TileUVRight#
Local TileY%, TileYPos#, TileYPosE#, TileHeight#, TileVMult#, TileCountV#, TileCountV2, TempVMult#, TileUVTop#, TileUVBottom#
If Sprite <> Null And Sprite\mSurface <> 0 And Width > 0 And Height > 0 Then
If Sprite\mShareSurface = False Then ClearSurface(Sprite\mSurface)
; Translate Mode into easily used variables.
Local BorderLft = ((Modes And TSPRITE_BORDER_LFT) > 0)
Local BorderRgt = ((Modes And TSPRITE_BORDER_RGT) > 0)
Local BorderTop = ((Modes And TSPRITE_BORDER_TOP) > 0)
Local BorderBtm = ((Modes And TSPRITE_BORDER_BTM) > 0)
Local BorderOutLft = (-1 + ((Modes And TSPRITE_BORDEROUT_LFT) > 0))
Local BorderOutRgt = (-1 + ((Modes And TSPRITE_BORDEROUT_RGT) > 0))
Local BorderOutTop = (-1 + ((Modes And TSPRITE_BORDEROUT_TOP) > 0))
Local BorderOutBtm = (-1 + ((Modes And TSPRITE_BORDEROUT_BTM) > 0))
Local RoundDownH = ((Modes And TSPRITE_ROUNDDOWN_HORZ) > 0)
Local RoundDownV = ((Modes And TSPRITE_ROUNDDOWN_VERT) > 0)
Local PartialH = ((Modes And TSPRITE_PARTIAL_HORZ) > 0)
Local PartialV = ((Modes And TSPRITE_PARTIAL_VERT) > 0)
Local PartialCutH = ((Modes And TSPRITE_PARTIALCUT_HORZ) > 0)
Local PartialCutV = ((Modes And TSPRITE_PARTIALCUT_VERT) > 0)
Local ForceSingleH = ((Modes And TSPRITE_FORCESINGLE_HORZ) > 0)
Local ForceSingleV = ((Modes And TSPRITE_FORCESINGLE_VERT) > 0)
; Calculate scaled sizes.
Local SpriteBorder#[4]
SpriteBorder[0] = (Sprite\mBorder[0] * Sprite\mBorderScale[0]) * BorderLft
SpriteBorder[2] = (Sprite\mBorder[2] * Sprite\mBorderScale[0]) * BorderRgt
SpriteBorder[1] = (Sprite\mBorder[1] * Sprite\mBorderScale[0]) * BorderTop
SpriteBorder[3] = (Sprite\mBorder[3] * Sprite\mBorderScale[0]) * BorderBtm
Local SpriteSize#[2]
SpriteSize[0] = (Sprite\mInner[2]-Sprite\mInner[0])*Sprite\mScale[0]
SpriteSize[1] = (Sprite\mInner[3]-Sprite\mInner[1])*Sprite\mScale[1]
; Calculate real values.
Local RealWidth# = Width + (SpriteBorder[0] * BorderOutLft) + (SpriteBorder[2] * BorderOutRgt)
Local RealHeight# = Height + (SpriteBorder[1] * BorderOutTop) + (SpriteBorder[3] * BorderOutBtm)
; Recalculate scaled border if we are below minimum size.
Local BorderScale#[4], BorderMaximum#[2], SizeScale#[2]
BorderMaximum[0] = ((SpriteBorder[0] * -BorderOutLft) + (SpriteBorder[2] * -BorderOutRgt))
BorderMaximum[1] = ((SpriteBorder[1] * -BorderOutTop) + (SpriteBorder[3] * -BorderOutBtm))
If Width < BorderMaximum[0] Then
SizeScale[0] = (Width / BorderMaximum[0])
SpriteBorder[0] = SpriteBorder[0] * SizeScale[0]
SpriteBorder[2] = SpriteBorder[2] * SizeScale[0]
RealWidth = 0
EndIf
If Height < BorderMaximum[1] Then
SizeScale[1] = (Height / BorderMaximum[1])
SpriteBorder[1] = SpriteBorder[1] * SizeScale[1]
SpriteBorder[3] = SpriteBorder[3] * SizeScale[1]
RealHeight = 0
EndIf
; Calculate Position
Local RealX# = X - (SpriteBorder[0] * BorderOutLft)
Local RealY# = -(Y - (SpriteBorder[1] * BorderOutTop))
; Calculate tiles.
If ForceSingleH = 0 Then
If RealWidth > 0 Then TileCountH = RealWidth / SpriteSize[0] Else TileCountH = 0
Else
TileCountH = 1
EndIf
If ForceSingleV = 0 Then
If RealHeight > 0 Then TileCountV = RealHeight / SpriteSize[1] Else TileCountV = 0
Else
TileCountV = 1
EndIf
If PartialH = 1 Or RoundDownH = 0 Then TileCountH2 = Ceil(TileCountH) Else TileCountH2 = Floor(TileCountH)
If PartialV = 1 Or RoundDownV = 0 Then TileCountV2 = Ceil(TileCountV) Else TileCountV2 = Floor(TileCountV)
If PartialH = 1 Then TileWidth = (RealWidth / TileCountH) Else TileWidth = (RealWidth / TileCountH2)
If PartialV = 1 Then TileHeight = (RealHeight / TileCountV) Else TileHeight = (RealHeight / TileCountV2)
If (TileCountH2 < 0) Then TileCountH2 = 0 Else TileCountH2 = TileCountH2 - 1
If (TileCountV2 < 0) Then TileCountV2 = 0 Else TileCountV2 = TileCountV2 - 1
; Calculate Partial scale
If PartialH = 1 Then TileHMult = TileCountH - TileCountH2
If PartialV = 1 Then TileVMult = TileCountV - TileCountV2
; Draw Corners
If SpriteBorder[1] > 0 Then
If (BorderTop And BorderLft And SpriteBorder[0] > 0) Then TSprite_CreateQuad(Sprite\mSurface, RealX - SpriteBorder[0], RealX, RealY + SpriteBorder[1], RealY, 0, 0, Sprite\mOuterUV[0], Sprite\mInnerUV[0], Sprite\mOuterUV[1], Sprite\mInnerUV[1])
If (BorderTop And BorderRgt And SpriteBorder[2] > 0) Then TSprite_CreateQuad(Sprite\mSurface, RealX + RealWidth, RealX + RealWidth + SpriteBorder[2], RealY + SpriteBorder[1], RealY, Z, Z, Sprite\mInnerUV[2], Sprite\mOuterUV[2], Sprite\mOuterUV[1], Sprite\mInnerUV[1])
EndIf
If SpriteBorder[3] > 0 Then
If (BorderBtm And BorderLft And SpriteBorder[0] > 0) Then TSprite_CreateQuad(Sprite\mSurface, RealX - SpriteBorder[0], RealX, RealY - RealHeight, RealY - RealHeight - SpriteBorder[3], Z, Z, Sprite\mOuterUV[0], Sprite\mInnerUV[0], Sprite\mInnerUV[3], Sprite\mOuterUV[3])
If (BorderBtm And BorderRgt And SpriteBorder[2] > 0) Then TSprite_CreateQuad(Sprite\mSurface, RealX + RealWidth, RealX + RealWidth + SpriteBorder[2], RealY - RealHeight, RealY - RealHeight - SpriteBorder[1], Z, Z, Sprite\mInnerUV[2], Sprite\mOuterUV[2], Sprite\mInnerUV[3], Sprite\mOuterUV[3])
EndIf
For TileX% = 0 To TileCountH2
; Horizontal coordinates and UV.
TileXPos = RealX + (TileX * TileWidth)
TileXPosE = TileXPos + TileWidth
TileUVLeft = Sprite\mInnerUV[0]
TileUVRight = Sprite\mInnerUV[2]
; Support for partial horizontal tiles.
If PartialH And TileX = TileCountH2 Then
TileXPosE = TileXPos + (TileWidth * TileHMult)
If PartialCutH Then TileUVRight = (TileUVLeft * (1-TileHMult)) + (TileUVRight * TileHMult)
EndIf
For TileY% = 0 To TileCountV2
; Vertical coordinates and UV.
TileYPos = RealY - (TileY * TileHeight)
TileYPosE = TileYPos - TileHeight
TileUVTop = Sprite\mInnerUV[1]
TileUVBottom = Sprite\mInnerUV[3]
; Support for partial vertical tiles.
If PartialV And TileY = TileCountV2 Then
TileYPosE = TileYPos - (TileHeight * TileVMult)
If PartialCutV Then TileUVBottom = (TileUVTop * (1-TileVMult)) + (TileUVBottom * TileVMult)
EndIf
; Tiles
TSprite_CreateQuad(Sprite\mSurface, TileXPos, TileXPosE, TileYPos, TileYPosE, Z, Z, TileUVLeft, TileUVRight, TileUVTop, TileUVBottom)
Next
; Horizontal Border
If (BorderTop) Then TSprite_CreateQuad(Sprite\mSurface, TileXPos, TileXPosE, RealY + SpriteBorder[1], RealY, Z, Z, TileUVLeft, TileUVRight, Sprite\mOuterUV[1], Sprite\mInnerUV[1])
If (BorderBtm) Then TSprite_CreateQuad(Sprite\mSurface, TileXPos, TileXPosE, RealY - RealHeight, RealY - RealHeight - SpriteBorder[3], Z, Z, TileUVLeft, TileUVRight, Sprite\mInnerUV[3], Sprite\mOuterUV[3])
Next
For TileY% = 0 To TileCountV2
; Vertical coordinates and UV.
TileYPos = RealY - (TileY * TileHeight)
TileYPosE = TileYPos - TileHeight
TileUVTop = Sprite\mInnerUV[1]
TileUVBottom = Sprite\mInnerUV[3]
; Support for partial vertical tiles.
If PartialV And TileY = TileCountV2 Then
TileYPosE = TileYPos - (TileHeight * TileVMult)
If PartialCutV Then TileUVBottom = (TileUVTop * (1-TileVMult)) + (TileUVBottom * TileVMult)
EndIf
; Vertical Border
If (BorderLft) Then TSprite_CreateQuad(Sprite\mSurface, RealX - SpriteBorder[0], RealX, TileYPos, TileYPosE, Z, Z, Sprite\mOuterUV[0], Sprite\mInnerUV[0], TileUVTop, TileUVBottom)
If (BorderRgt) Then TSprite_CreateQuad(Sprite\mSurface, RealX + RealWidth, RealX + RealWidth + SpriteBorder[2], TileYPos, TileYPosE, Z, Z, Sprite\mInnerUV[2], Sprite\mOuterUV[2], TileUVTop, TileUVBottom)
Next
EndIf
End Function
Function TSprite_CreateQuad(Surface%, X0#, X1#, Y0#, Y1#, Z0#, Z1#, U0# = 0, U1# = 0, V0# = 0, V1# = 0, W0# = 0, W1# = 0, TurnOrder% = 0, ShareVertices% = True)
Local TrisOut% = 0
Local vTL, vBL, vTR, vBR
vTL = AddVertex(Surface, X0, Y0, Z0, U0, V0, W0)
vTR = AddVertex(Surface, X1, Y0, (Z0+Z1)/2, U1, V0, (W0+W1)/2)
vBL = AddVertex(Surface, X0, Y1, (Z0+Z1)/2, U0, V1, (W0+W1)/2)
vBR = AddVertex(Surface, X1, Y1, Z1, U1, V1, W1)
If ShareVertices Then
If (TurnOrder) Then
TrisOut = TrisOut + AddTriangle(Surface, vBL, vTL, vTR) Shl 16
TrisOut = TrisOut + AddTriangle(Surface, vBL, vTR, vBR)
Else
TrisOut = TrisOut + AddTriangle(Surface, vTL, vTR, vBR) Shl 16
TrisOut = TrisOut + AddTriangle(Surface, vTL, vBR, vBL)
EndIf
Else
If TurnOrder Then
Local vTR2, vBL2
vTR2 = AddVertex(Surface, X1, Y0, (Z0+Z1)/2, U1, V0, (W0+W1)/2)
vBL2 = AddVertex(Surface, X0, Y1, (Z0+Z1)/2, U0, V1, (W0+W1)/2)
TrisOut = TrisOut + AddTriangle(Surface, vBL, vTL, vTR) Shl 16
TrisOut = TrisOut + AddTriangle(Surface, vBL2, vTR2, vBR)
Else
Local vTL2, vBR2
vTL2 = AddVertex(Surface, X0, Y0, Z0, U0, V0, W0)
vBR2 = AddVertex(Surface, X1, Y1, Z1, U1, V1, W1)
TrisOut = TrisOut + AddTriangle(Surface, vTL, vTR, vBR) Shl 16
TrisOut = TrisOut + AddTriangle(Surface, vTL2, vBR2, vBL)
EndIf
EndIf
Return TrisOut
End Function
Function TSprite_CreateQuadEx(Surface%, X0#, X1#, Y0#, Y1#, Z0#, Z1#, U0# = 0, U1# = 0, V0# = 0, V1# = 0, W0# = 0, W1# = 0, ShareVertices% = True)
Local vTL, vTR, vCC, vBL, vBR
vTL = AddVertex(Surface, X0, Y0, Z0, U0, V0, W0)
vTR = AddVertex(Surface, X1, Y0, (Z0+Z1)/2, U1, V0, (W0+W1)/2)
vCC = AddVertex(Surface, (X0+X1)/2, (Y0+Y1)/2, (Z0+Z1)/2, (U0+U1)/2, (V0+V1)/2, (W0+W1)/2)
vBL = AddVertex(Surface, X0, Y1, (Z0+Z1)/2, U0, V1, (W0+W1)/2)
vBR = AddVertex(Surface, X1, Y1, Z1, U1, V1, W1)
If ShareVertices Then
AddTriangle(Surface, vTL, vTR, vCC)
AddTriangle(Surface, vBL, vTL, vCC)
AddTriangle(Surface, vTR, vBR, vCC)
AddTriangle(Surface, vBL, vBR, vCC)
Else
Local vTL2, vTR2, vBL2, vBR2, vCC2, vCC3, vCC4
vTL2 = AddVertex(Surface, X0, Y0, Z0, U0, V0, W0)
vTR2 = AddVertex(Surface, X1, Y0, (Z0+Z1)/2, U1, V0, (W0+W1)/2)
vBL2 = AddVertex(Surface, X0, Y1, (Z0+Z1)/2, U0, V1, (W0+W1)/2)
vBR2 = AddVertex(Surface, X1, Y1, Z1, U1, V1, W1)
vCC2 = AddVertex(Surface, (X0+X1)/2, (Y0+Y1)/2, (Z0+Z1)/2, (U0+U1)/2, (V0+V1)/2, (W0+W1)/2)
vCC3 = AddVertex(Surface, (X0+X1)/2, (Y0+Y1)/2, (Z0+Z1)/2, (U0+U1)/2, (V0+V1)/2, (W0+W1)/2)
vCC4 = AddVertex(Surface, (X0+X1)/2, (Y0+Y1)/2, (Z0+Z1)/2, (U0+U1)/2, (V0+V1)/2, (W0+W1)/2)
AddTriangle(Surface, vTL, vTR, vCC)
AddTriangle(Surface, vBL, vTL2, vCC2)
AddTriangle(Surface, vTR2, vBR, vCC3)
AddTriangle(Surface, vBL2, vBR2, vCC4)
EndIf
End Function
;~IDEal Editor Parameters:
;~F#1C#36#5D#65#70#79#84#8D#98#A2#AA#B2#BA#C2#CA#D5#E6#F7#102#1D3
;~F#1F8
;~C#Blitz3D
Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

@@ -0,0 +1,85 @@
;----------------------------------------------------------------
;-- Types
;----------------------------------------------------------------
Type BU_Rectangle
Field X,Y
Field X2,Y2
End Type
Type BU_Point
Field X,Y
End Type
;----------------------------------------------------------------
;----------------------------------------------------------------
;-- Global
;----------------------------------------------------------------
Global Utility_Rect.BU_Rectangle = New BU_Rectangle
Global Utility_Point.BU_Point = New BU_Point
Global Utility_PrivateProfileBuffer = CreateBank(65535)
;----------------------------------------------------------------
;----------------------------------------------------------------
;-- Functions
;----------------------------------------------------------------
Function Utility_LockPointerToWindow(hwnd=0)
If hwnd = 0 Then
Utility_Rect\X = 0
Utility_Rect\Y = 0
Utility_Rect\X2 = BUApi_GetSystemMetrics(78)
Utility_Rect\Y2 = BUApi_GetSystemMetrics(79)
BUApi_ClipCursor(Utility_Rect)
Else
;Grab TopLeft
Utility_Point\X = 0
Utility_Point\Y = 0
BUApi_ClientToScreen(hwnd, Utility_Point)
Utility_Rect\X = Utility_Point\X
Utility_Rect\Y = Utility_Point\Y
;Grab BottomRight
Utility_Point\X = GraphicsWidth()
Utility_Point\Y = GraphicsHeight()
BUApi_ClientToScreen(hwnd, Utility_Point)
Utility_Rect\X2 = Utility_Point\X
Utility_Rect\Y2 = Utility_Point\Y
BUApi_ClipCursor(Utility_Rect)
EndIf
End Function
Function Utility_BorderlessWindowmode(Title$="", MonitorId=0)
Local hWnd = SystemProperty("AppHwnd")
If hWnd = 0 Then hWnd = BUApi_FindWindow("Blitz Runtime Class", Title)
If hWnd = 0 Then RuntimeError("Unable to create borderless window.")
Utility_EnumerateDisplays()
Local dispCnt = Utility_GetDisplayCount()
If MonitorId < 0 Then MonitorId = 0
If MonitorId >= dispCnt Then MonitorId = dispCnt -1
Local rct.BU_Rectangle = New BU_Rectangle
Utility_GetDisplay(MonitorId, rct)
BUApi_SetWindowLong hWnd, -16, $01000000
BUApi_SetWindowPos hWnd, 0, rct\X, rct\Y, rct\X2, rct\Y2, 64
End Function
Function Utility_GetIniString$(File$, Section$, Key$, Def$)
Local wLen% = BUApi_GetPrivateProfileString(Section, Key, Def, Utility_PrivateProfileBuffer, 65535, File)
If wLen > 0 Then
Local wOut$ = ""
Local wPos = 1
While (wPos < wLen)
wOut = wOut + Chr(PeekByte(Utility_PrivateProfileBuffer, wPos - 1))
wPos=wPos+1
Wend
Return wOut
EndIf
End Function
Function Utility_SetIniString(File$, Section$, Key$, Value$)
Return (BUApi_SetPrivateProfileString(Section, Key, Value, File) = 1)
End Function
;~IDEal Editor Parameters:
;~C#Blitz3D
@@ -0,0 +1,137 @@
/*----------------------------------------------------------------*\
| Linker Options: -static-libgcc -static-libstdc++
| Linker Libraries: user32
\*----------------------------------------------------------------*/
#Include <windows.h>
struct Display {
int left;
int top;
int right;
int bottom;
Display* nextDisplay;
Display* prevDisplay;
};
Display* firstDisplay = NULL;
Display* lastDisplay = NULL;
BOOL CALLBACK _EnumerateDisplaysProcedure(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData);
STDAPIV_(void) Utility_EnumerateDisplays() {
/* Clean up the Linked List first. */
if (firstDisplay) {
Display* displayPointer = firstDisplay;
while(displayPointer) {
Display* thisDisplay = displayPointer;
displayPointer = displayPointer->nextDisplay;
delete thisDisplay;
}
firstDisplay = NULL;
lastDisplay = NULL;
}
EnumDisplayMonitors(NULL, NULL, _EnumerateDisplaysProcedure, 0);
}
BOOL CALLBACK _EnumerateDisplaysProcedure(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
Display* thisDisplay = new Display;
ZeroMemory(thisDisplay,sizeof(thisDisplay));
if (!firstDisplay) firstDisplay = thisDisplay;
if (!lastDisplay) {
lastDisplay = thisDisplay;
} else {
lastDisplay->nextDisplay = thisDisplay;
thisDisplay->prevDisplay = lastDisplay;
}
thisDisplay->left = lprcMonitor->left;
thisDisplay->top = lprcMonitor->top;
thisDisplay->right = lprcMonitor->right;
thisDisplay->bottom = lprcMonitor->bottom;
lastDisplay = thisDisplay;
return TRUE;
}
STDAPIV_(int) Utility_GetDisplayCount() {
int displayCount = 0;
Display* displayPointer = firstDisplay;
while (displayPointer) {
displayCount++;
displayPointer = displayPointer->nextDisplay;
}
return displayCount;
}
STDAPIV_(void) Utility_GetDisplay(int displayId, LPRECT display) {
int displayCount = 0;
Display* displayPointer = firstDisplay;
while (displayPointer) {
if ((displayCount == displayId) && (display) && (displayPointer)) {
display->left = displayPointer->left;
display->top = displayPointer->top;
display->right = displayPointer->right;
display->bottom = displayPointer->bottom;
}
displayCount++;
displayPointer = displayPointer->nextDisplay;
}
}
LRESULT CALLBACK _CloseWindowProcedure(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
struct WindowUserData {
Int oldWindowProcedure;
Int oldUserData;
Int closeCount;
};
STDAPIV_(void) Utility_InstallCloseHandler(HWND hwnd) {
If (hwnd) {
WindowUserData* hwndData = New WindowUserData;
ZeroMemory(hwndData, sizeof(hwndData));
hwndData->oldWindowProcedure = SetWindowLong(hwnd, GWL_WNDPROC, (LONG)&_CloseWindowProcedure);
hwndData->oldUserData = SetWindowLong(hwnd, GWL_USERDATA, (LONG)hwndData);
}
}
STDAPIV_(void) Utility_UninstallCloseHandler(HWND hwnd) {
If (hwnd) {
WindowUserData* hwndData = (WindowUserData*)GetWindowLong(hwnd, GWL_USERDATA);
If (hwndData) {
SetWindowLong(hwnd, GWL_USERDATA, hwndData->oldUserData);
SetWindowLong(hwnd, GWL_WNDPROC, hwndData->oldWindowProcedure);
Delete hwndData;
}
}
}
STDAPIV_(Int) Utility_GetCloseCount(HWND hwnd) {
If (hwnd) {
WindowUserData* hwndData = (WindowUserData*)GetWindowLong(hwnd, GWL_USERDATA);
If (hwndData) {
Int toReturn = hwndData->closeCount;
hwndData->closeCount = 0;
Return toReturn;
}
}
Return 0;
}
LRESULT CALLBACK _CloseWindowProcedure(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
WindowUserData* hwndData = (WindowUserData*)GetWindowLong(hwnd, GWL_USERDATA);
If (hwndData) {
switch(uMsg) {
Case WM_CLOSE:
Case WM_DESTROY:
hwndData->closeCount++;
Return False;
Default:
Return CallWindowProc((WNDPROC)hwndData->oldWindowProcedure, hwnd, uMsg, wParam, lParam);
}
} Else {
Return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {return TRUE;}
@@ -0,0 +1,20 @@
.lib "User32.dll"
BUApi_SetWindowLong%(hwnd%, nIndex%, dwNewLong%):"SetWindowLongA"
BUApi_GetWindowLong%(hwnd%, index%):"GetWindowLongA"
BUApi_SetWindowPos%(hwnd%, hWndInsertAfter%, x%, y%, cx%, cy%, wFlags%):"SetWindowPos"
BUApi_ClientToScreen%(hwnd%, point*):"ClientToScreen"
BUApi_ClipCursor%(rect*):"ClipCursor"
BUApi_GetSystemMetrics%(index%):"GetSystemMetrics"
BUApi_FindWindow%(class$, title$):"FindWindowA"
.lib "Kernel32.dll"
BUApi_GetPrivateProfileString%(lpszAppName$, lpszKeyName$, lpszDefault$, lpReturnedString*, nSize%, lpszFileName$):"GetPrivateProfileStringA"
BUApi_SetPrivateProfileString%(lpszAppName$, lpszKeyName$, lpszString$, lpszFileName$):"WritePrivateProfileStringA"
.lib "BlitzUtility.dll"
Utility_InstallCloseHandler(hwnd%):"Utility_InstallCloseHandler"
Utility_UninstallCloseHandler(hwnd%):"Utility_UninstallCloseHandler"
Utility_GetCloseCount%(hwnd%):"Utility_GetCloseCount"
Utility_EnumerateDisplays():"Utility_EnumerateDisplays"
Utility_GetDisplayCount%():"Utility_GetDisplayCount"
Utility_GetDisplay(id%, rectangle*):"Utility_GetDisplay"
@@ -0,0 +1,9 @@
BlitzUtility
=======================
The beaty of C++ and how fast you can do something in it. I didn't want to mess around with unsafe pointers and invalid stacks in BlitzBasic, so instead I just wrote it in C++ and made the code public.
Documentation at: http://www.blitzforum.de/forum/viewtopic.php?p=405650#405650
License
=======
BlitzUtility by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+322
View File
@@ -0,0 +1,322 @@
;----------------------------------------------------------------
;-- Userlib
;----------------------------------------------------------------
;.lib "User32.dll"
;User32_FindWindow%(class$, title$):"FindWindowA"
;User32_GetActiveWindow%():"GetActiveWindow"
;User32_GetCursorPosition%(point*):"GetCursorPos"
;User32_ScreenToClient%(hwnd%, point*):"ScreenToClient"
;User32_MapVirtualKeyEx%(code%, mapType%, dwhkl%):"MapVirtualKeyExA"
;User32_GetAsyncKeyState%(vkey%):"GetAsyncKeyState"
;
;.lib " "
;InputEx_Init()
;InputEx_Update()
;InputEx_VKeyTime%(VirtualKey%)
;InputEx_VKeyDownEx%(VirtualKey%)
;InputEx_VKeyDown%(VirtualKey%)
;InputEx_VKeyHitEx%(VirtualKey%)
;InputEx_VKeyHit%(VirtualKey%)
;InputEx_KeyTime%(ScanCode%)
;InputEx_KeyDownEx%(ScanCode%)
;InputEx_KeyDown%(ScanCode%)
;InputEx_KeyHitEx%(ScanCode%)
;InputEx_KeyHit%(ScanCode%)
;InputEx_MouseTime%(Button%)
;InputEx_MouseDownEx%(Button%)
;InputEx_MouseDown%(Button%)
;InputEx_MouseHitEx%(Button%)
;InputEx_MouseHit%(Button%)
;KeyTime%(Key%)
;KeyDownEx%(Key%)
;KeyHitEx%(Key%)
;MouseTime%(Button%)
;MouseDownEx%(Button%)
;MouseHitEx%(Button%)
;----------------------------------------------------------------
;----------------------------------------------------------------
;-- Types
;----------------------------------------------------------------
Type Point
Field X,Y
End Type
;----------------------------------------------------------------
;----------------------------------------------------------------
;-- Globals
;----------------------------------------------------------------
Global InputEx_Window = SystemProperty("AppHWND"), InputEx_ForMe = True
Global InputEx_Mouse.Point = New Point
Global InputEx_Width = GraphicsWidth()
Global InputEx_Height = GraphicsHeight()
Dim InputEx_State(256)
Dim InputEx_StateTime(256)
Dim InputEx_StateUpdates(256)
Dim InputEx_Hits(256)
Dim InputEx_VSCAsVK(256)
;----------------------------------------------------------------
;----------------------------------------------------------------
;-- Functions
;----------------------------------------------------------------
Function InputEx_Init(applicationTitle$="")
;@desc: Call this when your program starts to allow InputEx to work.
;If Not InputEx_Window Then InputEx_Window = User32_FindWindow("Blitz Runtime Class", applicationTitle)
InputEx_Window = SystemProperty("AppHWND")
User32_GetCursorPosition(InputEx_Mouse)
User32_ScreenToClient(InputEx_Window, InputEx_Mouse)
InputEx_ForMe = (User32_GetActiveWindow() = InputEx_Window)
If Not ((InputEx_Mouse\X >= 0) And (InputEx_Mouse\Y >= 0) And (InputEx_Mouse\X < GraphicsWidth()) And (InputEx_MouseY < GraphicsHeight())) Then InputEx_ForMe = False
For VSC = 0 To 255
InputEx_VSCAsVK(VSC) = User32_MapVirtualKeyEx(VSC, 1, 0)
Next
End Function
Function InputEx_SetResolution(Width, Height)
InputEx_Width = Width
InputEx_Height = Height
End Function
Function InputEx_Update()
;@desc: Call this once per frame to update InputExs values.
Local InputEx_StateNew
Local InputEx_Time = MilliSecs()
User32_GetCursorPosition(InputEx_Mouse)
User32_ScreenToClient(InputEx_Window, InputEx_Mouse)
InputEx_ForMe = (User32_GetActiveWindow() = InputEx_Window)
If Not ((InputEx_Mouse\X >= 0) And (InputEx_Mouse\Y >= 0) And (InputEx_Mouse\X < InputEx_Width) And (InputEx_Mouse\Y < InputEx_Height)) Then InputEx_ForMe = False
;If InputEx_ForMe Then ;Are those signals even for us?
For VK = 0 To 255
InputEx_StateNew = (User32_GetAsyncKeyState(VK) <> 0)
; Generic Update Structure
If (InputEx_StateNew = 1) And (InputEx_State(VK) = 0) Then
InputEx_Hits(VK) = InputEx_Hits(VK) + 1 ; Register as new key hit.
InputEx_State(VK) = 1 ; Set State to down.
InputEx_StateUpdates(VK) = 0 ; Reset updatecount.
InputEx_StateTime(VK) = InputEx_Time ; Set time at which the state changed.
ElseIf (InputEx_StateNew = 0) And (InputEx_State(VK) = 1) Then
InputEx_State(VK) = 0 ; Set State to up.
InputEx_StateUpdates(VK) = 0 ; Reset Updatecount.
InputEx_StateTime(VK) = InputEx_Time ; Set time at which the state changed.
Else
If (InputEx_State(VK) = 1) Then
InputEx_StateUpdates(VK) = InputEx_StateUpdates(VK) + 1 ; Increase updatecount because button is down.
Else
InputEx_StateUpdates(VK) = InputEx_StateUpdates(VK) - 1 ; Decrease updatecount because button is up.
EndIf
EndIf
Next
;Else ;No
For VK = 0 To 255
InputEx_State(VK) = 0
InputEx_StateTime(VK) = InputEx_Time
Next
;EndIf
;Some may ask why i didn't put the If into the loop, this is the answer:
;If I put it outside the loop, it's one less task for the CPU to do for every iteration. Thus increasing speed.
;If I put it inside the loop, it's one more task for the CPU to do for every iteration. Thus decreasing speed.
End Function
Function InputEx_VKeyTime(VirtualKey)
;@desc: This tells you when the last state of the key was recieved in milliseconds.
;@returns: Time in milliseconds when the state of the key was registered.
Return InputEx_StateTime(VirtualKey)
End Function
Function InputEx_VKeyDownEx(VirtualKey)
;@desc: This tells you the amount of updates a key has been down for(positive) or the amount of updates a key has been up for(negative).
;@returns: Updates the key has been down for.
Return InputEx_StateUpdates(VirtualKey)
End Function
Function InputEx_VKeyDown(VirtualKey)
;@desc: This tells you if a key is down or not.
;@returns: The keys state.
Return InputEx_State(VirtualKey)
End Function
Function InputEx_VKeyHitEx(VirtualKey, Reduce=1)
;@desc: This tells you the amount of hits a key has recieved, while reducing the amount by <Reduce>.
;@returns: How many times the key has been hit.
Local Hits = InputEx_Hits(VirtualKey)
InputEx_Hits(VirtualKey) = InputEx_Hits(VirtualKey) - Reduce
Return Hits
End Function
Function InputEx_VKeyHit(VirtualKey)
;@desc: This tells you the amount of hits a key has recieved since the last call and setting the amount to zero.
;@returns: How many times the key has been hit.
Local Hits = InputEx_Hits(VirtualKey)
InputEx_Hits(VirtualKey) = 0
Return Hits
End Function
Function InputEx_KeyTime(ScanCode)
;@desc: See [InputEx_VKeyTime].
Return InputEx_VKeyTime(InputEx_VSCAsVK(ScanCode))
End Function
Function InputEx_KeyDownEx(ScanCode)
;@desc: See [InputEx_VKeyDownEx].
Return InputEx_VKeyDownEx(InputEx_VSCAsVK(ScanCode))
End Function
Function InputEx_KeyDown(ScanCode)
;@desc: See [InputEx_VKeyDown].
Return InputEx_VKeyDown(InputEx_VSCAsVK(ScanCode))
End Function
Function InputEx_KeyHitEx(ScanCode)
;@desc: See [InputEx_VKeyHitEx].
Return InputEx_VKeyHitEx(InputEx_VSCAsVK(ScanCode))
End Function
Function InputEx_KeyHit(ScanCode)
;@desc: See [InputEx_VKeyHit].
Return InputEx_VKeyHit(InputEx_VSCAsVK(ScanCode))
End Function
Function InputEx_MouseTime(Button)
;@desc: See [InputEx_VKeyTime].
Select Button
Case 1,2
Return InputEx_VKeyTime(Button)
Case 3,4,5
Return InputEx_VKeyTime(Button+1)
End Select
End Function
Function InputEx_MouseDownEx(Button)
;@desc: See [InputEx_VKeyDownEx].
Select Button
Case 1,2
Return InputEx_VKeyDownEx(Button)
Case 3,4,5
Return InputEx_VKeyDownEx(Button+1)
End Select
End Function
Function InputEx_MouseDown(Button)
;@desc: See [InputEx_VKeyDown].
Select Button
Case 1,2
Return InputEx_VKeyDown(Button)
Case 3,4,5
Return InputEx_VKeyDown(Button+1)
End Select
End Function
Function InputEx_MouseHitEx(Button)
;@desc: See [InputEx_VKeyHitEx].
Select Button
Case 1,2
Return InputEx_VKeyHitEx(Button)
Case 3,4,5
Return InputEx_VKeyHitEx(Button+1)
End Select
End Function
Function InputEx_MouseHit(Button)
;@desc: See [InputEx_VKeyHit].
Select Button
Case 1,2
Return InputEx_VKeyHit(Button)
Case 3,4,5
Return InputEx_VKeyHit(Button+1)
End Select
End Function
;----------------------------------------------------------------
;----------------------------------------------------------------
;-- Helper Functions for ease of use.
;----------------------------------------------------------------
Function MouseTime(Button)
Return InputEx_MouseTime(Button)
End Function
Function MouseDownEx(Button)
Return InputEx_MouseDownEx(Button)
End Function
Function MouseDown(Button)
Return InputEx_MouseDown(Button)
End Function
Function MouseHitEx(Button)
Return InputEx_MouseHitEx(Button)
End Function
Function MouseHit(Button)
Return InputEx_MouseHit(Button)
End Function
Function KeyTime(Key)
Return InputEx_KeyTime(Key)
End Function
Function KeyDownEx(Key)
Return InputEx_KeyHitEx(Key)
End Function
Function KeyDown(Key)
Return InputEx_KeyDown(Key)
End Function
Function KeyHitEx(Key)
Return InputEx_KeyHitEx(Key)
End Function
Function KeyHit(Key)
Return InputEx_KeyHit(Key)
End Function
;----------------------------------------------------------------
;----------------------------------------------------------------
;-- Example
;----------------------------------------------------------------
;Graphics 400,300,32,2
;SetBuffer BackBuffer()
;User32_ShowWindow(SystemProperty("AppHWND"), 1)
;
;Local Behaviour
;
;InputEx_Init()
;While Not KeyDown(1)
; InputEx_Update()
;
; Cls
;
; If KeyHit(2) Then Behaviour = 0
; If KeyHit(3) Then Behaviour = 1
;
; Select Behaviour
; Case 0
; Color 255,204,204
; Text 0, 0,"Behaviour: Normal (Press 2 to change to 'Extended')"
; Text 0,15,"Mouse L: "+MouseDown(1)+" "+MouseTime(1)
; Text 0,30,"Mouse R: "+MouseDown(2)+" "+MouseTime(2)
; Text 0,45,"Mouse M: "+MouseDown(3)+" "+MouseTime(3)
; Text 0,60,"Mouse X1: "+MouseDown(4)+" "+MouseTime(4)
; Text 0,75,"Mouse X2: "+MouseDown(5)+" "+MouseTime(5)
; Case 1
; Color 204,204,255
; Text 0, 0,"Behaviour: Extended (Press 1 to change to 'Normal')"
; Text 0,15,"Mouse L: "+MouseDownEx(1)+" "+MouseTime(1)
; Text 0,30,"Mouse R: "+MouseDownEx(2)+" "+MouseTime(2)
; Text 0,45,"Mouse M: "+MouseDownEx(3)+" "+MouseTime(3)
; Text 0,60,"Mouse X1: "+MouseDownEx(4)+" "+MouseTime(4)
; Text 0,75,"Mouse X2: "+MouseDownEx(5)+" "+MouseTime(5)
; End Select
;
; Flip
;Wend
;
;End
;----------------------------------------------------------------
;~IDEal Editor Parameters:
;~C#Blitz3D
+32
View File
@@ -0,0 +1,32 @@
.lib "User32.dll"
User32_FindWindow%(class$, title$):"FindWindowA"
User32_GetActiveWindow%():"GetActiveWindow"
User32_GetCursorPosition%(point*):"GetCursorPos"
User32_ScreenToClient%(hwnd%, point*):"ScreenToClient"
User32_MapVirtualKeyEx%(code%, mapType%, dwhkl%):"MapVirtualKeyExA"
User32_GetAsyncKeyState%(vkey%):"GetAsyncKeyState"
.lib " "
InputEx_Init()
InputEx_Update()
InputEx_VKeyTime%(VirtualKey%)
InputEx_VKeyDownEx%(VirtualKey%)
InputEx_VKeyDown%(VirtualKey%)
InputEx_VKeyHitEx%(VirtualKey%)
InputEx_VKeyHit%(VirtualKey%)
InputEx_KeyTime%(ScanCode%)
InputEx_KeyDownEx%(ScanCode%)
InputEx_KeyDown%(ScanCode%)
InputEx_KeyHitEx%(ScanCode%)
InputEx_KeyHit%(ScanCode%)
InputEx_MouseTime%(Button%)
InputEx_MouseDownEx%(Button%)
InputEx_MouseDown%(Button%)
InputEx_MouseHitEx%(Button%)
InputEx_MouseHit%(Button%)
KeyTime%(Key%)
KeyDownEx%(Key%)
KeyHitEx%(Key%)
MouseTime%(Button%)
MouseDownEx%(Button%)
MouseHitEx%(Button%)
+9
View File
@@ -0,0 +1,9 @@
InputEx
=======================
You know what is great to do? Extend the functionality of a shitty language! This userlibrary adds the ability to use the entire keyboard and mouse buttons, even allowing you to read the time of access, how long it's been active etc. Only downside is that it relies on GetAsyncKeyState.
Documentation at: http://www.blitzforum.de/forum/viewtopic.php?p=405648#405648
License
=======
BlitzUtility by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+6
View File
@@ -0,0 +1,6 @@
# Binary Files
*.o
*.a
*.exe
*/.bmx
*/.indevIDE
@@ -0,0 +1,124 @@
Strict
Import BRL.Stream
Import BRL.Retro
Function FileMD5$(filePath$, bufferSize=$400000)
Assert (bufferSize & 63) = 0 Else "bufferSize must be a multiple of 64 bytes"
Local h0 = $67452301, h1 = $EFCDAB89, h2 = $98BADCFE, h3 = $10325476
Local r[] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,..
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,..
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,..
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]
Local k[] = [$D76AA478, $E8C7B756, $242070DB, $C1BDCEEE, $F57C0FAF, $4787C62A,..
$A8304613, $FD469501, $698098D8, $8B44F7AF, $FFFF5BB1, $895CD7BE,..
$6B901122, $FD987193, $A679438E, $49B40821, $F61E2562, $C040B340,..
$265E5A51, $E9B6C7AA, $D62F105D, $02441453, $D8A1E681, $E7D3FBC8,..
$21E1CDE6, $C33707D6, $F4D50D87, $455A14ED, $A9E3E905, $FCEFA3F8,..
$676F02D9, $8D2A4C8A, $FFFA3942, $8771F681, $6D9D6122, $FDE5380C,..
$A4BEEA44, $4BDECFA9, $F6BB4B60, $BEBFBC70, $289B7EC6, $EAA127FA,..
$D4EF3085, $04881D05, $D9D4D039, $E6DB99E5, $1FA27CF8, $C4AC5665,..
$F4292244, $432AFF97, $AB9423A7, $FC93A039, $655B59C3, $8F0CCC92,..
$FFEFF47D, $85845DD1, $6FA87E4F, $FE2CE6E0, $A3014314, $4E0811A1,..
$F7537E82, $BD3AF235, $2AD7D2BB, $EB86D391]
Local fileStream:TStream = OpenStream(filePath$, True, False)
If fileStream = Null Then Return
Local buffer:Byte Ptr = MemAlloc(bufferSize)
Local bitCount:Long, dataTop = bufferSize
Repeat
Local bytesRead = fileStream.Read(buffer, bufferSize)
If fileStream.EOF()
dataTop = (((bytesRead + 8) Shr 6) + 1) Shl 6
If dataTop > bufferSize
buffer = MemExtend(buffer, bufferSize, dataTop)
EndIf
bitCount :+ (bytesRead Shl 3)
For Local b = (bytesRead + 1) Until (dataTop - 8)
buffer[b] = 0
Next
buffer[bytesRead] = $80
LEPokeLong(buffer, dataTop - 8, bitCount)
Else
bitCount :+ (bufferSize Shl 3)
EndIf
For Local chunkStart=0 Until (dataTop Shr 2) Step 16
Local a = h0, b = h1, c = h2, d = h3
For Local i=0 To 15
Local f = d ~ (b & (c ~ d))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + i) Shl 2)), r[i]) + b
a = t
Next
For Local i=16 To 31
Local f = c ~ (d & (b ~ c))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + (((5 * i) + 1) & 15)) Shl 2)), r[i]) + b
a = t
Next
For Local i=32 To 47
Local f = b ~ c ~ d
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + (((3 * i) + 5) & 15)) Shl 2)), r[i]) + b
a = t
Next
For Local i=48 To 63
Local f = c ~ (b | ~d)
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + ((7 * i) & 15)) Shl 2)), r[i]) + b
a = t
Next
h0 :+ a ; h1 :+ b
h2 :+ c ; h3 :+ d
Next
Until fileStream.EOF()
fileStream.Close()
MemFree(buffer)
Return (LEHex(h0) + LEHex(h1) + LEHex(h2) + LEHex(h3)).ToLower()
End Function
Function Rol(val, shift)
Return (val Shl shift) | (val Shr (32 - shift))
End Function
Function LEPeekInt(buffer:Byte Ptr, offset)
Return (buffer[offset + 3] Shl 24) | (buffer[offset + 2] Shl 16) | ..
(buffer[offset + 1] Shl 8) | buffer[offset]
End Function
Function LEPokeLong(buffer:Byte Ptr, offset, value:Long)
For Local b=7 To 0 Step -1
buffer[offset + b] = (value Shr (b Shl 3)) & $ff
Next
End Function
Function LEHex$(val)
Local out$ = Hex(val)
Return out$[6..8] + out$[4..6] + out$[2..4] + out$[0..2]
End Function
@@ -0,0 +1,197 @@
'Function DebugProgressCB:Int(data:Object,dltotal:Double,dlnow:Double,ultotal:Double,ulnow:Double)
' DebugLog "dltotal="+Int(dltotal)+",dlnow="+Int(dlnow)+",ultotal="+Int(ultotal)+",ulnow="+Int(ulnow)
'EndFunction
Rem
Type TTaskPatchCheck Extends TTaskPatch
Field m_stFile:String
Field m_stHash:String
Field l_bValid:Byte = True
Method Run()
' Retrieve Hash
Local stHash:String = FileMD5(m_stFile).ToUpper();l_fProgress = 0.5
' Compare Hash
If stHash <> m_stHash Then
l_bValid = False
oPatchListMutex.Lock()
oPatchList.AddLast(m_stFile)
oPatchListMutex.Unlock()
EndIf
l_fProgress = 1.0
EndMethod
Function Create:TTask(File:String, Hash:String)
Local oTask:TTaskPatchCheck = New TTaskPatchCheck
oTask.m_stFile = File
oTask.m_stHash = Hash
Return oTask
EndFunction
EndType
Type TTaskPatchFile Extends TTaskPatch
Field m_stFile:String
Method Run()
Local oCurl:TCurlEasy = New TCurlEasy
oCurl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
oCurl.setOptString(CURLOPT_USERAGENT, "Sirius Online Launcher")
oCurl.setOptString(CURLOPT_REFERER, TPatcher_Server)
oCurl.setOptString(CURLOPT_URL, TPatcher_Server + m_stFile)
oCurl.setWriteString()
EndMethod
Function Create:TTask(File:String)
Local oTask:TTaskPatchFile = New TTaskPatchFile
oTask.m_stFile = File
Return oTask
EndFunction
EndType
Rem
Import BRL.LinkedList
Const TPatcher_MaxParallelTasks:Int = 4
Const TPatcher_Server:String = "http://sirius-online.us.to/patch/"
Type TPatcher
' TCurlMulti Instance for non-blocking IO.
Field oCurlMulti:TCurlMulti = TCurlMulti.Create()
' List of available tasks and active tasks.
Field oTasks:TList = (New TList)
Field oTaskSlots:TTaskSlot[] = New TTaskSlot[TPatcher_MaxParallelTasks]
Field oTasksDone:TList = (New TList)
Method New()
For Local i:Int = 0 Until TPatcher_MaxParallelTasks
oTaskSlots[i].oCurl = oCurlMulti.newEasy()
next
oTasks.AddLast(TTask_PatchInfo.Create())
EndMethod
' Main loop for TPatcher
Method Perform()
Local runningHandles:Int
If oTaskSlots[0].oTask <> Null or oTaskSlots[1].oTask <> Null or oTaskSlots[2].oTask <> Null or oTaskSlots[3].oTask <> Null Then
Local iResult:Int = CURLM_OK
Repeat
iResult = oCurlMulti.multiPerform(runningHandles)
For Local slot:Int = 0 Until TPatcher_MaxParallelTasks
If oTaskSlots[slot].oTask = Null And oTasks.Count() > 0 Then
oTaskSlots[slot].oTask = TTask(oTasks.RemoveLast())
oTaskSlots[slot].oTask.Initialize(Self, oTaskSlots[slot].oCurl)
ElseIf oTaskSlots[slot].oTask <> Null Then
If oTaskSlots[slot].oTask.bComplete = True Then
oTasksDone.AddLast(oTaskSlots[slot].oTask)
oTaskSlots[slot].oTask = Null
' Restore TCurlEasy to useable state.
oCurlMulti.multiRemove(oTaskSlots[slot].oCurl)
oTaskSlots[slot].oCurl.cleanup()
oCurlMulti.multiAdd(oTaskSlots[slot].oCurl)
EndIf
Endif
Next
Until iResult <> CURLM_CALL_MULTI_PERFORM
Else
oCurlMulti.cleanup()
EndIf
EndMethod
EndType
Type TTaskSlot
Field oTask:TTask
Field oCurl:TCurlEasy
EndType
Type TTask Abstract
Field oPatcher:TPatcher = Null
Field stName:String = "Unknown"
Field bComplete:Byte = False
Field fProgress:Float = 0.0
Method Initialize(oPatcher:TPatcher, oCurl:TCurlEasy)
Self.oPatcher = oPatcher
oCurl.setWriteCallback(_HandleWriteCallback, Self)
oCurl.setProgressCallback(_HandleProgressCallback, Self)
EndMethod
Method HandleProgressCallback:Int(dltotal:Double, dlnow:Double, ultotal:Double, ulnow:Double)
fProgress = dlnow / dltotal
If dlnow = dltotal Then bComplete = True
EndMethod
Method HandleWriteCallback:Int(buffer:Byte Ptr, size:Int)
EndMethod
Function _HandleProgressCallback:Int(Data:Object, dltotal:Double, dlnow:Double, ultotal:Double, ulnow:Double)
Local Task:TTask = TTask(Data)
Return Task.HandleProgressCallback(dltotal, dlnow, ultotal, ulnow)
EndFunction
Function _HandleWriteCallback(buffer:Byte Ptr, size:Int, Data:Object)
Local Task:TTask = TTask(Data)
Return Task.HandleWriteCallback(buffer, size)
EndFunction
EndType
Type TTask_PatchInfo Extends TTask
Method New()
Self.stName = "Retrieving Patch Information"
EndMethod
Method Initialize(oPatcher:TPatcher, oCurl:TCurlEasy)
Super.Initialize(oPatcher, oCurl)
oCurl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
oCurl.setOptString(CURLOPT_USERAGENT, "Sirius Online Launcher")
oCurl.setOptString(CURLOPT_REFERER, TPatcher_Server)
oCurl.setOptString(CURLOPT_URL, TPatcher_Server + "info")
oCurl.setWriteString()
EndMethod
Method HandleProgressCallback:Int(dltotal:Double, dlnow:Double, ultotal:Double, ulnow:Double)
Super.HandleProgressCallback()
If bComplete = True Then
EndIf
EndMethod
Function Create:TTask()
Return (New TTask_PatchInfo)
EndFunction
EndType
Type TTask_File Extends TTask
Field stHash:String
Field stFile:String
Method Initialize(oPatcher:TPatcher, oCurl:TCurlEasy)
Super.Initialize(oPatcher, oCurl)
oCurl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
oCurl.setOptString(CURLOPT_USERAGENT, "Sirius Online Launcher")
oCurl.setOptString(CURLOPT_REFERER, TPatcher_Server + "info")
'Local oFileStream:TStream =
oCurl.setWriteString()
EndMethod
Method HandleProgressCallback:Int(dltotal:Double, dlnow:Double, ultotal:Double, ulnow:Double)
Super.HandleProgressCallback()
EndMethod
Function Create:TTask(File:String, Hash:String)
Local oTask:TTask_File = New TTask_File
oTask.stHash = Hash
oTask.stFile = File
oCurl.setOptString(CURLOPT_URL, TPatcher_Server + oTask.File)
Return oTask
EndFunction
EndType
EndRem
@@ -0,0 +1,242 @@
SuperStrict
Import BRL.Threads
Import BRL.LinkedList
Import BRL.StandardIO
Const DEF_THREADPOOL_MINTHREADS:Int = 1
Const DEF_THREADPOOL_MAXTHREADS:Int = 4
Type TThreadPool
' Threads
Field m_oThreads:TList = New TList
Field m_iMinThreads:Int = DEF_THREADPOOL_MINTHREADS
Field m_iMaxThreads:Int = DEF_THREADPOOL_MAXTHREADS
' Task Queue
Field m_oTaskList:TList = New TList
Field m_oTaskMutex:TMutex = TMutex.Create()
' Construction
Function Create:TThreadPool(iMinThreads:Int = DEF_THREADPOOL_MINTHREADS, iMaxThreads:Int = DEF_THREADPOOL_MAXTHREADS)
Local oThreadPool:TThreadPool = New TThreadPool
oThreadPool.SetLimits(iMinThreads, iMaxThreads)
Return oThreadPool
EndFunction
' Destruction
Method Destroy()
For Local oThreadWorker:TThreadWorker = EachIn m_oThreads
oThreadWorker.ForceDestroy()
Next
m_oThreads.Clear()
m_oTaskList.Clear()
EndMethod
' Change the thread limits, for example when the game configuration changes. Effective immediately or after
Method SetLimits(iMinThreads:Int = DEF_THREADPOOL_MINTHREADS, iMaxThreads:Int = DEF_THREADPOOL_MAXTHREADS)
m_iMinThreads = iMinThreads
If (iMaxThreads < iMinThreads) Then iMaxThreads = iMinThreads
m_iMaxThreads = iMaxThreads
EndMethod
' Add new Task to the queue.
Method AddTask(oTask:TTask)
m_oTaskMutex.Lock()
m_oTaskList.AddLast(oTask)
m_oTaskMutex.Unlock()
EndMethod
' Distributes work across threads, destroys and spawns threads
Method Update:Int()
Local iThreadCount:Int = m_oThreads.Count()
' Spawn more Threads if we don't have at least m_iMinThreads
If iThreadCount < m_iMinThreads Then
Local iSpawnCount:Int = m_iMinThreads - iThreadCount
For Local spawn:Int = 1 To iSpawnCount
m_oThreads.AddLast(New TThreadWorker)
iThreadCount :+ 1
Next
EndIf
For Local oThreadWorker:TThreadWorker = EachIn m_oThreads
' Loosely enforce m_iMaxThreads by destroying unused Threads.
If iThreadCount > m_iMaxThreads And oThreadWorker.m_oAvailable.TryLock() = True Then
If oThreadWorker.m_oTask = Null Then
oThreadWorker.m_oAvailable.Unlock()
oThreadWorker.Destroy()
m_oThreads.Remove(oThreadWorker)
iThreadCount :- 1
Exit
EndIf
EndIf
' Distribute available work.
m_oTaskMutex.Lock()
If m_oTaskList.Count() > 0 And oThreadWorker.m_oAvailable.TryLock() = True Then
oThreadWorker.m_oAvailable.Unlock()
Local oTask:TTask = TTask(m_oTaskList.RemoveFirst())
If oThreadWorker.AssignTask(oTask) = False Then m_oTaskList.AddLast(oTask)
EndIf
m_oTaskMutex.Unlock()
' Destroy Threads that have been waiting too long on Work, given that they are unneeded.
If iThreadCount > m_iMinThreads And oThreadWorker.m_oAvailable.TryLock() = True Then
oThreadWorker.m_oAvailable.Unlock()
If oThreadWorker.m_oTask = Null And (MilliSecs() - oThreadWorker.m_lTaskTime) > 5000 Then
m_oThreads.Remove(oThreadWorker)
oThreadWorker.Destroy()
iThreadCount :- 1
EndIf
EndIf
Next
' Spawn more Threads if we did not hit m_iMaxThreads and there is still work left.
m_oTaskMutex.Lock()
If m_oTaskList.Count() > 0 And iThreadCount < m_iMaxThreads Then
Local iSpawnCount:Int = Min(m_oTaskList.Count(), m_iMaxThreads - iThreadCount)
For Local spawn:Int = 1 To iSpawnCount
m_oThreads.AddLast(New TThreadWorker)
iThreadCount :+ 1
Next
EndIf
m_oTaskMutex.Unlock()
Return iThreadCount
EndMethod
Method CountTasks:Int()
Local retVal:Int = 0
m_oTaskMutex.Lock()
retVal = m_oTaskList.Count()
m_oTaskMutex.Unlock()
Return retVal
EndMethod
Method CountActiveTasks:Int()
Local retVal:Int = 0
For Local oThreadWorker:TThreadWorker = EachIn m_oThreads
oThreadWorker.m_oAvailable.Lock()
If oThreadWorker.m_oTask <> Null Then retVal :+ 1
oThreadWorker.m_oAvailable.Unlock()
Next
Return retVal
EndMethod
EndType
Type TThreadWorker
Field m_oThread:TThread
' Used to make the Thread sleep and work.
Field m_oAvailable:TMutex
Field m_oCondVar:TCondVar
' Contains Task and the time it was assigned at.
Field m_oTask:TTask
Field m_lTaskTime:Long
Field d_iCount:Int
' Construction
Method New()
m_oAvailable = TMutex.Create()
m_oCondVar = TCondVar.Create()
m_oThread = TThread.Create(Execute, Self)
m_lTaskTime = MilliSecs()
EndMethod
' Destruction
Method Destroy()
While AssignTask(oTaskTerminate) = False
Delay 10
Wend
m_oThread.Wait() 'broken?
m_oThread.Detach()
EndMethod
Method ForceDestroy()
m_oThread.Detach()
EndMethod
' Task Management
Method AssignTask:Int(oTask:TTask)
If m_oAvailable.TryLock() = True And m_oTask = Null Then
m_oTask = oTask
m_lTaskTime = MilliSecs()
m_oAvailable.Unlock()
m_oCondVar.Signal()
Return True
EndIf
Return False
EndMethod
' Thread Wrapper Function
Function Execute:Object(Data:Object)
Local oThreadWorker:TThreadWorker = TThreadWorker(Data)
Local oTask:TTask = Null
oThreadWorker.m_oAvailable.Lock()
Repeat
oThreadWorker.m_oCondVar.Wait(oThreadWorker.m_oAvailable)
If oThreadWorker.m_oTask <> Null Then
oThreadWorker.d_iCount :+ 1
oTask = oThreadWorker.m_oTask
oThreadWorker.m_oAvailable.Unlock()
oTask.Run()
oThreadWorker.m_oAvailable.Lock()
oThreadWorker.m_oTask = Null
EndIf
Until oTask = oTaskTerminate
oThreadWorker.m_oAvailable.Unlock()
EndFunction
EndType
Type TTask Abstract
' Called when a thread is working on this item.
Method Run()
EndMethod
EndType
Type TTaskTerminate Extends TTask
EndType
Global oTaskTerminate:TTask = New TTaskTerminate
Type TTaskPtr Extends TTask
Field m_pFunc:Object(data:Object)
Field m_pData:Object
Field m_pReturn:Object
' Construction
Function Create:TTask(pFunc:Object(data:Object), pData:Object)
Local oTWPtr:TTaskPtr = New TTaskPtr
oTWPtr.SetFunction(pFunc)
oTWPtr.SetData(pData)
Return oTWPtr
EndFunction
' Called when a thread is working on this item.
Method Run()
m_pReturn = m_pFunc(m_pData)
EndMethod
' Set the Function executed by Run()
Method SetFunction(pFunc:Object(data:Object))
m_pFunc = pFunc
EndMethod
' Set the Data passed to the Function.
Method SetData(pData:Object)
m_pData = pData
EndMethod
' Retrieve the return value of the executed Function
Method GetReturn:Object()
Return m_pReturn
EndMethod
EndType
Global PrintMutex:TMutex = TMutex.Create()
Function _Print(Str:String)
PrintMutex.Lock()
Print(Str)
PrintMutex.Unlock()
EndFunction
+14
View File
@@ -0,0 +1,14 @@
#include <brl.mod/blitz.mod/blitz.h>
#include <time.h>
int getClocksPerSecond_() {
return CLOCKS_PER_SEC;
}
int getClock_() {
return (int)clock();
}
int getClockDiff_(int clockStart, int clockEnd) {
return ((clock_t)clockEnd - (clock_t)clockStart);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 KiB

@@ -0,0 +1,488 @@
SuperStrict
' Modules and Includes -----------------------------------------------------------------------------------------------------------------------------------------
Framework BRL.Blitz
Import BRL.StandardIO
Import BRL.Timer
Import BRL.Max2D
Import BRL.GLMax2D
Import BRL.Event
Import BRL.EventQueue
Import PUB.FreeProcess
Import MaxGUI.MaxGUI
Import MaxGUI.Drivers
' Libraries
Import "TGUI.bmx"
Import "Max2DExtended.bmx"
' Resources -----------------------------------------------------------------------------------------------------------------------------------------------------
' Binary Resources
Incbin "GFX/LNC/GUIxSTYLE.png"
Incbin "SFX/M/launcher.ogg"
' Initialization ------------------------------------------------------------------------------------------------------------------------------------------------
SetGraphicsDriver(GLMax2DDriver())
' Create Timers to reduce CPU load.
Global tmrRender:TTimer = CreateTimer(20) ' One for rendering the GUI
Global tmrUpdate:TTimer = CreateTimer(100) ' And one for working.
' Create the Window and Canvas for the Patcher, set the Graphics Driver to OpenGL and enable polled input.
Global gdgPatcher:TGadget = CreateWindow("Sirius Online", 0, 0, 720, 460, Desktop(), WINDOW_CLIENTCOORDS | WINDOW_CENTER | WINDOW_HIDDEN)
Global gdgCanvas:TGadget = CreateCanvas(0, 0, ClientWidth(gdgPatcher), ClientHeight(gdgPatcher), gdgPatcher)
SetGraphics(gdgCanvas) ' Change OpenGL Context to the Canvas.
EnablePolledInput(gdgCanvas) ' Enable input handling for the Canvas.
DebugLog TShader.CheckCompatability()
End
Rem
' Load our GUI Style and split it into the required images.
Global guiStyle:TPixmap = LoadPixmap("GFX/LNC/GUIxSTYLE.png")
If guiStyle = Null Then guiStyle = LoadPixmap("incbin::GFX/LNC/GUIxSTYLE.png")
Global guiWindowBackground:TImage = LoadImage(guiStyle.Window(0, 0, 32, 32), FILTEREDIMAGE)
Global guiWindowShade:TImage[] = New TImage[2]
guiWindowShade[0] = LoadImage(guiStyle.Window(32, 0, 16, 16), FILTEREDIMAGE)
guiWindowShade[1] = LoadImage(guiStyle.Window(32, 16, 16, 16), FILTEREDIMAGE)
Global guiWindowTitleBar:TImage[] = New TImage[2]
guiWindowTitleBar[0] = LoadImage(guiStyle.Window(48, 0, 16, 16), FILTEREDIMAGE)
guiWindowTitleBar[1] = LoadImage(guiStyle.Window(48, 16, 16, 16), FILTEREDIMAGE)
Global guiSymbols:TImage[] = New TImage[8]
guiSymbols[0] = LoadImage(guiStyle.Window(64, 0, 16, 16), FILTEREDIMAGE) 'Close
guiSymbols[1] = LoadImage(guiStyle.Window(80, 0, 16, 16), FILTEREDIMAGE) 'Minimize
guiSymbols[2] = LoadImage(guiStyle.Window(96, 0, 16, 16), FILTEREDIMAGE) 'Maximize
guiSymbols[3] = LoadImage(guiStyle.Window(112, 0, 16, 16), FILTEREDIMAGE) 'Restore
guiSymbols[4] = LoadImage(guiStyle.Window(64, 16, 16, 16), FILTEREDIMAGE)
guiSymbols[5] = LoadImage(guiStyle.Window(80, 16, 16, 16), FILTEREDIMAGE)
guiSymbols[6] = LoadImage(guiStyle.Window(96, 16, 16, 16), FILTEREDIMAGE)
guiSymbols[7] = LoadImage(guiStyle.Window(112, 16, 16, 16), FILTEREDIMAGE)
Global guiButtonNormal:TImage[] = New TImage[3]
guiButtonNormal[0] = LoadImage(guiStyle.Window(0, 32, 16, 16), FILTEREDIMAGE)
guiButtonNormal[1] = LoadImage(guiStyle.Window(0, 48, 16, 16), FILTEREDIMAGE)
guiButtonNormal[2] = LoadImage(guiStyle.Window(0, 64, 16, 16), FILTEREDIMAGE)
Global guiButtonShaped:TImage[] = New TImage[3]
guiButtonShaped[0] = LoadImage(guiStyle.Window(16, 32, 16, 16), FILTEREDIMAGE)
guiButtonShaped[1] = LoadImage(guiStyle.Window(16, 48, 16, 16), FILTEREDIMAGE)
guiButtonShaped[2] = LoadImage(guiStyle.Window(16, 64, 16, 16), FILTEREDIMAGE)
Global guiProgressBar:TImage[] = New TImage[3]
guiProgressBar[0] = LoadImage(guiStyle.Window(16, 80, 16, 16), FILTEREDIMAGE)
guiProgressBar[1] = LoadImage(guiStyle.Window(16, 96, 16, 16), FILTEREDIMAGE)
guiProgressBar[2] = LoadImage(guiStyle.Window(16, 112, 16, 16), FILTEREDIMAGE)
EndRem
' Show the Patcher Window
ShowGadget gdgPatcher
' GUI Values
Const guiTitleHeight:Int = 24
Global guiWidth:Int = ClientWidth(gdgPatcher)
Global guiHeight:Int = ClientHeight(gdgPatcher)
Global guiActive:Int = True
' Main Loop -----------------------------------------------------------------------------------------------------------------------------------------------------
Repeat
WaitEvent()
Select EventSource()
Case tmrRender
SetGraphics CanvasGraphics(gdgCanvas);Cls
Rem
' Draw GUI
SetColor(255, 255, 255); SetAlpha(1.0); SetBlend(SOLIDBLEND); SetScale(1.0, 1.0); SetRotation(0.0)
' Title Bar and Title
DrawTiledImage guiWindowTitleBar[guiActive], 0, 0, guiWidth, guiTitleHeight, 0, 0, 16, 16,,,,4,4,4,4, True, MODE_SCALEUPX | MODE_SCALEUPY
DrawText(GadgetText(gdgPatcher), 4, guiTitleHeight / 2 - (12 / 2))
' Content Background
DrawSubImageRectEx guiWindowBackground, 0, guiTitleHeight, guiWidth, guiHeight - guiTitleHeight, 0, 0, 32, 32,,,, MODE_REPEATX | MODE_REPEATY
SetBlend SHADEBLEND
DrawTiledImage guiContent[guiActive], 0, guiTitleHeight, guiWidth, guiHeight - guiTitleHeight, 0, 0, 16, 16,,,, 4, 4, 4, 4, True, MODE_REPEATX | MODE_REPEATY | MODE_SCALEUPX | MODE_SCALEUPY
EndRem
' Show the now rendered GUI
Flip False
Case gdgPatcher
Select EventID()
Case EVENT_WINDOWMODE, EVENT_WINDOWSIZE
' Update GUI Values {
guiWidth = ClientWidth(gdgPatcher)
guiHeight = ClientWidth(gdgPatcher)
' }
End Select
End Select
Forever
End
Rem
' Files
Import "Patcher.bmx"
'=====> Constants
?Win32
Const LAUNCHER_NAME:String = "Launcher.exe"
?Linux
Const LAUNCHER_NAME:String = "Launcher.bin"
?MacOS
Const LAUNCHER_NAME:String = "Launcher.app"
?
'=====> Parse Arguments
Global stProgram:String = AppArgs[0]
Global stProgramPath:String = ExtractDir(AppArgs[0])
Global stProgramName:String = StripDir(AppArgs[0])
Global bPatchLauncher:Byte = False
Global iPatchRetries:Int = 30
For Local stArgument:String = EachIn AppArgs[1..]
Local stArgName:String, stArgValue:String
' Skip arguments not starting with a dash
If stArgument[0..1] <> "-" Then Continue
Local iValuePos:Int = stArgument.Find("=")
If iValuePos >= 0 Then
stArgName = stArgument[1..iValuePos]
stArgValue = stArgument[iValuePos..]
Else
stArgName = stArgument[1..]
stArgValue = "1"
EndIf
Select stArgName
Case "patch"
bPatchLauncher = Byte(stArgValue)
Case "retry"
iPatchRetries = Int(stArgValue)
End Select
Next
'=====> Use parsed Arguments
'--> Patch the Launcher
If bPatchLauncher = True Then
Local iRetryCount:Int = 0
Local oRetryTimer:TTimer = TTimer.Create(10)
' Copy the newly downloaded Launcher file
If stProgramName <> LAUNCHER_NAME Then
If FileType(LAUNCHER_NAME) = FILETYPE_FILE Then
Repeat
oRetryTimer.Wait()
iRetryCount :+ 1
Until (DeleteFile(LAUNCHER_NAME) = True) or (iRetryCount > iPatchRetries)
EndIf
If FileType(LAUNCHER_NAME) = 0 Then
Repeat
oRetryTimer.Wait()
iRetryCount :+ 1
Until (CopyFile(stProgramName, LAUNCHER_NAME) = True) or (iRetryCount > iPatchRetries)
If FileType(LAUNCHER_NAME) = FILETYPE_FILE Then
Local oProcess:TProcess = CreateProcess(LAUNCHER_NAME)
TProcess.ProcessList.Remove oProcess
End
Else
Notify("Error: Failed to replace Launcher", True)
End
EndIf
Else
Notify("Error: Failed to delete old Launcher", True)
End
EndIf
EndIf
EndIf
' Resources: Create Variables that store resources.
Global riMainBackground:Int, imMainBackground:TImage;LoadResource("GFX/LNC/LAUxPATxB.png",, imMainBackground, riMainBackground)
Global riMainForeground:Int, imMainForeground:TImage;LoadResource("GFX/LNC/LAUxPATxA.png",, imMainForeground, riMainForeground)
Global riProgressBar:Int, imProgressBar:TImage; LoadResource("GFX/LNC/BARxPROGRESS.png",, imProgressBar, riProgressBar)
Global riButtonClose:Int, imButtonClose:TImage; LoadResource("GFX/LNC/BTNxCLOSE.png",, imButtonClose, riButtonClose)
Global riButtonAccount:Int, imButtonAccount:TImage; LoadResource("GFX/LNC/BTNxACCOUNT.png",, imButtonAccount, riButtonAccount)
Global riButtonWebsite:Int, imButtonWebsite:TImage; LoadResource("GFX/LNC/BTNxWEBSITE.png",, imButtonWebsite, riButtonWebsite)
Global riButtonSupport:Int, imButtonSupport:TImage; LoadResource("GFX/LNC/BTNxSUPPORT.png",, imButtonSupport, riButtonSupport)
Global riButtonEULATOS:Int, imButtonEULATOS:TImage; LoadResource("GFX/LNC/BTNxEULATOS.png",, imButtonEULATOS, riButtonEULATOS)
Global riButtonCheck:Int, imButtonCheck:TImage; LoadResource("GFX/LNC/BTNxCHECK.png",, imButtonCheck, riButtonCheck)
Global riButtonPatch:Int, imButtonPatch:TImage; LoadResource("GFX/LNC/BTNxPATCH.png",, imButtonPatch, riButtonPatch)
Global riButtonPlay:Int, imButtonPlay:TImage; LoadResource("GFX/LNC/BTNxPLAY.png",, imButtonPlay, riButtonPlay)
Global riButtonRestart:Int, imButtonRestart:TImage; LoadResource("GFX/LNC/BTNxRESTART.png",, imButtonRestart, riButtonRestart)
Global rfSmallFont:Int, fnSmallFont:TImageFont; LoadFontResource("GFX/FNT/TranscencsGames.otf", 10,, fnSmallFont, rfSmallFont)
Global rfMediumFont:Int, fnMediumFont:TImageFont;LoadFontResource("GFX/FNT/TranscencsGames.otf", 12,, fnMediumFont, rfMediumFont)
Global rfBigFont:Int, fnBigFont:TImageFont; LoadFontResource("GFX/FNT/TranscencsGames.otf", 14,, fnBigFont, rfBigFont)
' Buttons
Const BTN_STT_NORMAL:Int = 0, BTN_STT_HOVER:Int = 1, BTN_STT_DOWN:Int = 2, BTN_STT_ACTION:Int = 3
Global stButtonClose:Int = BTN_STT_NORMAL
Global stButtonAccount:Int = BTN_STT_NORMAL
Global stButtonWebsite:Int = BTN_STT_NORMAL
Global stButtonSupport:Int = BTN_STT_NORMAL
Global stButtonEULATOS:Int = BTN_STT_NORMAL
Global stButtonCheck:Int = BTN_STT_NORMAL
Global stButtonPatch:Int = BTN_STT_NORMAL
Global stButtonPlay:Int = BTN_STT_NORMAL
Global stButtonRestart:Int = BTN_STT_NORMAL
' PatchLog
Global oPatchLog:TList = New TList
' Patcher
Global oPatcher:TPatcher = TPatcher.Create()
ShowGadget(gdPatcherWindow)
EndRem
Rem
'=====> Mainloop
Local relMouseX:Int, relMouseY:Int, bDragging:Byte
Repeat
WaitEvent()
Select EventSource()
Case tmTimer ' Core timer that is basically our main loop.
'=====> User-input
Local MX:Int = MouseX(), MY:Int = MouseY()
Local MD1:Int = MouseDown(1), MH1:Int = MouseHit(1)
stButtonClose = GetButtonState(stButtonClose, 684, 0, 24, 18, MX, MY, MD1)
stButtonWebsite = GetButtonState(stButtonWebsite, 618, 330, 96, 16, MX, MY, MD1)
stButtonSupport = GetButtonState(stButtonSupport, 618, 348, 96, 16, MX, MY, MD1)
stButtonAccount = GetButtonState(stButtonAccount, 618, 366, 96, 16, MX, MY, MD1)
stButtonEULATOS = GetButtonState(stButtonEULATOS, 618, 384, 96, 16, MX, MY, MD1)
' React on the close button by sending a WindowCloseEvent
If stButtonClose = BTN_STT_ACTION Then PostEvent(TEvent.Create(EVENT_WINDOWCLOSE, gdPatcherWindow, 0, 0, 0, 0, Null))
If stButtonWebsite = BTN_STT_ACTION Then OpenURL("http://www.sirius.vektor-studios.com/")
If stButtonSupport = BTN_STT_ACTION Then OpenURL("http://www.sirius.vektor-studios.com/#contact")
If stButtonAccount = BTN_STT_ACTION Then OpenURL("http://www.sirius.vektor-studios.com/")
If stButtonEULATOS = BTN_STT_ACTION Then OpenURL("http://www.sirius.vektor-studios.com/")
' State based checking
Select oPatcher.GetState()
Case TPatcher.STATE_PATCHINFO
stButtonCheck = GetButtonState(stButtonCheck, 312, 441, 96, 16, MX, MY, MD1)
If stButtonCheck = BTN_STT_ACTION Then oPatcher.Advance()
Case TPatcher.STATE_PREPATCH
stButtonPatch = GetButtonState(stButtonPatch, 312, 441, 96, 16, MX, MY, MD1)
If stButtonPatch = BTN_STT_ACTION Then oPatcher.Advance()
Case TPatcher.STATE_COMPLETE
stButtonPlay = GetButtonState(stButtonPlay, 312, 441, 96, 16, MX, MY, MD1)
If stButtonPlay = BTN_STT_ACTION Then oPatcher.Advance()
Case TPatcher.STATE_LAUNCHER
stButtonRestart = GetButtonState(stButtonRestart, 312, 441, 96, 16, MX, MY, MD1)
If stButtonRestart = BTN_STT_ACTION Then oPatcher.Advance()
EndSelect
' Window Dragging
If bDragging = False And (MH1 = True And (MY >= 0 And MY < 32) And (MX >= 0 And MX < 720)) Then
bDragging = True
relMouseX = MX;relMouseY = MY
ElseIf bDragging = True And MD1 = True Then
SetGadgetShape(gdPatcherWindow, GadgetX(gdPatcherWindow) - (relMouseX - MX), GadgetY(gdPatcherWindow) - (relMouseY - MY), 720, 460)
relMouseX = MX + (relMouseX - MX);relMouseY = MY + (relMouseY - MY) 'Magic o.o - I don't understand why this works this way, but not when using :+ notation.
Else
bDragging = False
EndIf
'=====> Rendering
SetGraphics CanvasGraphics(gdRenderCanvas)
Cls
' Draw Back- & Foreground
SetBlend ALPHABLEND;SetMaskColor 0, 0, 0
SetColor 255, 255, 255;SetAlpha 1.0
SetOrigin 0, 0;SetTransform 0, 1, 1
If imMainBackground <> Null Then DrawImage(imMainBackground, 0, 0)
If imMainForeground <> Null Then DrawImage(imMainForeground, 0, 0)
' Window Close Button
DrawButtonState(stButtonClose, 684, 0, 24, 18, imButtonClose, "X")
' Buttons
DrawButtonState(stButtonWebsite, 618, 330, 96, 16, imButtonWebsite, "Website")
DrawButtonState(stButtonSupport, 618, 348, 96, 16, imButtonSupport, "Support")
DrawButtonState(stButtonAccount, 618, 366, 96, 16, imButtonAccount, "Account")
DrawButtonState(stButtonEULATOS, 618, 384, 96, 16, imButtonEULATOS, "EULA/TOS")
' State based drawing.
Select oPatcher.GetState()
Case TPatcher.STATE_PATCHINFO
DrawButtonState(stButtonCheck, 312, 441, 96, 16, imButtonCheck, "Check")
Case TPatcher.STATE_PREPATCH
DrawButtonState(stButtonPatch, 312, 441, 96, 16, imButtonPatch, "Patch")
Case TPatcher.STATE_COMPLETE
DrawButtonState(stButtonPlay, 312, 441, 96, 16, imButtonPlay, "Play")
Case TPatcher.STATE_LAUNCHER
DrawButtonState(stButtonRestart, 312, 441, 96, 16, imButtonRestart, "Restart")
Case TPatcher.STATE_PATCHINFO, TPatcher.STATE_CHECKING, TPatcher.STATE_PATCHING
DrawProgressBar(8, 442, 704, 12, oPatcher.GetProgress(), imProgressBar)
EndSelect
' Draw Patcher Tasklog
SetBlend ALPHABLEND;SetMaskColor 0, 0, 0
SetColor 255, 255, 255;SetAlpha 0.66;SetImageFont fnSmallFont
SetOrigin 0, 0;SetTransform 0, 1, 1
SetViewport 11, 332, 600, 100
Local iLogNum:Int = 1, oLogEntry:TLink = oPatcher.m_oTaskList.FirstLink()
While (iLogNum < 9) And (oLogEntry <> Null)
Local stLine:String = String(oLogEntry.Value())
If stLine[0..1] = "n" Then SetColor 204, 244, 255
If stLine[0..1] = "e" Then SetColor 255, 222, 204
If stLine[0..1] = "g" Then SetColor 204, 255, 204
If stLine[0..1] = "h" Then SetColor 222, 222, 255
DrawText stLine[1..], 11, 430 - iLogNum * 12
oLogEntry = oLogEntry.NextLink()
iLogNum :+ 1
Wend
SetViewport 0, 0, 720, 460; SetColor 255,255,255; SetImageFont Null
Flip False
Case tmPatch
'=====> Patcher
oPatcher.Update()
If oPatcher.GetShutdown() <> Null Then
Local oProcess:TProcess = CreateProcess(oPatcher.GetShutdown())
TProcess.ProcessList.Remove oProcess
PostEvent(TEvent.Create(EVENT_WINDOWCLOSE, gdPatcherWindow, 0, 0, 684, 0, Null))
EndIf
Case tmResource
LoadResource("GFX/LNC/LAUxPATxB.png",, imMainBackground, riMainBackground)
LoadResource("GFX/LNC/LAUxPATxA.png",, imMainForeground, riMainForeground)
LoadResource("GFX/LNC/BARxPROGRESS.png",, imProgressBar, riProgressBar)
LoadResource("GFX/LNC/BTNxCLOSE.png",, imButtonClose, riButtonClose)
LoadResource("GFX/LNC/BTNxACCOUNT.png",, imButtonAccount, riButtonAccount)
LoadResource("GFX/LNC/BTNxWEBSITE.png",, imButtonWebsite, riButtonWebsite)
LoadResource("GFX/LNC/BTNxSUPPORT.png",, imButtonSupport, riButtonSupport)
LoadResource("GFX/LNC/BTNxEULATOS.png",, imButtonEULATOS, riButtonEULATOS)
LoadResource("GFX/LNC/BTNxCHECK.png",, imButtonCheck, riButtonCheck)
LoadResource("GFX/LNC/BTNxPATCH.png",, imButtonPatch, riButtonPatch)
LoadResource("GFX/LNC/BTNxPLAY.png",, imButtonPlay, riButtonPlay)
LoadFontResource("GFX/FNT/TranscencsGames.otf", 10,, fnSmallFont, rfSmallFont)
LoadFontResource("GFX/FNT/TranscencsGames.otf", 12,, fnMediumFont, rfMediumFont)
LoadFontResource("GFX/FNT/TranscencsGames.otf", 14,, fnBigFont, rfBigFont)
Case gdPatcherWindow
Select EventID()
Case EVENT_WINDOWCLOSE
'=====> End the patcher.
End
End Select
EndSelect
Forever
'=====> Functions
Function PointInsideRect:Byte(PX:Int, PY:Int, RX:Int, RY:Int, RW:Int, RH:Int)
If PX >= RX And PX < RX + RW Then
If PY >= RY And PY < RY + RH Then
Return True
EndIf
EndIf
Return False
EndFunction
Function GetButtonState:Byte(BS:Int, BX:Int, BY:Int, BW:Int, BH:Int, MX:Int, MY:Int, MB:Int)
Local retVal:Int = BS
If PointInsideRect(MX, MY, BX, BY, BW, BH) = True Then
If BS = BTN_STT_NORMAL Then
retVal = BTN_STT_HOVER
ElseIf BS = BTN_STT_HOVER And MB = True Then
retVal = BTN_STT_DOWN
ElseIf BS = BTN_STT_DOWN And MB = False Then
retVal = BTN_STT_ACTION
ElseIf BS = BTN_STT_ACTION Then
retVal = BTN_STT_HOVER
EndIf
Else
retVal = BTN_STT_NORMAL
EndIf
Return retVal
EndFunction
Function DrawBorder(X:Int, Y:Int, W:Int, H:Int)
DrawLine X, Y, X+W, Y
DrawLine X+W, Y, X+W, Y+H
DrawLine X+W, Y+H, X, Y+H
DrawLine X, Y+H, X, Y
EndFunction
Function DrawButtonState(BS:Int, BX:Int, BY:Int, BW:Int, BH:Int, imButton:TImage, Text:String = "")
SetBlend ALPHABLEND; SetAlpha 1.0; SetColor 255, 255, 255
SetTransform 0, 1, 1;SetOrigin 0, 0; SetImageFont Null
Select BS
Case BTN_STT_NORMAL
If imButton <> Null Then
DrawSubImageRect(imButton, BX, BY, BW, BH, 0, 0, BW, BH, 0, 0, 0)
Else
SetColor 0, 0, 0;DrawRect BX, BY, BW, BH
SetColor 255, 255, 255;DrawBorder(BX,BY,BW,BH)
DrawText Text, BX + BW/2 - TextWidth(Text)/2, BY + BH/2 - TextHeight(Text)/2
EndIf
Case BTN_STT_HOVER
If imButton <> Null Then
DrawSubImageRect(imButton, BX, BY, BW, BH, 0, BH, BW, BH, 0, 0, 0)
Else
SetColor 0, 0, 0;DrawRect BX, BY, BW, BH
SetColor 204, 225, 255;DrawBorder(BX,BY,BW,BH)
DrawText Text, BX + BW/2 - TextWidth(Text)/2, BY + BH/2 - TextHeight(Text)/2
EndIf
Case BTN_STT_DOWN, BTN_STT_ACTION
If imButton <> Null Then
DrawSubImageRect(imButton, BX, BY, BW, BH, 0, BH*2, BW, BH, 0, 0, 0)
Else
SetColor 0, 0, 0;DrawRect BX, BY, BW, BH
SetColor 102, 123, 188;DrawBorder(BX,BY,BW,BH)
DrawText Text, BX + BW/2 - TextWidth(Text)/2, BY + BH/2 - TextHeight(Text)/2
EndIf
EndSelect
EndFunction
Function DrawProgressBar(X:Int, Y:Int, W:Int, H:Int, fProgress:Float, imProgressBar:TImage)
SetBlend ALPHABLEND; SetAlpha 1.0; SetColor 255, 255, 255
SetTransform 0, 1, 1;SetOrigin 0, 0
If imProgressBar = Null Then
SetColor 255, 255, 255;DrawBorder(X,Y,W,H)
SetColor 0, 0, 0;DrawRect X+1,Y+1,W-2,H-2
SetColor 204, 225, 255;SetAlpha 0.75 + Sin(MilliSecs()/5) * 0.25;DrawRect X, Y, W * fProgress, H
Else
DrawSubImageRect(imProgressBar, X, Y, W, H, 0, 0, W, H, 0, 0, 0)
SetAlpha 0.75 + Sin(MilliSecs()/5) * 0.25
Local iLength:Int = (W-6) * fProgress
DrawSubImageRect(imProgressBar, X, Y, 3, H, 0, H, 3, H, 0, 0, 0)
DrawSubImageRect(imProgressBar, X+3, Y, iLength, H, 3, H, iLength, H, 0, 0, 0)
DrawSubImageRect(imProgressBar, X+3+iLength, Y, 3, H, W-3, H, 3, H, 0, 0, 0)
EndIf
EndFunction
Function LoadResource(URL:String, Flags:Int = - 1, ImagePtr:TImage Var, InfoPtr:Int Var)
Local iModTime:Int = FileTime(URL)
If iModTime <> InfoPtr Then
ImagePtr = LoadImage(URL, Flags)
InfoPtr = iModTime
EndIf
EndFunction
Function LoadFontResource(URL:String, Size:Int, Style:Int = SMOOTHFONT, FontPtr:TImageFont Var, InfoPtr:Int Var)
Local iModTime:Int = FileTime(URL)
If iModTime <> InfoPtr Then
FontPtr = LoadImageFont(URL, Size, Style)
InfoPtr = iModTime
EndIf
EndFunction
EndRem
@@ -0,0 +1,300 @@
SuperStrict
Import BRL.Max2D
Import BRL.TextStream
Import PUB.OpenGL
Import PUB.Glew
Const MODE_REPEATX:Byte = $00000001 ' Repeat.
Const MODE_REPEATY:Byte = $00000010
Const MODE_MIRRORX:Byte = $00000100 ' Mirror every second repeat.
Const MODE_MIRRORY:Byte = $00001000
Const MODE_SCALEUPX:Byte = $00010000 ' Scale up to fit the destination area if the source doesn't fit exactly in.
Const MODE_SCALEUPY:Byte = $00100000
Const MODE_SCALEDOWNX:Byte = $01000000 ' Similar to MODE_SCALEUP*, except that it scales down to fit.
Const MODE_SCALEDOWNY:Byte = $10000000
Function DrawSubImageRectEx:Int(img:TImage, ..
dstX:Float, dstY:Float, dstW:Float, dstH:Float, ..
srcX:Float, srcY:Float, srcW:Float, srcH:Float, ..
hndX:Float=0, hndY:Float=0, frame:Int=0, bFlags:Byte=0)
Assert img <> Null Else "Image does Not exist"
Local bRepeatX:Byte = ((bFlags & MODE_REPEATX) <> 0)
Local bRepeatY:Byte = ((bFlags & MODE_REPEATY) <> 0)
Local bMirrorX:Byte = ((bFlags & MODE_MIRRORX) <> 0)
Local bMirrorY:Byte = ((bFlags & MODE_MIRRORY) <> 0)
Local bScaleUpX:Byte = ((bFlags & MODE_SCALEUPX) <> 0)
Local bScaleUpY:Byte = ((bFlags & MODE_SCALEUPY) <> 0)
Local bScaleDownX:Byte = ((bFlags & MODE_SCALEDOWNX) <> 0)
Local bScaleDownY:Byte = ((bFlags & MODE_SCALEDOWNY) <> 0)
Local lXRepeat:Float = 1, lXScale:Float = 1
If bRepeatX Then
lXRepeat = dstW / srcW
If bScaleUpX Then
lXRepeat = Floor(lXRepeat)
lXScale = (dstW / srcW) / lXRepeat
ElseIf bScaleDownX Then
lXRepeat = Ceil(lXRepeat)
lXScale = (dstW / srcW) / lXRepeat
EndIf
Else
lXScale = dstW / srcW
EndIf
Local lYRepeat:Float = 1, lYScale:Float = 1
If bRepeatY Then
lYRepeat = dstH / srcH
If bScaleUpY Then
lYRepeat = Floor(lYRepeat)
lYScale = (dstH / srcH) / lYRepeat
ElseIf bScaleDownY Then
lYRepeat = Ceil(lYRepeat)
lYScale = (dstH / srcH) / lYRepeat
EndIf
Else
lYScale = dstH / srcH
EndIf
Local lXSize:Float = srcW * lXScale, lYSize:Float = srcH * lYScale
Local lM2DScaleXOrig:Float, lM2DScaleYOrig:Float
Local lM2DScaleX:Float, lM2DScaleY:Float
GetScale(lM2DScaleXOrig, lM2DScaleYOrig)
GetScale(lM2DScaleX, lM2DScaleY)
' Cache some variables, so that we don't waste CPU time
Local lXRepeatFl:Int = Floor(lXRepeat), lXRepeatOverflow:Float = lXRepeat - lXRepeatFl
Local lYRepeatFl:Int = Floor(lYRepeat), lYRepeatOverflow:Float = lYRepeat - lYRepeatFl
For Local lYIndex:Int = 0 To lYRepeatFl
Local lYSizeMul:Float = 1
Local lYPos:Float = dstY + lYIndex * lYSize
If bMirrorY Then lM2DScaleY :* -1
If (lYIndex = lYRepeatFl) Then lYSizeMul = lYRepeatOverflow
For Local lXIndex:Int = 0 To lXRepeatFl
Local lXSizeMul:Float = 1
Local lXPos:Float = dstX + lXIndex * lXSize
If bMirrorX Then lM2DScaleX :* -1
If (lXIndex = lXRepeatFl) Then lXSizeMul = lXRepeatOverflow
SetScale lM2DScaleX, lM2DScaleY
DrawSubImageRect(img, lXPos, lYPos, lXSize * lXSizeMul, lYSize * lYSizeMul, srcX, srcY, srcW * lXSizeMul, srcH * lYSizeMul, hndX, hndY, frame)
Next
Next
SetScale(lM2DScaleXOrig, lM2DScaleYOrig)
EndFunction
Function DrawTiledImage:Int(img:TImage, dstX:Float, dstY:Float, dstW:Float, dstH:Float, srcX:Float, srcY:Float, srcW:Float, srcH:Float, hndX:Float=0, hndY:Float=0, frame:Int=0, lft:Float, top:Float, rgt:Float, btm:Float, bBackground:Byte=True, bFlags:Byte=MODE_REPEATX | MODE_REPEATY)
DrawSubImageRect(img, dstX, dstY, lft, top, srcX, srcY, lft, top, hndX, hndY, frame)
DrawSubImageRect(img, dstX + dstW - rgt, dstY, rgt, top, srcX + srcW - rgt, srcY, rgt, top, hndX, hndY, frame)
DrawSubImageRect(img, dstX, dstY + dstH - btm, lft, top, srcX, srcY + srcH - btm, lft, btm, hndX, hndY, frame)
DrawSubImageRect(img, dstX + dstW - rgt, dstY + dstH - btm, rgt, top, srcX + srcW - rgt, srcY + srcH - btm, rgt, btm, hndX, hndY, frame)
' Left
DrawSubImageRectEx(img, dstX, dstY + top, lft, dstH - top - btm, srcX, srcY + top, lft, srcH - top - btm, hndX, hndY, frame, bFlags)
' Right
DrawSubImageRectEx(img, dstX + dstW - rgt, dstY + top, rgt, dstH - top - btm, srcX + srcW - rgt, srcY + top, rgt, srcH - top - btm, hndX, hndY, frame, bFlags)
' Top
DrawSubImageRectEx(img, dstX + lft, dstY, dstW - lft - rgt, top, srcX + lft, srcY, srcW - lft - rgt, top, hndX, hndY, frame, bFlags)
' Bottom
DrawSubImageRectEx(img, dstX + lft, dstY + dstH - btm, dstW - lft - rgt, btm, srcX + lft, srcY + srcH - btm, srcW - lft - rgt, btm, hndX, hndY, frame, bFlags)
If bBackground Then DrawSubImageRectEx(img, dstX + lft, dstY + top, dstW - lft - rgt, dstH - top - btm, srcX + lft, srcY + top, srcW - lft - rgt, srcH - top - btm, hndX, hndY, frame, bFlags)
End Function
' Max2D Shader Support ---------------------------------------------------------
Type TShader
' Functions ----------------------------------------------------------------
Function Create:TShader()
Return (New TShader)
EndFunction
Function CreateVertex:TShader(oVertexCode:String)
Local oShader:TShader = TShader.Create()
oShader.Load(oVertexCode, True)
Return oShader
EndFunction
Function CreateFragement:TShader(oFragmentCode:String)
Local oShader:TShader = TShader.Create()
oShader.Load(oFragmentCode, True)
Return oShader
EndFunction
Function CreateCombined:TShader(oVertexCode:String, oFragmentCode:String)
Local oShader:TShader = TShader.Create()
oShader.Load(oVertexCode, True)
oShader.Load(oFragmentCode, False)
Return oShader
EndFunction
Function CheckForErrors:Int(ShaderObject:Int, ErrorString:String Var, Compiled:Int = True)
Local Successful:Int
If Compiled Then
glGetShaderiv (ShaderObject, GL_COMPILE_STATUS, Varptr Successful)
Else
glGetProgramiv(ShaderObject, GL_LINK_STATUS, Varptr Successful)
EndIf
If Not Successful Then
Local ErrorLength:Int
glGetObjectParameterivARB(ShaderObject, GL_OBJECT_INFO_LOG_LENGTH_ARB, Varptr ErrorLength)
Local Message:Byte Ptr = MemAlloc(ErrorLength), Dummy:Int
glGetInfoLogARB(ShaderObject, ErrorLength, Varptr Dummy, Message)
ErrorString = String.FromCString(Message)
MemFree(Message)
Return True
EndIf
Return False
End Function
Function CheckCompatability:Int()
Local Extensions:String = String.FromCString(Byte Ptr glGetString(GL_EXTENSIONS))
Local GLVersion:String = String.FromCString(Byte Ptr glGetString(GL_VERSION))
Local GLVersionInt:Int = GLVersion[.. 3].Replace(".", "").ToInt()
DebugLog Extensions
If Extensions.Find("GL_ARB_shader_objects" ) >= 0 And ..
Extensions.Find("GL_ARB_vertex_shader" ) >= 0 And ..
Extensions.Find("GL_ARB_fragment_shader") >= 0 or GLVersionInt >= 20 Then
Return True
EndIf
Return False
End Function
' Variables ----------------------------------------------------------------
Field iProgramObject:Int ' Shader Program Object
Field tError:String ' Shader Compile Errors & Warnings
' Members ------------------------------------------------------------------
Method New()
Self.iProgramObject = glCreateProgram()
EndMethod
Method Delete()
glDeleteProgram(Self.iProgramObject)
EndMethod
'' Retrieves the error that happened during loading or linking.
' @return <String> Error log retrieved from the
Method GetError:String()
Return Self.tError
EndMethod
'' Loads a new shader and, if successful, attaches it to the program.
' @param <String> tShaderCode A string containing the shader code.
' @param <Bool> bIsVertexShader Is this code a vertex Shader
' @return <Bool> Success
Method Load:Byte(tShaderCode:String, bIsVertexShader:Byte = True)
Local liShaderObject:Int
If tShaderCode = Null Then Return False
If tShaderCode.length = 0 Then Return False
' Create a new Shader Object, either for Vertex or Fragment processing.
If bIsVertexShader Then
liShaderObject = glCreateShader(GL_VERTEX_SHADER)
Else
liShaderObject = glCreateShader(GL_FRAGMENT_SHADER)
EndIf
If liShaderObject = 0 Then Return False
' Load the shader source into the compiler.
Local lbShaderCodePtr:Byte Ptr = tShaderCode.ToCString()
Local liShaderLength:Int = tShaderCode.length
glShaderSource(liShaderObject, 1, VarPtr lbShaderCodePtr, VarPtr liShaderLength)
MemFree(lbShaderCodePtr)
' Compile the shader and check for errors
glCompileShader(liShaderObject)
If (TShader.CheckForErrors(liShaderObject, Self.tError, True) = False) Then
glAttachShader(iProgramObject, liShaderObject)
glDeleteShader(liShaderObject)
Return True
EndIf
glDeleteShader(liShaderObject)
EndMethod
'' Links the attached shaders to the program, if successful.
' @return <Bool> Success
Method Link:Byte()
glLinkProgramARB(Self.iProgramObject)
Return (TShader.CheckForErrors(Self.iProgramObject, Self.tError, False) = False)
EndMethod
'' Enable the this program and disable all other programs.
' @return <Bool> Success
Method Enable:Byte()
glUseProgramObjectARB(Self.iProgramObject)
Return (TShader.CheckForErrors(Self.iProgramObject, Self.tError, False) = False)
End Method
'' Disable the all programs.
' @return <Bool> Success
Method Disable:Byte()
glUseProgramObjectARB(0)
Return (TShader.CheckForErrors(Self.iProgramObject, Self.tError, False) = False)
End Method
'' Uniform Management
Method GetUniformLocation:Int(tUniform:String)
Return glGetUniformLocationARB(Self.iProgramObject, tUniform)
End Method
Method SetUniform1F(tUniform:String, fValue1:Float)
glUniform1f(GetUniformLocation(tUniform), fValue1)
EndMethod
Method SetUniform2F(tUniform:String, fValue1:Float, fValue2:Float)
glUniform2f(GetUniformLocation(tUniform), fValue1, fValue2)
EndMethod
Method SetUniform3F(tUniform:String, fValue1:Float, fValue2:Float, fValue3:Float)
glUniform3f(GetUniformLocation(tUniform), fValue1, fValue2, fValue3)
EndMethod
Method SetUniform4F(tUniform:String, fValue1:Float, fValue2:Float, fValue3:Float, fValue4:Float)
glUniform4f(GetUniformLocation(tUniform), fValue1, fValue2, fValue3, fValue4)
EndMethod
Method SetUniform1I(tUniform:String, iValue1:Int)
glUniform1i(GetUniformLocation(tUniform), iValue1)
EndMethod
Method SetUniform2I(tUniform:String, iValue1:Int, iValue2:Int)
glUniform2i(GetUniformLocation(tUniform), iValue1, iValue2)
EndMethod
Method SetUniform3I(tUniform:String, iValue1:Int, iValue2:Int, iValue3:Int)
glUniform3i(GetUniformLocation(tUniform), iValue1, iValue2, iValue3)
EndMethod
Method SetUniform4I(tUniform:String, iValue1:Int, iValue2:Int, iValue3:Int, iValue4:Int)
glUniform4i(GetUniformLocation(tUniform), iValue1, iValue2, iValue3, iValue4)
EndMethod
Method SetUniform1UI(tUniform:String, iValue1:Int)
glUniform1ui(GetUniformLocation(tUniform), iValue1)
EndMethod
Method SetUniform2UI(tUniform:String, iValue1:Int, iValue2:Int)
glUniform2ui(GetUniformLocation(tUniform), iValue1, iValue2)
EndMethod
Method SetUniform3UI(tUniform:String, iValue1:Int, iValue2:Int, iValue3:Int)
glUniform3ui(GetUniformLocation(tUniform), iValue1, iValue2, iValue3)
EndMethod
Method SetUniform4UI(tUniform:String, iValue1:Int, iValue2:Int, iValue3:Int, iValue4:Int)
glUniform4ui(GetUniformLocation(tUniform), iValue1, iValue2, iValue3, iValue4)
EndMethod
EndType
@@ -0,0 +1,9 @@
Sirius Online Launcher
=======================
Originally supposed to be the official launcher, it was later dumped as contact died off to the lead developer due to him going from 100mbit to potato quality internet. He didn't like the idea that it would check for an update and download it, instead of letting you play directly. Neither did he like the way the updates were handled, hash based checking for new files seemed to not go over well to him.
The project contains some things from the forums for BlitzMax, as well as my try at adding some extra support to Max2D. Remember Blitz3D? The 2D system in BlitzMax is basically the same, except worse.
License
=======
Sirius Online Launcher by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+285
View File
@@ -0,0 +1,285 @@
Strict
Import BRL.Retro
Function MD5$(in:String Var)
Local h0 = $67452301, h1 = $EFCDAB89, h2 = $98BADCFE, h3 = $10325476
Local r[] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,..
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,..
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,..
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]
Local k[] = [$D76AA478, $E8C7B756, $242070DB, $C1BDCEEE, $F57C0FAF, $4787C62A,..
$A8304613, $FD469501, $698098D8, $8B44F7AF, $FFFF5BB1, $895CD7BE,..
$6B901122, $FD987193, $A679438E, $49B40821, $F61E2562, $C040B340,..
$265E5A51, $E9B6C7AA, $D62F105D, $02441453, $D8A1E681, $E7D3FBC8,..
$21E1CDE6, $C33707D6, $F4D50D87, $455A14ED, $A9E3E905, $FCEFA3F8,..
$676F02D9, $8D2A4C8A, $FFFA3942, $8771F681, $6D9D6122, $FDE5380C,..
$A4BEEA44, $4BDECFA9, $F6BB4B60, $BEBFBC70, $289B7EC6, $EAA127FA,..
$D4EF3085, $04881D05, $D9D4D039, $E6DB99E5, $1FA27CF8, $C4AC5665,..
$F4292244, $432AFF97, $AB9423A7, $FC93A039, $655B59C3, $8F0CCC92,..
$FFEFF47D, $85845DD1, $6FA87E4F, $FE2CE6E0, $A3014314, $4E0811A1,..
$F7537E82, $BD3AF235, $2AD7D2BB, $EB86D391]
Local intCount = (((in$.length + 8) Shr 6) + 1) Shl 4
Local data[intCount]
For Local c=0 Until in$.length
data[c Shr 2] = data[c Shr 2] | ((in$[c] & $FF) Shl ((c & 3) Shl 3))
Next
data[in$.length Shr 2] = data[in$.length Shr 2] | ($80 Shl ((in$.length & 3) Shl 3))
data[data.length - 2] = (Long(in$.length) * 8) & $FFFFFFFF
data[data.length - 1] = (Long(in$.length) * 8) Shr 32
For Local chunkStart=0 Until intCount Step 16
Local a = h0, b = h1, c = h2, d = h3
For Local i=0 To 15
Local f = d ~ (b & (c ~ d))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + i]), r[i]) + b
a = t
Next
For Local i=16 To 31
Local f = c ~ (d & (b ~ c))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + (((5 * i) + 1) & 15)]), r[i]) + b
a = t
Next
For Local i=32 To 47
Local f = b ~ c ~ d
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + (((3 * i) + 5) & 15)]), r[i]) + b
a = t
Next
For Local i=48 To 63
Local f = c ~ (b | ~d)
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + ((7 * i) & 15)]), r[i]) + b
a = t
Next
h0 :+ a ; h1 :+ b
h2 :+ c ; h3 :+ d
Next
Return (LEHex(h0) + LEHex(h1) + LEHex(h2) + LEHex(h3))
End Function
Function MD5Bank:String(inbank:TBank Var)
Local h0 = $67452301, h1 = $EFCDAB89, h2 = $98BADCFE, h3 = $10325476
Local r[] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,..
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,..
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,..
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]
Local k[] = [$D76AA478, $E8C7B756, $242070DB, $C1BDCEEE, $F57C0FAF, $4787C62A,..
$A8304613, $FD469501, $698098D8, $8B44F7AF, $FFFF5BB1, $895CD7BE,..
$6B901122, $FD987193, $A679438E, $49B40821, $F61E2562, $C040B340,..
$265E5A51, $E9B6C7AA, $D62F105D, $02441453, $D8A1E681, $E7D3FBC8,..
$21E1CDE6, $C33707D6, $F4D50D87, $455A14ED, $A9E3E905, $FCEFA3F8,..
$676F02D9, $8D2A4C8A, $FFFA3942, $8771F681, $6D9D6122, $FDE5380C,..
$A4BEEA44, $4BDECFA9, $F6BB4B60, $BEBFBC70, $289B7EC6, $EAA127FA,..
$D4EF3085, $04881D05, $D9D4D039, $E6DB99E5, $1FA27CF8, $C4AC5665,..
$F4292244, $432AFF97, $AB9423A7, $FC93A039, $655B59C3, $8F0CCC92,..
$FFEFF47D, $85845DD1, $6FA87E4F, $FE2CE6E0, $A3014314, $4E0811A1,..
$F7537E82, $BD3AF235, $2AD7D2BB, $EB86D391]
Local intCount = (((inbank.Size() + 8) Shr 6) + 1) Shl 4
Local data[intCount]
Local inPtr:Byte Ptr = inbank.Buf()
For Local c=0 Until inbank.Size()
data[c Shr 2] = data[c Shr 2] | ((inPtr[c] & $FF) Shl ((c & 3) Shl 3))
Next
data[inbank.Size() Shr 2] = data[inbank.Size() Shr 2] | ($80 Shl ((inbank.Size() & 3) Shl 3))
data[data.length - 2] = (Long(inbank.Size()) * 8) & $FFFFFFFF
data[data.length - 1] = (Long(inbank.Size()) * 8) Shr 32
For Local chunkStart=0 Until intCount Step 16
Local a = h0, b = h1, c = h2, d = h3
For Local i=0 To 15
Local f = d ~ (b & (c ~ d))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + i]), r[i]) + b
a = t
Next
For Local i=16 To 31
Local f = c ~ (d & (b ~ c))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + (((5 * i) + 1) & 15)]), r[i]) + b
a = t
Next
For Local i=32 To 47
Local f = b ~ c ~ d
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + (((3 * i) + 5) & 15)]), r[i]) + b
a = t
Next
For Local i=48 To 63
Local f = c ~ (b | ~d)
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + ((7 * i) & 15)]), r[i]) + b
a = t
Next
h0 :+ a ; h1 :+ b
h2 :+ c ; h3 :+ d
Next
Return (LEHex(h0) + LEHex(h1) + LEHex(h2) + LEHex(h3))
End Function
Function SHA1$(in$)
Local h0 = $67452301, h1 = $EFCDAB89, h2 = $98BADCFE, h3 = $10325476, h4 = $C3D2E1F0
Local intCount = (((in$.length + 8) Shr 6) + 1) Shl 4
Local data[intCount]
For Local c=0 Until in$.length
data[c Shr 2] = (data[c Shr 2] Shl 8) | (in$[c] & $FF)
Next
data[in$.length Shr 2] = ((data[in$.length Shr 2] Shl 8) | $80) Shl ((3 - (in$.length & 3)) Shl 3)
data[data.length - 2] = (Long(in$.length) * 8) Shr 32
data[data.length - 1] = (Long(in$.length) * 8) & $FFFFFFFF
For Local chunkStart=0 Until intCount Step 16
Local a = h0, b = h1, c = h2, d = h3, e = h4
Local w[] = data[chunkStart..chunkStart + 16]
w = w[..80]
For Local i=16 To 79
w[i] = Rol(w[i - 3] ~ w[i - 8] ~ w[i - 14] ~ w[i - 16], 1)
Next
For Local i=0 To 19
Local t = Rol(a, 5) + (d ~ (b & (c ~ d))) + e + $5A827999 + w[i]
e = d ; d = c
c = Rol(b, 30)
b = a ; a = t
Next
For Local i=20 To 39
Local t = Rol(a, 5) + (b ~ c ~ d) + e + $6ED9EBA1 + w[i]
e = d ; d = c
c = Rol(b, 30)
b = a ; a = t
Next
For Local i=40 To 59
Local t = Rol(a, 5) + ((b & c) | (d & (b | c))) + e + $8F1BBCDC + w[i]
e = d ; d = c
c = Rol(b, 30)
b = a ; a = t
Next
For Local i=60 To 79
Local t = Rol(a, 5) + (b ~ c ~ d) + e + $CA62C1D6 + w[i]
e = d ; d = c
c = Rol(b, 30)
b = a ; a = t
Next
h0 :+ a ; h1 :+ b ; h2 :+ c
h3 :+ d ; h4 :+ e
Next
Return (Hex(h0) + Hex(h1) + Hex(h2) + Hex(h3) + Hex(h4)).ToLower()
End Function
Function SHA256$(in$)
Local h0 = $6A09E667, h1 = $BB67AE85, h2 = $3C6EF372, h3 = $A54FF53A
Local h4 = $510E527F, h5 = $9B05688C, h6 = $1F83D9AB, h7 = $5BE0CD19
Local k[] = [$428A2F98, $71374491, $B5C0FBCF, $E9B5DBA5, $3956C25B, $59F111F1,..
$923F82A4, $AB1C5ED5, $D807AA98, $12835B01, $243185BE, $550C7DC3,..
$72BE5D74, $80DEB1FE, $9BDC06A7, $C19BF174, $E49B69C1, $EFBE4786,..
$0FC19DC6, $240CA1CC, $2DE92C6F, $4A7484AA, $5CB0A9DC, $76F988DA,..
$983E5152, $A831C66D, $B00327C8, $BF597FC7, $C6E00BF3, $D5A79147,..
$06CA6351, $14292967, $27B70A85, $2E1B2138, $4D2C6DFC, $53380D13,..
$650A7354, $766A0ABB, $81C2C92E, $92722C85, $A2BFE8A1, $A81A664B,..
$C24B8B70, $C76C51A3, $D192E819, $D6990624, $F40E3585, $106AA070,..
$19A4C116, $1E376C08, $2748774C, $34B0BCB5, $391C0CB3, $4ED8AA4A,..
$5B9CCA4F, $682E6FF3, $748F82EE, $78A5636F, $84C87814, $8CC70208,..
$90BEFFFA, $A4506CEB, $BEF9A3F7, $C67178F2]
Local intCount = (((in$.length + 8) Shr 6) + 1) Shl 4
Local data[intCount]
For Local c=0 Until in$.length
data[c Shr 2] = (data[c Shr 2] Shl 8) | (in$[c] & $FF)
Next
data[in$.length Shr 2] = ((data[in$.length Shr 2] Shl 8) | $80) Shl ((3 - (in$.length & 3)) Shl 3)
data[data.length - 2] = (Long(in$.length) * 8) Shr 32
data[data.length - 1] = (Long(in$.length) * 8) & $FFFFFFFF
For Local chunkStart=0 Until intCount Step 16
Local a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7
Local w[] = data[chunkStart..chunkStart + 16]
w = w[..64]
For Local i=16 To 63
w[i] = w[i - 16] + (Ror(w[i - 15], 7) ~ Ror(w[i - 15], 18) ~ (w[i - 15] Shr 3))..
+ w[i - 7] + (Ror(w[i - 2], 17) ~ Ror(w[i - 2], 19) ~ (w[i - 2] Shr 10))
Next
For Local i=0 To 63
Local t0 = (Ror(a, 2) ~ Ror(a, 13) ~ Ror(a, 22)) + ((a & b) | (b & c) | (c & a))
Local t1 = h + (Ror(e, 6) ~ Ror(e, 11) ~ Ror(e, 25)) + ((e & f) | (~e & g)) + k[i] + w[i]
h = g ; g = f ; f = e ; e = d + t1
d = c ; c = b ; b = a ; a = t0 + t1
Next
h0 :+ a ; h1 :+ b ; h2 :+ c ; h3 :+ d
h4 :+ e ; h5 :+ f ; h6 :+ g ; h7 :+ h
Next
Return (Hex(h0) + Hex(h1) + Hex(h2) + Hex(h3) + Hex(h4) + Hex(h5) + Hex(h6) + Hex(h7)).ToLower()
End Function
Function Rol(val, shift)
Return (val Shl shift) | (val Shr (32 - shift))
End Function
Function Ror(val, shift)
Return (val Shr shift) | (val Shl (32 - shift))
End Function
Function LEHex$(val)
Local out$ = Hex(val)
Return out$[6..8] + out$[4..6] + out$[2..4] + out$[0..2]
End Function
+184
View File
@@ -0,0 +1,184 @@
SuperStrict
Import BRL.LinkedList
Import BRL.Map
Import BRL.Graphics
Import BRL.GLGraphics
Import BRL.Max2D
Import BRL.GLMax2D
Import BRL.Pixmap
Import Pub.OpenGL
Import "Max2DExtended.bmx"
Import BRL.BMPLoader
Import BRL.JPGLoader
Import BRL.PNGLoader
Import BRL.TGALoader
'-------------------------------------------------------------------------------
Type TGUI
' Variables ----------------------------------------------------------------
' Skinning
Field oSkinImageSet:TPixmap = Null
' GUI Area
Field oRootGadget:TGUIGadget = New TGUIGadget
' Functions ----------------------------------------------------------------
Function Create:TGUI(X:Float, Y:Float, W:Float, H:Float, Skin:Object)
Local loGUI:TGUI = New TGUI
Return loGUI
EndFunction
' Members ------------------------------------------------------------------
Method New()
Self.oRootGadget = (New TGUIGadget)
EndMethod
Method Destroy()
Self.oRootGadget = Null
EndMethod
Method Update:Int(fDelta:Float)
oRootGadget.Update(fDelta)
EndMethod
Method Render:Int(fDelta:Float)
oRootGadget.Render(fDelta)
EndMethod
'' Changes the
Method SetRootGadget:TGUIGadget(oRootGadget:TGUIGadget)
If oRootGadget = Null Or oRootGadget.Insane() Then Return Null
Local loRootWindow:TGUIGadget = Self.oRootGadget
Self.oRootGadget = oRootGadget
Return loRootWindow
EndMethod
Method GetRootGadget:TGUIGadget()
Return oRootGadget
EndMethod
EndType
'-------------------------------------------------------------------------------
Type TGUIGadget
' Constants ----------------------------------------------------------------
Const COORD_ABSOLUTE:Byte = 0
Const COORD_RELATIVE:Byte = 1
' Variables ----------------------------------------------------------------
' Gadget Coordinates
Field bLocalCoordType:Byte[] = New Byte[4]
Field dLocalCoord:Double[] = New Double[4]
Field dCoord:Double[] = New Double[4]
' Parent and Childs
Field oParentGUI:TGUI = Null
Field oParent:TGUIGadget = Null
Field oChildList:TList = New TList
' Members ------------------------------------------------------------------
'' Deconstructor for TGUIGadget
' Automatically removed itself from the parent and releases all pointers to chils
Method Delete()
' Unregister from parent gadget and release all pointers to childs.
SetParent(Null)
Self.oChildList.Clear()
' Destroy objects in reverse order.
Self.bCoordType = Null
Self.dCoord = Null
Self.dLocalCoord = Null
Self.oChildList = Null
EndMethod
'' Checks if the Gadget went insane due to invalid usage or other influence.
' @return <Bool> True if the TGUIGadget went insane, otherwise false.
Method Insane:Byte()
If Self.bCoordType = Null Then Return True
If Self.dCoord = Null Then Return True
If Self.dLocalCoord = Null Then Return True
If Self.oChildList = Null Then Return True
EndMethod
'' Updates the GUIGadget and any other objects in it.
' @return <Int>
Method Update:Int(fDelta:Float)
EndMethod
Method Render:Int(fDelta:Float)
EndMethod
' Parent Management
Method SetParent(oParent:TGUIGadget)
If Self.oParent <> Null Then Self.oParent.RemoveChild(Self)
If oParent <> Null Then oParent.AddChild(Self)
EndMethod
Method GetParent:TGUIGadget()
Return Self.oParent
EndMethod
' Child Management
Method IsChild:Int(oChild:TGUIGadget)
If oChild = Null Then Return False
Return Self.oChildList.Contains(oChild)
EndMethod
Method AddChild:Int(oChild:TGUIGadget)
If oChild <> Null Then
If IsChild(oChild) Then
Return True
Else
Return (Self.oChildList.AddLast(oChild) <> Null)
EndIf
EndIf
EndMethod
Method RemoveChild:Int(oChild:TGUIGadget)
If oChild <> Null Then
If IsChild(oChild) Then
Return True
Else
Return Self.oChildList.Remove(oChild)
EndIf
EndIf
EndMethod
Method GetChildAtIndex:TGUIGadget(iIndex:Int)
If iIndex <> -1 Then
Local liChildCount:Int = Self.oChildList.Count()
If iIndex >= 0 And iIndex < liChildCount Then
Return Self.oChildList.ValueAtIndex(iIndex)
Else
Return Null
EndIf
Else
Return Self.oChildList.Last()
EndIf
EndMethod
Method SetChildIndex:Int(oChild:TGUIGadget, iIndex:Int)
If oChild <> Null Then
If IsChild(oChild) Then
Local liChildCount:Int = Self.oChildList.Count()
If iIndex >= 0 And iIndex < liChildCount Then
'Local loChild:TGUIGadget = Self.oChildList.ValueAtIndex(iIndex)
'Local lChild:TGUIGadget = Self.oChildList.ValueAtIndex(iIndex)
'Self.oChildList.Insert
EndIf
EndIf
EndIf
EndMethod
' Signal Handlers ----------------------------------------------------------
EndType
'-------------------------------------------------------------------------------
Public
Type TGUIWindow Extends TGUIGadget
'-------------------------------------------------------------------------------
EndType
@@ -0,0 +1,435 @@
SuperStrict
Import BaH.libcurl
Import BRL.Bank
Import BRL.FileSystem
Import BRL.LinkedList
Import BRL.StandardIO
Import BRL.Stream
Import BRL.Timer
Import "Clock.c"
Import "Digest.bmx"
Type TPatcher
Const STATE_DEFAULT:Byte = 0
Const STATE_PATCHINFO:Byte = 1
Const STATE_CHECKING:Byte = 2
Const STATE_PREPATCH:Byte = 3
Const STATE_PATCHING:Byte = 4
Const STATE_COMPLETE:Byte = 5
Const STATE_LAUNCHER:Byte = 6
Const SSTATE_ENTER:Byte = 0
Const SSTATE_WORK:Byte = 1
Const SSTATE_LEAVE:Byte = 2
Const SERVER:String = "http://sirius-online.us.to/patch/"
' State-based Patcher
Field m_bState:Byte = TPatcher.STATE_DEFAULT
Field m_bSubState:Byte = TPatcher.SSTATE_ENTER
' lib/cURL is used for downloading of data.
Field m_oCurlMulti:TCurlMulti = Null
Field m_oCurl:TCurlEasy = Null
Field m_fCurlProgress:Float
' State: All
Field m_oTaskList:TList = New TList
Field m_fProgress:Float = 0
' State: Patchinfo, Checking, Patching
Field m_oFileHashList:TList = New TList
Field m_iFileCount:Int = 0
' State: Checking, Patching
Field m_oFileLoader:TAsyncLoader = New TAsyncLoader
Field m_oFileHashPair:TFileHash = Null
' State: Patching
Field m_oFileList:TList = New TList
Field m_oFile:String, m_oFileDL:String
Field m_oFileStream:TStream
' Construction
Method New()
EndMethod
Function Create:TPatcher()
Local oPatcher:TPatcher = New TPatcher
Return oPatcher
EndFunction
' Deconstruction
Method Destroy()
m_oCurlMulti.multiCleanup()
m_oCurl.cleanup()
EndMethod
' Basically the Main Loop of the Patcher, handles everything. Call GetShutdown:String() if you want to know when the patcher is telling you to run an executable and close.
Method Update()
' Check
Select m_bState
Case TPatcher.STATE_DEFAULT
If m_bSubState = TPatcher.SSTATE_ENTER Then
m_oCurlMulti = TCurlMulti.Create()
m_oCurl = m_oCurlMulti.newEasy()
m_oCurl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
m_oCurl.setOptInt(CURLOPT_CRLF, False)
m_oCurl.setOptString(CURLOPT_USERAGENT, "Sirius Online Launcher")
m_oCurl.setOptString(CURLOPT_REFERER, TPatcher.SERVER)
m_oCurl.setOptString(CURLOPT_URL, TPatcher.SERVER + "info")
m_oCurl.setProgressCallback(TPatcher.ProgressCallback, Self)
m_oCurl.setWriteString()
m_oTaskList.AddFirst("n[WAIT] Getting patch information...")
m_bSubState = TPatcher.SSTATE_WORK
EndIf
If m_bSubState = TPatcher.SSTATE_WORK Then
Local iResult:Int = Perform()
m_fProgress = m_fCurlProgress
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[" + RSet(String(Int(m_fProgress * 100)), 3) + "%] Retrieving patch information...")
If iResult = CURLM_OK Then
If m_fCurlProgress = 1.0 And m_iCurlMultiHandles = 0 Then
m_bSubState = TPatcher.SSTATE_LEAVE
EndIf
Else
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[FAIL] Retrieving patch information... ("+CurlError(iResult)+")")
SetState(TPatcher.STATE_COMPLETE)
EndIf
EndIf
If m_bSubState = TPatcher.SSTATE_LEAVE Then
m_oCurlMulti.multiRemove(m_oCurl)
m_oCurlMulti.multiCleanup()
m_oCurlMulti = Null
Local oCurlRCode:Int = m_oCurl.getInfo().responseCode()
Local stResult:String = m_oCurl.toString()
m_oCurl.cleanup()
m_oCurl = Null
If oCurlRCode <> 404 Then
m_oFileHashList.Clear()
If stResult.length > 0 Then
Local stFileHashArr:String[] = stResult.Split("~n")
For Local stFileHashPair:String = EachIn stFileHashArr
If stFileHashPair.length > 0 And stFileHashPair[0..1] <> "#" Then ' Ignore Comments
Local stPairArr:String[] = stFileHashPair.Split(":")
m_oFileHashList.AddLast(TFileHash.Create(stPairArr[0], stPairArr[1]))
EndIf
Next
m_iFileCount = m_oFileHashList.Count()
m_oFileList.Clear()
SetState(TPatcher.STATE_PATCHINFO) ' Got Patchinfo, and it had information.
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[ OK ] Retrieving patch information... done.")
Else
SetState(TPatcher.STATE_COMPLETE)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("e[FAIL] Retrieving patch information... invalid information file.")
EndIf
Else
SetState(TPatcher.STATE_COMPLETE)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("e[FAIL] Retrieving patch information... file not found.")
EndIf
EndIf
Case TPatcher.STATE_CHECKING
If m_bSubState = TPatcher.SSTATE_ENTER Then ' Used to load a new File
m_oFileHashPair = TFileHash(m_oFileHashList.RemoveFirst())
If m_oFileHashPair <> Null Then
m_oFileLoader.Initialize(m_oFileHashPair.stName)
m_oTaskList.AddFirst("n[WAIT] Checking '" + m_oFileHashPair.stName + "'...")
m_bSubState = TPatcher.SSTATE_WORK
Else
m_bSubState = TPatcher.SSTATE_LEAVE
EndIf
EndIf
If m_bSubState = TPatcher.SSTATE_WORK Then
If m_oFileLoader.m_bComplete = 0 Then
m_oFileLoader.Process(2, 1024)
m_fProgress = ((m_iFileCount - (m_oFileHashList.Count() + 1)) / Float(m_iFileCount)) + m_oFileLoader.m_fProgress * (1.0 / m_iFileCount)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[" + RSet(String(Int(m_fProgress * 100)), 3) + "%] Checking '" + m_oFileHashPair.stName + "'...")
Else
If m_oFileLoader.m_bComplete = 1
If m_oFileLoader.m_oBank <> Null Then
Local stHash:String = MD5Bank(m_oFileLoader.m_oBank).ToUpper()
If stHash <> m_oFileHashPair.stHash Then
m_oFileList.AddLast(m_oFileHashPair.stName)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("h[ OK ] Checking '" + m_oFileHashPair.stName + "'... requires update.")
Else
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[ OK ] Checking '" + m_oFileHashPair.stName + "'... up to date.")
EndIf
Else
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("e[FAIL] Checking '" + m_oFileHashPair.stName + "'... (File in use?)")
EndIf
Else
m_oFileList.AddLast(m_oFileHashPair.stName)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("h[ OK ] Checking '" + m_oFileHashPair.stName + "'... missing.")
EndIf
m_bSubState = TPatcher.SSTATE_ENTER
m_oFileLoader.Cleanup()
EndIf
EndIf
If m_bSubState = TPatcher.SSTATE_LEAVE Then
If m_oFileList.Count() > 0 Then
m_iFileCount = m_oFileList.Count()
SetState(TPatcher.STATE_PREPATCH)
Else
SetState(TPatcher.STATE_COMPLETE)
EndIf
EndIf
Case TPatcher.STATE_PATCHING
If m_bSubState = TPatcher.SSTATE_ENTER Then
Local m_oEntry:Object = m_oFileList.RemoveFirst()
If m_oEntry <> Null Then
m_oFile = String(m_oEntry);m_oFileDL = m_oFile + ".part"
CreateDir(ExtractDir(m_oFile), True)
m_oFileStream = WriteFile(m_oFileDL)
If m_oFileStream <> Null Then
m_oCurlMulti = TCurlMulti.Create()
m_oCurl = m_oCurlMulti.newEasy()
m_oCurl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
m_oCurl.setOptInt(CURLOPT_CRLF, False)
m_oCurl.setOptString(CURLOPT_USERAGENT, "Sirius Online Launcher")
m_oCurl.setOptString(CURLOPT_REFERER, TPatcher.SERVER + "info")
m_oCurl.setOptString(CURLOPT_URL, TPatcher.SERVER + m_oFile)
m_oCurl.setWriteStream(m_oFileStream)
m_oCurl.setProgressCallback(TPatcher.ProgressCallback, Self)
m_oTaskList.AddFirst("n[WAIT] Downloading '" + m_oFile + "'...")
m_bSubState = TPatcher.SSTATE_WORK
EndIf
Else
SetState(TPatcher.STATE_DEFAULT)
EndIf
EndIf
If m_bSubState = TPatcher.SSTATE_WORK Then
Local iResult:Int = Perform()
m_fProgress = ((m_iFileCount - (m_oFileList.Count() + 1)) / Float(m_iFileCount)) + m_fCurlProgress * (1.0 / m_iFileCount)
If iResult = CURLM_OK Then
m_oFileStream.Flush()
If m_fCurlProgress = 1.0 And m_iCurlMultiHandles = 0 Then
m_oCurlMulti.multiRemove(m_oCurl)
m_oCurlMulti.multiCleanup()
Local oCurlRCode:Int = m_oCurl.getInfo().responseCode()
m_oCurl.cleanup()
' Cleanup(1)
m_oCurl = Null
m_oCurlMulti = Null
m_oFileStream.Close()
m_oFileStream = Null
If oCurlRCode <> 404 Then
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[ OK ] Downloading '" + m_oFile + "'...")
' Rename files
If m_oFile <> "Launcher.exe" Then
RenameFile(m_oFile, m_oFile + ".old")
If RenameFile(m_oFileDL, m_oFile) Then
DeleteFile(m_oFile + ".old")
Else
RenameFile(m_oFile + ".old", m_oFile)
EndIf
Else' If we patched the launcher, tell the parent program to start the new one.
RenameFile(m_oFileDL, "-" + m_oFile)
m_oFileList.Clear() ' Clear the list to be sure
SetState(TPatcher.STATE_LAUNCHER)
EndIf
Else
DeleteFile(m_oFileDL)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("e[FAIL] Downloading '" + m_oFile + "'... file not found.")
EndIf
'Cleanup (2)
m_oFileDL = Null
m_oFile = Null
If m_oFileList.Count() = 0 Then
m_bSubState = TPatcher.SSTATE_LEAVE
Else
m_bSubState = TPatcher.SSTATE_ENTER
EndIf
Else
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("n[" + RSet(String(Int(m_fCurlProgress * 100)), 3) + "%] Downloading '" + m_oFile + "'...")
EndIf
Else
m_oFileStream.Close()
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("e[FAIL] Downloading '" + m_oFile + "'... " + CurlError(iResult))
EndIf
EndIf
If m_bSubState = TPatcher.SSTATE_LEAVE And m_bState = TPatcher.STATE_PATCHING Then
SetState(TPatcher.STATE_DEFAULT)
EndIf
EndSelect
EndMethod
Method Advance()
Select m_bState
Case TPatcher.STATE_PATCHINFO
SetState(TPatcher.STATE_CHECKING)
Case TPatcher.STATE_PREPATCH
SetState(TPatcher.STATE_PATCHING)
Case TPatcher.STATE_COMPLETE
m_stProcessToRun = "ExeFile.exe"
Case TPatcher.STATE_LAUNCHER
m_stProcessToRun = "-Launcher.exe 1"
EndSelect
EndMethod
Field m_iCurlMultiHandles:Int, m_bCurlMultiState:Byte = 0
Method Perform:Int()
Local iResult:Int = 0
iResult = MultiPerform()
Select m_bCurlMultiState
Case 0, 2
m_bCurlMultiState = (m_bCurlMultiState + 1) Mod 3
Case 1
If m_oCurlMulti.multiSelect(0.1) <> -1 And m_iCurlMultiHandles Then
iResult = MultiPerform()
If m_iCurlMultiHandles = 0 Then m_bCurlMultiState = 2
EndIf
EndSelect
Return iResult
EndMethod
Method MultiPerform:Int()
Local iResult:Int = m_oCurlMulti.multiPerform(m_iCurlMultiHandles)
While iResult = CURLM_CALL_MULTI_PERFORM
iResult = m_oCurlMulti.multiPerform(m_iCurlMultiHandles)
Wend
Return iResult
EndMethod
' State Management
Method SetState(bState:Byte)
m_bState = bState
m_bSubState = TPatcher.SSTATE_ENTER
m_fProgress = 0.0
EndMethod
Method GetState:Byte()
Return m_bState
EndMethod
' Information
Method GetProgress:Float()
Return m_fProgress
EndMethod
Field m_stProcessToRun:String = NUll
Method GetShutdown:String()
Return m_stProcessToRun
EndMethod
' Callbacks
Function ProgressCallback:Int(oPatcherObj:Object, dDownloadTotal:Double, dDownloadNow:Double, dUploadTotal:Double, dUploadNow:Double)
If dDownloadTotal = 0 And dDownloadNow = 0 And dUploadTotal = 0 And dUploadNow = 0 Then TPatcher(oPatcherObj).m_fCurlProgress = 0.0;Return 0
TPatcher(oPatcherObj).m_fCurlProgress = (dDownloadNow / dDownloadTotal)
EndFunction
EndType
Type TFileHash
Field stName:String, stHash:String
Function Create:TFileHash(stName:String, stHash:String)
Local oFH:TFileHash = New TFileHash
oFH.stName = stName
oFH.stHash = stHash
Return oFH
EndFunction
EndType
Type TAsyncLoader
Field m_oBank:TBank
Field m_oStream:TStream, m_iFileSize:Int
Field m_fProgress:Float, m_bComplete:Byte
Method Initialize(stFile:String)
If FileType(stFile) = FILETYPE_FILE Then
m_oStream = ReadFile(stFile)
If m_oStream <> Null Then
m_iFileSize = FileSize(stFile)
m_oBank = CreateBank(m_iFileSize)
If m_oBank <> Null Then
m_fProgress = 0.0
m_bComplete = False
Else
m_oStream.Close()
EndIf
Else
m_fProgress = 1.0
m_bComplete = -2
EndIf
Else
m_fProgress = 1.0
m_bComplete = -2
EndIf
EndMethod
Method Process(iMs:Float, iBufferSize:Int = 1024)
Local iClockStart:Int = getClock()
If (m_oStream <> Null And m_oBank <> Null) And m_oStream.Eof() = False Then
Local iClockNow:Int = getClock()
Repeat
Local iRemaining:Int = Min(m_iFileSize - m_oStream.Pos(), iBufferSize)
m_oBank.Read(m_oStream, m_oStream.Pos(), iRemaining)
iClockNow = getClock()
Until m_oStream.Eof() = True or getClockDiff(iClockStart, iClockNow) > (iMs / 1000.0 * getClocksPerSecond())
m_fProgress = m_oStream.Pos() / Float(m_iFileSize)
m_bComplete = m_oStream.Eof()
If m_oStream.Eof() = True Then
m_oStream.Close()
m_oStream = Null
EndIf
ElseIf m_bComplete = 0 Then
m_fProgress = 1.0
m_bComplete = -1
EndIf
EndMethod
Method Cleanup()
m_oBank = Null
EndMethod
EndType
Function DebugClock(Text:String)
DebugLog getClock() + ":" + Text
EndFunction
Extern "c"
Function getClocksPerSecond:Int()="getClocksPerSecond_"
Function getClock:Int()="getClock_"
Function getClockDiff:Int(clockStart:Int, clockEnd:Int)="getClockDiff_"
EndExtern
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
Sirius Online Server
=======================
This project was supposed to be the official server software for Sirius Online, before the idea of multiplayer was dumped completely. Talk about sticking to the project plan. Oh wait, there was none. Why did I join that trainwreck of a team. Anyway, the server was designed to be somewhat efficient at its job of calculating and transferring. It supports up to 65535 players and will re-use Ids where possible instead of constantly incrementing. This makes memory management really easy, but join times are sometimes higher than normal. The project uses Xaymar.IOQueue, something which no longer exists. All it did was store packets to be sent off at a later point in time. Networking was done using UDP and TCP, i think. No idea anymore, don't care either, I'm now using Unreal Engine 4 for game development.
License
=======
Sirius Online Server by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+639
View File
@@ -0,0 +1,639 @@
SuperStrict
'--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Framework BRL.Blitz
Import BRL.Threads
Import BRL.Timer
Import "BlitzNet.bmx"
'--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
' Fix GC weirdness
OnEnd(GCCollect)
Local Server:BNetServer = New BNetServer
Server.Open(27000, 27001, 8)
While
Server.Update()
Wend
Server.Close()
'----------------------------------------------------------------
'-- Types
'----------------------------------------------------------------
'Type Server
' Field m_Server:BNetServer
'End Type
Rem
Const VersionMajor:Byte = 0
Const VersionMinor:Byte = 40
Const Net_VersionMajor:Byte = 0
Const Net_VersionMinor:Byte = 1
' Network Initiation
Global InfoSocket:TSocket = TSocket.CreateTCP()
Global DataSocket:TSocket = TSocket.CreateUDP()
' Set up Information Socket.
Const SOCKET_INFO_PORT:Short = 27000
Const SOCKET_DATA_PORT:Short = 27001
If InfoSocket.Bind(SOCKET_INFO_PORT) Then
InfoSocket.SetTCPNoDelay(True)
Else
InfoSocket.Close()
Print "[ERR] Unable to bind Information Socket to port " + SOCKET_INFO_PORT + ". Make sure it is not in use."
End
EndIf
InfoSocket.Listen(128)
' Set up Data Socket.
If Not DataSocket.Bind(SOCKET_DATA_PORT) Then
DataSocket.Close()
Print "[ERR] Unable to bind Data Socket to port " + SOCKET_DATA_PORT + ". Make sure it is not in use."
End
EndIf
'END OF: Network Initiation
' Timers
Const DataTicks:Int = 5
Local l_LoopTimer:TTimer = TTimer.Create(120)
' Network Packet Buffer
Const NetPacketBufferSize:Int = 64
Local NetPacketBuffer:TBank = TBank.Create(NetPacketBufferSize)
Local NetPacketBufferStream:TBankStream = TBankStream.Create(NetPacketBuffer)
Local NetPacketQueueTCP:TList = (New TList)
Local NetPacketQueueTCPSwap:TList = (New TList)
Local NetPacketQueueUDP:TList = (New TList)
Local NetPacketQueueUDPSwap:TList = (New TList)
Repeat
Local l_LoopTime:Int = MilliSecs()
' Check for data on InfoSockets {
' Check for new connections. {
Local l_NewSocket:TSocket
Repeat
l_NewSocket = InfoSocket.Accept(0)
If l_NewSocket <> Null Then
Local l_NewPlayer:TPlayer = TPlayer.Create(l_NewSocket)
If l_NewPlayer <> Null Then
Print RSet(l_NewPlayer.m_UniqueId, 6) + ": Connected from " + DottedIP(l_NewSocket.RemoteIp()) + ":" + l_NewSocket.RemotePort() + "."
Else
l_NewSocket.Close()
Print "Server: New player tried connecting, but we are full."
EndIf
EndIf
Until l_NewSocket = Null
' }
' Check if a pregame client sent his login information {
For Local l_PGPlayer:TPlayer = EachIn TPlayer.PreGame
If l_PGPlayer.m_InfoSocket.Connected() = False Then
Print RSet(l_PGPlayer.m_UniqueId, 6) + ": Closed connection."
l_PGPlayer.Destroy();Continue
EndIf
While l_PGPlayer.m_InfoSocket.ReadAvail() > 0
Local l_ReadLength:Int = l_PGPlayer.m_InfoSocket.Recv(NetPacketBuffer._buf, 1);NetPacketBufferStream.Seek(0)
If l_ReadLength = 1
Local l_PacketId:Byte = NetPacketBufferStream.ReadByte()
Select l_PacketId
Case TInfoLogin.Id
l_PGPlayer.m_InfoSocket.Recv(NetPacketBuffer._buf, TInfoLogin.Size);NetPacketBufferStream.Seek(0)
Local l_InfoLogin:TInfoLogin = TInfoLogin(TInfoLogin.Read(NetPacketBufferStream))
If l_InfoLogin Then
' Retrieve Information from Packet
l_PGPlayer.m_Name = l_InfoLogin.m_Name
l_PGPlayer.m_Position[0] = l_InfoLogin.m_Position[0]
l_PGPlayer.m_Position[1] = l_InfoLogin.m_Position[1]
l_PGPlayer.m_Position[2] = l_InfoLogin.m_Position[2]
' Create UDP Socket for Client.
l_PGPlayer.m_DataSocket = TSocket.CreateUDP()
l_PGPlayer.m_DataSocket.Connect(l_PGPlayer.m_InfoSocket.RemoteIp(), l_InfoLogin.m_PunchPort)
' Send information to this client (order is important!).
Local l_InfoLogin:TInfoLogin = (New TInfoLogin)
l_InfoLogin.m_UniqueId = l_PGPlayer.m_UniqueId
l_InfoLogin.m_Name = l_PGPlayer.m_Name
'Local l_InfoUpdate:TInfoUpdate = (New TInfoUpdate)
'l_InfoUpdate.m_UniqueId = l_PGPlayer.m_UniqueId
'l_InfoUpdate.m_Name = l_PGPlayer.m_Name
'NetPacketBufferStream.Seek(0)
'Local l_Size:Int = l_InfoUpdate.Write(NetPacketBufferStream)
'l_PGPlayer.m_InfoSocket.Send(NetPacketBuffer._buf, l_Size)
' Add Player to ingame list.
TPlayer.PreGame.Remove(l_PGPlayer)
TPlayer.InGame.AddLast(l_PGPlayer)
Print RSet(l_PGPlayer.m_UniqueId, 6) + ": Logged in at " + l_PGPlayer.m_Position[0] + ":" + l_PGPlayer.m_Position[1] + ":" + l_PGPlayer.m_Position[2] + "."
Else
Print RSet(l_PGPlayer.m_UniqueId, 6) + ": CheckSum did not match with ours, Client is probably outdated."
l_PGPlayer.Destroy();Exit
EndIf
EndSelect
Else
Print RSet(l_PGPlayer.m_UniqueId, 6) + ": Unable to read first byte, socket might be corrupted. Dropping client."
l_PGPlayer.Destroy();Exit
EndIf
Wend
' If we still have no login packet, check if they are supposed to be dropped by timeout.
If l_PGPlayer.m_InfoSocket And (l_LoopTime - l_PGPlayer.m_Time) > 5000 Then
Print RSet(l_PGPlayer.m_UniqueId, 6) + ": Did not login, dropped."
l_PGPlayer.Destroy();Continue
EndIf
Next
' }
' Check if an ingame client sent packets. {
While DataSocket.ReadAvail() > 0
Local l_ReadLength:Int = DataSocket.Recv(NetPacketBuffer._buf, 1);NetPacketBufferStream.Seek(0)
If l_ReadLength = 1
Local l_PacketId:Byte = NetPacketBufferStream.ReadByte()
Select l_PacketId
Case TDataUpdate.Id
l_ReadLength = DataSocket.Recv(NetPacketBuffer._buf, NetPacketBufferSize)
Local l_DataUpdate:TDataUpdate = TDataUpdate(TDataUpdate.Read(NetPacketBufferStream))
Local l_Player:TPlayer = TPlayer.UIDToPlayer[l_DataUpdate.m_UniqueId]
If l_Player And l_Player.m_DataSocket Then ' Player exists and is logged in.
If DataSocket.RemoteIp() = l_Player.m_DataSocket.RemoteIp() And DataSocket.RemotePort() = l_Player.m_DataSocket.RemotePort() Then ' It is the same player.
If l_DataUpdate.m_Changed & TPlayer.CHANGED_POSX <> 0 Then l_Player.m_Position[0] = l_DataUpdate.m_Position[0]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_POSY <> 0 Then l_Player.m_Position[1] = l_DataUpdate.m_Position[1]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_POSZ <> 0 Then l_Player.m_Position[2] = l_DataUpdate.m_Position[2]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_ROTX <> 0 Then l_Player.m_Rotation[0] = l_DataUpdate.m_Rotation[0]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_ROTY <> 0 Then l_Player.m_Rotation[1] = l_DataUpdate.m_Rotation[1]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_ROTZ <> 0 Then l_Player.m_Rotation[2] = l_DataUpdate.m_Rotation[1]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_VEL <> 0 Then
l_Player.m_Velocity[0] = l_DataUpdate.m_Velocity[0]
l_Player.m_Velocity[1] = l_DataUpdate.m_Velocity[1]
l_Player.m_Velocity[2] = l_DataUpdate.m_Velocity[2]
EndIf
Else
Print "Server: Recieved update for another player from " + DottedIP(DataSocket.RemoteIp()) + ":" + DataSocket.RemotePort() + "."
EndIf
EndIf
EndSelect
EndIf
Wend
' }
' Check if an ingame client sent packets or packets need sending. {
For Local l_IGPlayer:TPlayer = EachIn TPlayer.InGame
Local l_Skip:Byte = False
If l_IGPlayer = Null Then Print "Fatal Error: Ran into ingame client, which apparently doesn't exist. Skipping."; Continue
' Check if the Player still has his TCP Socket open, otherwise drop him.
If l_IGPlayer.m_InfoSocket.Connected() = False Then
Print RSet(l_IGPlayer.m_UniqueId, 6) + ": Closed connection."
' Create InfoLogout packet.
Local l_InfoLogout:TInfoLogout = New TInfoLogout
l_InfoLogout.m_UniqueId = l_IGPlayer.m_UniqueId
' Remove the player from nearby other players.
NetPacketBufferStream.Seek(0)
Local l_Size:Int = l_InfoLogout.Write(NetPacketBufferStream)
For Local l_IGPlayerKnown:TPlayer = EachIn l_IGPlayer.__KnownPlayers:TList
l_IGPlayerKnown.m_InfoSocket.Send(NetPacketBuffer._buf, l_Size)
l_IGPlayerKnown.__KnownPlayers.Remove(l_IGPlayer)
Next
l_IGPlayer.Destroy();Continue
EndIf
' TCP: Do we have any incoming data from this player?
While l_IGPlayer.m_InfoSocket.ReadAvail() > 0
Local l_ReadLength:Int = l_IGPlayer.m_InfoSocket.Recv(NetPacketBuffer._buf, 1);NetPacketBufferStream.Seek(0)
If l_ReadLength = 1
Local l_PacketId:Byte = NetPacketBufferStream.ReadByte()
NetPacketBufferStream.Seek(0)
Select l_PacketId
Case TInfoLogin.Id
l_IGPlayer.m_InfoSocket.Recv(NetPacketBuffer._buf, TInfoLogin.Size)
Case TInfoLogout.Id
l_IGPlayer.m_InfoSocket.Recv(NetPacketBuffer._buf, TInfoLogout.Size)
Local l_InfoLogout:TInfoLogout = TInfoLogout(TInfoLogout.Read(NetPacketBufferStream))
l_InfoLogout.m_UniqueId = l_IGPlayer.m_UniqueId
' Send information to other clients.
NetPacketQueueTCPSwap.AddLast(l_InfoLogout)
Print RSet(l_IGPlayer.m_UniqueId, 6) + ": Logged out."
l_IGPlayer.Destroy();l_Skip = True;Exit
EndSelect
EndIf
Wend
If l_Skip = True Then Continue
' TCP: Do we have any data for this player? If so then send it out.
If NetPacketQueueTCP.Count() > 0 Then
For Local l_Packet:TNetPacket = EachIn NetPacketQueueTCP
NetPacketBufferStream.Seek(0)
l_IGPlayer.m_InfoSocket.Send(NetPacketBuffer._buf, l_Packet.Write(NetPacketBufferStream))
Next
EndIf
' UDP: If a DataUpdate is needed, send it.
If l_IGPlayer.m_TicksOnline Mod DataTicks Then
For Local l_IGPlayer2:TPlayer = EachIn TPlayer.InGame
If l_IGPlayer2 = l_IGPlayer Then Continue
If l_IGPlayer.IsInRange(l_IGPlayer2) Then ' Is this player even in range? If yes, continue
If Not l_IGPlayer.IsKnown(l_IGPlayer2) Then ' This client is new to him, need to introduce him first.
Local l_InfoLogin:TInfoLogin = (New TInfoLogin)
l_InfoLogin.m_UniqueId = l_IGPlayer2.m_UniqueId
l_InfoLogin.m_Name = l_IGPlayer2.m_Name
l_InfoLogin.m_Position[0] = l_IGPlayer2.m_Position[0]
l_InfoLogin.m_Position[1] = l_IGPlayer2.m_Position[1]
l_InfoLogin.m_Position[2] = l_IGPlayer2.m_Position[2]
l_InfoLogin.m_Rotation[0] = l_IGPlayer2.m_Rotation[0]
l_InfoLogin.m_Rotation[1] = l_IGPlayer2.m_Rotation[1]
l_InfoLogin.m_Rotation[2] = l_IGPlayer2.m_Rotation[2]
NetPacketBufferStream.Seek(0)
l_IGPlayer.m_InfoSocket.Send(NetPacketBuffer._buf, l_InfoLogin.Write(NetPacketBufferStream))
EndIf
Local l_DataUpdate:TDataUpdate = l_IGPlayer.GetDataUpdate(l_IGPlayer)
If l_DataUpdate Then
NetPacketBufferStream.Seek(0)
l_IGPlayer.m_DataSocket.Send(NetPacketBuffer._buf, l_DataUpdate.Write(NetPacketBufferStream))
EndIf
Else
If l_IGPlayer.IsKnownEx(l_IGPlayer2) Then ' This client is known to him, need to remove him.
Local l_InfoLogout:TInfoLogout = (New TInfoLogout)
l_InfoLogout.m_UniqueId = l_IGPlayer2.m_UniqueId
NetPacketBufferStream.Seek(0)
l_IGPlayer.m_InfoSocket.Send(NetPacketBuffer._buf, l_InfoLogout.Write(NetPacketBufferStream))
EndIf
EndIf
Next
EndIf
' UDP: Do we have any data for this player? If so then send it out.
If NetPacketQueueUDP.Count() > 0 Then
For Local l_Packet:TNetPacket = EachIn NetPacketQueueUDP
NetPacketBufferStream.Seek(0)
l_IGPlayer.m_DataSocket.Send(NetPacketBuffer._buf, l_Packet.Write(NetPacketBufferStream))
Next
EndIf
l_IGPlayer.m_TicksOnline :+ 1
Next
' }
' }
' Swap Network Packet Queue.
NetPacketQueueTCP.Swap(NetPacketQueueTCPSwap)
NetPacketQueueUDP.Swap(NetPacketQueueUDPSwap)
NetPacketQueueTCPSwap.Clear()
NetPacketQueueUDPSwap.Clear()
l_LoopTimer.Wait()
Until False
DataSocket.Close()
InfoSocket.Close()
End
'--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Type TPlayer
'! Array that tells us if an Id is in use. Toggle the bit you were using if an object is created or dies.
Global UniqueIds:Byte[] = (New Byte[8192])
Global UIDToPlayer:TPlayer[] = (New TPlayer[65536])
'! List of active players
Global PreGame:TList = (New TList)
Global InGame:TList = (New TList)
' Constants {
Const NAME_LENGTH:Int = 16
Const CHANGED_POSX:Byte = $00000001
Const CHANGED_POSY:Byte = $00000010
Const CHANGED_POSZ:Byte = $00000100
Const CHANGED_ROTX:Byte = $00001000
Const CHANGED_ROTY:Byte = $00010000
Const CHANGED_ROTZ:Byte = $00100000
Const CHANGED_VEL:Byte = $01000000
Const CHANGED_SHOOT:Byte = $10000000
' }
' Identification
Field m_UniqueId:Short
Field m_Name:Byte[]
' Ship Data
Field m_Changed:Byte
Field m_Position:Float[]
Field m_Rotation:Short[]
Field m_Velocity:Short[]
' Network Data
Field m_InfoSocket:TSocket
Field m_DataSocket:TSocket
Field m_Time:Int
Field m_TicksOnline:Int
' Initialize and Create new Players {
Method New()
' Some Network Data
m_Time = MilliSecs()
m_TicksOnline = 0
' Identification
m_Name = New Byte[TPlayer.NAME_Length]
m_UniqueID = 0
' Ship Data
m_Position = New Float[3]
m_Rotation = New Short[3]
m_Velocity = New Short[3]
TPlayer.PreGame.AddLast(Self)
EndMethod
Function Create:TPlayer(p_InfoSocket:TSocket)
' Make sure the Socket is still alive.
If p_InfoSocket <> Null And p_InfoSocket.Connected() Then
Local l_Player:TPlayer = (New TPlayer)
' Find a Unique ID that is not yet in use.
Local l_UniqueId:Int = 0
While l_UniqueId < 8192
Local l_SubUniqueId:Byte = 0
While l_SubUniqueId < 8
If (TPlayer.UniqueIds[l_UniqueId] & (1 shl l_SubUniqueId)) = 0 Then
' Mark UniqueId as used.
TPlayer.UniqueIds[l_UniqueId] :| (1 shl l_SubUniqueId)
l_Player.m_UniqueId = l_UniqueId * 8 + l_SubUniqueId
' Exit Loops.
l_UniqueId = 65535;l_SubUniqueId = 7
EndIf
l_SubUniqueId :+ 1
Wend
l_UniqueId :+ 1
Wend
If l_UniqueId = 65536 Then ' We have a Unique Id if we hit the unsigned limit for Short.
TPlayer.UIDToPlayer[l_Player.m_UniqueId] = l_Player
l_Player.m_InfoSocket = p_InfoSocket
Return l_Player
EndIf
EndIf
EndFunction
' }
' Deinitalize and Destroy old Players {
Method Destroy()
' Mark UniqueId as unused.
TPlayer.UniqueIds[Int(m_UniqueId / 8)] :& ~(1 Shl (m_UniqueId Mod 8))
TPlayer.UIDToPlayer[m_UniqueId] = Null
' Try and remove from both Player lists.
TPlayer.PreGame.Remove(Self)
TPlayer.InGame.Remove(Self)
' Close remaining Sockets.
If m_InfoSocket Then m_InfoSocket.Close()
If m_DataSocket Then m_DataSocket.Close()
' Destroy Data
m_Name = Null
m_Position = Null
m_Rotation = Null
m_Velocity = Null
m_InfoSocket = Null
m_DataSocket = Null
EndMethod
' }
' Update {
Method Update(p_Multiplier:Float)
Local m_OPositionX:Float = m_Position[0]
Local m_OPositionY:Float = m_Position[1]
Local m_OPositionZ:Float = m_Position[2]
m_Position[0] :+ m_Velocity[0] * p_Multiplier
m_Position[1] :+ m_Velocity[1] * p_Multiplier
m_Position[2] :+ m_Velocity[2] * p_Multiplier
If m_Position[0] <> m_OPositionX Then m_Changed :| TPlayer.CHANGED_POSX
If m_Position[1] <> m_OPositionY Then m_Changed :| TPlayer.CHANGED_POSY
If m_Position[2] <> m_OPositionZ Then m_Changed :| TPlayer.CHANGED_POSZ
EndMethod
' }
' Packets {
Const Range:Int = 3000
Method IsInRange:Byte(p_Player:TPlayer)
Local l_Distance:Float = Abs(p_Player.m_Position[0] - m_Position[0]) + Abs(p_Player.m_Position[1] - m_Position[1]) + Abs(p_Player.m_Position[2] - m_Position[2])
If l_Distance < TPlayer.Range Then Return True
Return False
EndMethod
Field __KnownPlayers:TList = New TList
Method IsKnown:Byte(p_Player:TPlayer)
If Not __KnownPlayers.Contains(p_Player) Then
__KnownPlayers.AddLast(p_Player)
Return False
EndIf
Return True
EndMethod
Method IsKnownEx:Byte(p_Player:TPlayer)
If __KnownPlayers.Contains(p_Player) Then
__KnownPlayers.Remove(p_Player)
Return True
EndIf
Return False
EndMethod
Method GetDataUpdate:TDataUpdate(p_Player:TPlayer)
Local l_Distance:Float = Abs(p_Player.m_Position[0] - m_Position[0]) + Abs(p_Player.m_Position[1] - m_Position[1]) + Abs(p_Player.m_Position[2] - m_Position[2])
If l_Distance < TPlayer.Range And m_Changed Then
Local l_DataUpdate:TDataUpdate = New TDataUpdate
Local l_Changed:Byte = $00000000
l_Changed = m_Changed & (TPlayer.CHANGED_POSX | TPlayer.CHANGED_POSY | TPlayer.CHANGED_POSZ)
If l_Distance < 2000 Then l_Changed = m_Changed & (TPlayer.CHANGED_ROTX | TPlayer.CHANGED_ROTY | TPlayer.CHANGED_ROTZ)
If l_Distance < 1000 Then l_Changed = m_Changed & TPlayer.CHANGED_VEL
l_DataUpdate.m_UniqueId = m_UniqueId
l_DataUpdate.m_Changed = m_Changed
l_DataUpdate.m_Position[0] = m_Position[0]
l_DataUpdate.m_Position[1] = m_Position[1]
l_DataUpdate.m_Position[2] = m_Position[2]
l_DataUpdate.m_Rotation[0] = m_Rotation[0]
l_DataUpdate.m_Rotation[1] = m_Rotation[1]
l_DataUpdate.m_Rotation[2] = m_Rotation[2]
l_DataUpdate.m_Velocity[0] = m_Velocity[0]
l_DataUpdate.m_Velocity[1] = m_Velocity[1]
l_DataUpdate.m_Velocity[2] = m_Velocity[2]
Return l_DataUpdate
EndIf
Return Null
EndMethod
' }
EndType
' Basic Network Packet
Type TNetPacket
Field m_UniqueId:Short
Function Read:TNetPacket(p_Stream:TStream)
EndFunction
Method Write(p_Stream:TStream)
EndMethod
EndType
Type TInfoLogin Extends TNetPacket
Const Id:Byte = 0
Const Size:Int = 34
Global Version:Short = Net_VersionMajor Shl 8 + Net_VersionMinor
Field m_Name:Byte[] = New Byte[TPlayer.NAME_LENGTH]
Field m_Position:Float[] = New Float[3]
Field m_Rotation:Float[] = New Float[3]
Field m_PunchPort:Short
Function Read:TNetPacket(p_Stream:TStream)
Local l_UPDPort:Short = p_Stream.ReadShort()
Local l_Version:Short = p_Stream.ReadShort()
If l_Version = TInfoLogin.Version Then
Local l_Packet:TInfoLogin = New TInfoLogin
p_Stream.ReadBytes(l_Packet.m_Name, TPlayer.NAME_LENGTH)
l_Packet.m_Position[0] = p_Stream.ReadFloat()
l_Packet.m_Position[1] = p_Stream.ReadFloat()
l_Packet.m_Position[2] = p_Stream.ReadFloat()
l_Packet.m_Rotation[0] = p_Stream.ReadFloat()
l_Packet.m_Rotation[1] = p_Stream.ReadFloat()
l_Packet.m_Rotation[2] = p_Stream.ReadFloat()
l_Packet.m_PunchPort = l_UDPPort
Return l_Packet
EndIf
EndFunction
Method Write:Int(p_Stream:TStream)
Local l_Pos:Int = p_Stream.Pos()
p_Stream.WriteByte(TInfoLogin.Id)
p_Stream.WriteShort(m_UniqueId)
p_Stream.WriteShort(TInfoLogin.Version)
p_Stream.WriteBytes(m_Name, TPlayer.NAME_LENGTH)
p_Stream.WriteFloat(m_Position[0])
p_Stream.WriteFloat(m_Position[1])
p_Stream.WriteFloat(m_Position[2])
p_Stream.WriteFloat(m_Rotation[0])
p_Stream.WriteFloat(m_Rotation[1])
p_Stream.WriteFloat(m_Rotation[2])
Return p_Stream.Pos() - l_Pos
EndMethod
EndType
Type TInfoLogout Extends TNetPacket
Const Id:Byte = 1
Const Size:Int = 2
Function Read:TNetPacket(p_Stream:TStream)
Local l_Packet:TInfoLogout = New TInfoLogout
Return l_Packet
EndFunction
Method Write:Int(p_Stream:TStream)
Local l_Pos:Int = p_Stream.Pos()
p_Stream.WriteByte(TInfoLogout.Id)
p_Stream.WriteShort(m_UniqueId)
Return p_Stream.Pos() - l_Pos
EndMethod
EndType
Type TInfoUpdate Extends TNetPacket
Const Id:Byte = 2
Const Size:Int = 18
Field m_Name:Byte[] = New Byte[TPlayer.NAME_LENGTH]
Function Read:TNetPacket(p_Stream:TStream)
Local l_Packet:TInfoUpdate = New TInfoUpdate
l_Packet.m_UniqueId = p_Stream.ReadShort() ~ p_Stream.ReadShort()
p_Stream.ReadBytes(l_Packet.m_Name, TPlayer.NAME_LENGTH)
Return l_Packet
EndFunction
Method Write:Int(p_Stream:TStream)
Local l_Pos:Int = p_Stream.Pos()
p_Stream.WriteByte(TInfoUpdate.Id)
p_Stream.WriteShort(m_UniqueId)
p_Stream.WriteBytes(m_Name, TPlayer.NAME_LENGTH)
Return p_Stream.Pos() - l_Pos
EndMethod
EndType
Type TDataUpdate Extends TNetPacket
Const Id:Byte = 3
Const Size:Int = 3
Field m_Changed:Byte
Field m_Position:Float[] = New Float[3]
Field m_Rotation:Float[] = New Float[3]
Field m_Velocity:Float[] = New Float[3]
Function Read:TNetPacket(p_Stream:TStream)
Local l_Packet:TDataUpdate = New TDataUpdate
l_Packet.m_UniqueId = p_Stream.ReadShort()
l_Packet.m_Changed = p_Stream.ReadByte()
If l_Packet.m_Changed & TPlayer.CHANGED_POSX <> 0 Then l_Packet.m_Position[0] = p_Stream.ReadFloat()
If l_Packet.m_Changed & TPlayer.CHANGED_POSY <> 0 Then l_Packet.m_Position[1] = p_Stream.ReadFloat()
If l_Packet.m_Changed & TPlayer.CHANGED_POSZ <> 0 Then l_Packet.m_Position[2] = p_Stream.ReadFloat()
If l_Packet.m_Changed & TPlayer.CHANGED_ROTX <> 0 Then l_Packet.m_Rotation[0] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 180.0
If l_Packet.m_Changed & TPlayer.CHANGED_ROTY <> 0 Then l_Packet.m_Rotation[1] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 180.0
If l_Packet.m_Changed & TPlayer.CHANGED_ROTZ <> 0 Then l_Packet.m_Rotation[2] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 180.0
If l_Packet.m_Changed & TPlayer.CHANGED_VEL <> 0 Then
l_Packet.m_Velocity[0] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 128.0
l_Packet.m_Velocity[1] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 128.0
l_Packet.m_Velocity[2] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 128.0
EndIf
Return l_Packet
EndFunction
Method Write:Int(p_Stream:TStream)
Local l_Pos:Int = p_Stream.Pos()
p_Stream.WriteByte(TDataUpdate.Id)
p_Stream.WriteShort(m_UniqueId)
p_Stream.WriteByte(m_Changed)
If m_Changed & TPlayer.CHANGED_POSX <> 0 Then p_Stream.WriteFloat(m_Position[0])
If m_Changed & TPlayer.CHANGED_POSY <> 0 Then p_Stream.WriteFloat(m_Position[1])
If m_Changed & TPlayer.CHANGED_POSZ <> 0 Then p_Stream.WriteFloat(m_Position[2])
If m_Changed & TPlayer.CHANGED_ROTX <> 0 Then p_Stream.WriteShort(Min(Max(m_Rotation[0] / 180.0, -1), 1) * 32767)
If m_Changed & TPlayer.CHANGED_ROTY <> 0 Then p_Stream.WriteShort(Min(Max(m_Rotation[1] / 180.0, -1), 1) * 32767)
If m_Changed & TPlayer.CHANGED_ROTZ <> 0 Then p_Stream.WriteShort(Min(Max(m_Rotation[2] / 180.0, -1), 1) * 32767)
If m_Changed & TPlayer.CHANGED_VEL <> 0 Then
p_Stream.WriteShort(Min(Max(m_Velocity[0] / 128.0, -1.0), 1.0) * 32767)
p_Stream.WriteShort(Min(Max(m_Velocity[1] / 128.0, -1.0), 1.0) * 32767)
p_Stream.WriteShort(Min(Max(m_Velocity[2] / 128.0, -1.0), 1.0) * 32767)
EndIf
Return p_Stream.Pos() - l_Pos
EndMethod
EndType
'--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
EndRem
+9
View File
@@ -0,0 +1,9 @@
xaymar.config
=======================
An easy way to load configurations from so called 'DataPaks'. DataPaks were inspired by Minecraft's NBT format and were able to store any arbitrary data. It's still more efficient to have a dedicated format instead of DataPaks, but it helps with compatability across versions. As far as I remember, this is thread-safe.
Documentation at: http://www.blitzforum.de/forum/viewtopic.php?p=388595#388595
License
=======
xaymar.config by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+366
View File
@@ -0,0 +1,366 @@
SuperStrict
Import xaymar.datapak
Module xaymar.config
ModuleInfo "License: Public Domain"
ModuleInfo "Original Author: Michael Dirks <support@levelnull.de>"
ModuleInfo "Purpose: Easily read and write configuration files by using xaymar.datapak."
Type TConfig
Field __MainDP:TDataPak
Field __CurrentDP:TDataPak
Method CreateConfig(name:String="Master")
__CurrentDP = Null
If __MainDP <> Null
__MainDP.Destroy()
__MainDP = Null
End If
__MainDP = TDataPak.Create(name)
End Method
Method OpenConfig(url:String,pwd:String="")
__CurrentDP = Null
If __MainDP <> Null
__MainDP.Destroy()
__MainDP = Null
End If
__MainDP = TDataPak.FromFile(url,pwd)
End Method
Method SaveConfig(url:String,pwd:String="")
__MainDP.ToFile(url, TDP_FLAG_COMPRESSED | TDP_FLAG_PASSWORDED, pwd)
End Method
Method CloseConfig()
__CurrentDP = Null
__MainDP.Destroy()
__MainDP = Null
End Method
Method IsConfigOpen:Int()
Return (__MainDP <> Null)
End Method
Method CreateGroup(name:String)
If __MainDP <> Null
Local TVarDP:TDataPakType[] = Null
If __MainDP.GetDataByName(name) <> Null Then
TVarDP = __MainDP.GetDataByName(name)
End If
If TVarDP <> Null And TVarDP[0].GetType() = TDP_CONTAINER
__CurrentDP = TDataPak(TVarDP[0])
Else
__CurrentDP = __MainDP.AddDataContainer(name)
End If
Else
Throw TConfigException.Create("No Config open.")
End If
End Method
Method OpenGroup(name:String)
If __MainDP <> Null
Local TVarDP:TDataPakType[] = Null
If __MainDP.GetDataByName(name) <> Null Then
TVarDP = __MainDP.GetDataByName(name)
End If
If TVarDP <> Null And TVarDP[0].GetType() = TDP_CONTAINER
__CurrentDP = TDataPak(TVarDP[0])
Else
Throw TConfigException.Create("Group '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Config open.")
End If
End Method
Method CloseGroup()
__CurrentDP = Null
End Method
Method IsGroupOpen:Int()
Return (__CurrentDP <> Null)
End Method
Method GetGroupByte:Byte(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_BYTE
Return TDataPakByte(TVarDP).GetData()
Else
Throw TConfigException.Create("Byte '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupShort:Short(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_SHORT
Return TDataPakShort(TVarDP).GetData()
Else
Throw TConfigException.Create("Short '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupInt:Int(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_INT
Return TDataPakInt(TVarDP).GetData()
Else
Throw TConfigException.Create("Int '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupLong:Long(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_LONG
Return TDataPakLong(TVarDP).GetData()
Else
Throw TConfigException.Create("Long '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupFloat:Float(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_FLOAT
Return TDataPakFloat(TVarDP).GetData()
Else
Throw TConfigException.Create("Float '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupDouble:Double(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_DOUBLE
Return TDataPakDouble(TVarDP).GetData()
Else
Throw TConfigException.Create("Double '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupString:String(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_STRING
Return TDataPakString(TVarDP).GetData()
Else
Throw TConfigException.Create("String '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupByteEx:Byte(name:String, def:Byte)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_BYTE
Return TDataPakByte(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupShortEx:Short(name:String, def:Short)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_SHORT
Return TDataPakShort(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupIntEx:Int(name:String, def:Int)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_INT
Return TDataPakInt(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupLongEx:Long(name:String, def:Long)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_LONG
Return TDataPakLong(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupFloatEx:Float(name:String, def:Float)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_FLOAT
Return TDataPakFloat(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupDoubleEx:Double(name:String, def:Double)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_DOUBLE
Return TDataPakDouble(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupStringEx:String(name:String, def:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_STRING
Return TDataPakString(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupByte(name:String,data:Byte)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_BYTE
TDataPakByte(TVarDP).SetData(data)
Else
__CurrentDP.AddDataByte(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupShort(name:String,data:Short)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_SHORT
TDataPakShort(TVarDP).SetData(data)
Else
__CurrentDP.AddDataShort(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupInt(name:String,data:Int)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_INT
TDataPakInt(TVarDP).SetData(data)
Else
__CurrentDP.AddDataInt(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupLong(name:String,data:Long)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_LONG
TDataPakLong(TVarDP).SetData(data)
Else
__CurrentDP.AddDataLong(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupFloat(name:String,data:Float)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_FLOAT
TDataPakFloat(TVarDP).SetData(data)
Else
__CurrentDP.AddDataFloat(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupDouble(name:String,data:Double)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_DOUBLE
TDataPakDouble(TVarDP).SetData(data)
Else
__CurrentDP.AddDataDouble(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupString(name:String,data:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_STRING
TDataPakString(TVarDP).SetData(data)
Else
__CurrentDP.AddDataString(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
End Type
Type TConfigException
Field Error:String
Method ToString:String()
Return Error
End Method
Function Create:TConfigException(Error:String)
Local TCE:TConfigException = New TConfigException
TCE.Error = Error
Return TCE
End Function
End Type
+11
View File
@@ -0,0 +1,11 @@
xaymar.datapak
=======================
A newer iteration of DataCollector, named DataPaks. It was inspired by Minecraft's NBT format and as such has similar features. It supports many types, as well as arrays of such types (in case you don't want to name each entry, useful for inventories). Saved and loaded archives can be passworded and compressed, it is up to you to use that feature. The project includes two examples, which just show how to use the module.
First iteration at: http://www.blitzforum.de/forum/viewtopic.php?t=36694
Documentation at: http://www.blitzforum.de/forum/viewtopic.php?p=388429#388429
License
=======
xaymar.datapak by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
File diff suppressed because it is too large Load Diff
+35
View File
@@ -0,0 +1,35 @@
Framework brl.retro
Import xaymar.datapak
'Advanced: Create a new Container
Local DPCnt:TDataPak = New TDataPak
DPCnt.SetName("MyContainer")
'Advanced: Add A new String (or any other Type: Byte, Short, Int, Long, Float, Double, Container)
Local DPStr:TDataPakString = New TDataPakString
DPStr.SetName("MyString")
DPStr.SetData("Hello :D")
DPCnt.AddData(DPStr)
'Easy: Add A new String (or any other Type: Byte, Short, Int, Long, Float, Double, Container)
DPCnt.AddDataString("MyString2", "Hallo :D")
'Easy: Safe to File
'Uncompressed & Unpassworded [sdp = Standard Data Pak]
DPCnt.ToFile("Test.sdp")
'Compressed & Unpassworded [cdp = Compressed Data Pak]
DPCnt.ToFile("Test.cdp", TDP_FLAG_COMPRESSED)
'Uncompressed & Passworded [pdp = Passworded Data Pak]
DPCnt.ToFile("Test.pdp", TDP_FLAG_PASSWORDED, "MyPassword")
'Compressed & Passworded [mdp = Merged Data Pak]
DPCnt.ToFile("Test.mdp", TDP_FLAG_PASSWORDED | TDP_FLAG_COMPRESSED, "MyPassword")
'Easy: Loading from File
'Uncompressed & Unpassworded [sdp = Standard Data Pak]
Local DPCntS:TDataPak = TDataPak.FromFile("Test.sdp")
'Compressed & Unpassworded [cdp = Compressed Data Pak]
Local DPCntC:TDataPak = TDataPak.FromFile("Test.cdp")
'Uncompressed & Passworded [pdp = Passworded Data Pak]
Local DPCntP:TDataPak = TDataPak.FromFile("Test.pdp", "MyPassword")
'Compressed & Passworded [mdp = Merged Data Pak]
Local DPCntM:TDataPak = TDataPak.FromFile("Test.mdp", "MyPassword")
+27
View File
@@ -0,0 +1,27 @@
Framework brl.retro
Import xaymar.datapak
'Testing consistency of DataPaks
Local DPCnt:TDataPak = New TDataPak
DPCnt.SetName("My Container")
DPCnt.AddDataByte("My Byte", 127)
DPCnt.AddDataShort("My Short", 256)
DPCnt.AddDataInt("My Int", 65536)
DPCnt.AddDataLong("My Long", 618317896391:Long)
DPCnt.AddDataFloat("My Float", 1.23456789)
DPCnt.AddDataDouble("My Double", 1.2345678912345:Double)
DPCnt.AddDataString("My String", "Totally not yours!")
Local DPSCnt:TDataPak = DPCnt.AddDataContainer("My SubContainer")
DPSCnt.AddDataByte("Sub Byte", 127)
DPSCnt.AddDataShort("Sub Short", 256)
DPSCnt.AddDataInt("Sub Int", 65536)
DPSCnt.AddDataLong("Sub Long", 618317896391:Long)
DPSCnt.AddDataFloat("Sub Float", 1.23456789)
DPSCnt.AddDataDouble("Sub Double", 1.2345678912345:Double)
DPSCnt.AddDataString("Sub String", "Totally not hub!")
DPCnt.ToFile("Consistency.sdp")
DPCnt.ToFile("Consistency.cdp", TDP_FLAG_COMPRESSED)
DPCnt.ToFile("Consistency.pdp", TDP_FLAG_PASSWORDED, "ThisIsATotallyUnsecurePasswordWithUnknownLengthToYouBecauseIDidn'tTellYouItsLength!")
DPCnt.ToFile("Consistency.mdp", TDP_FLAG_COMPRESSED | TDP_FLAG_PASSWORDED, "ThisIsATotallyUnsecurePasswordWithUnknownLengthToYouBecauseIDidn'tTellYouItsLength!")
+8
View File
@@ -0,0 +1,8 @@
xaymar.desktop
=======================
An attempt at rendering to the desktop. Failed, mind you. The module it references no longer exists, no idea what it even added.
License
=======
xaymar.desktop by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+104
View File
@@ -0,0 +1,104 @@
SuperStrict
Framework BRL.StandardIO
Import Xaymar.Desktop
Import Pub.DirectX
Import Pub.Win32
Import MaxGUI.Win32MaxGUIEx
Extern "win32"
Function GetLastError() = "GetLastError@0"
EndExtern
Global d3dx9Lib:Int = LoadLibraryA( "d3dx9" )
DebugLog GetLastError()
If d3dx9Lib Then
Global D3DXAssembleShader:Int(pSrcData:Byte Ptr, SrcDataLen:Int, pDefines:Byte Ptr, pInclude:Byte Ptr, FLAGS:Int, ppShader:ID3DXBuffer Var, ppErrorMsgs:ID3DXBuffer Var)"win32"=GetProcAddress( d3dx9Lib,"D3DXAssembleShader" )
Global D3DXSaveSurfaceToFile:Int(pConstString:Byte Ptr, DestFormat:Int, pSurface:Byte Ptr, pSrcPalette:Byte Ptr, pSrcRect:Byte Ptr)"win32"=GetProcAddress( d3dx9Lib, "D3DXSaveSurfaceToFile" )
EndIf
Local l_Displays:TList = GetDisplayList()
For Local l_Display:Rect = EachIn l_Displays
Print "[" + l_Display.Left + ", " + l_Display.Top + "]:[" + l_Display.Right + ", " + l_Display.Bottom + "]"
Next
Local l_Display:Rect = Rect(l_Displays.ValueAtIndex(0))
Local l_D3D:IDirect3D9 = Direct3DCreate9( 32 )
If Not l_D3D Then
Print "0x00000001"
Else
Local l_D3DCaps:D3DCAPS9 = New D3DCAPS9
If l_D3D.GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, l_D3DCaps) < 0
Print "0x00000002"
Else
Local l_D3DPresentParam:D3DPRESENT_PARAMETERS = New D3DPRESENT_PARAMETERS
l_D3DPresentParam.BackBufferWidth = (l_Display.Right - l_Display.Left)
l_D3DPresentParam.BackBufferHeight = (l_Display.Bottom - l_Display.Top)
l_D3DPresentParam.BackBufferCount = 1
l_D3DPresentParam.BackBufferFormat = D3DFMT_UNKNOWN
l_D3DPresentParam.MultiSampleType = D3DMULTISAMPLE_NONE
l_D3DPresentParam.SwapEffect = D3DSWAPEFFECT_DISCARD
l_D3DPresentParam.hDeviceWindow = Null
l_D3DPresentParam.Windowed = True
l_D3DPresentParam.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER | D3DPRESENTFLAG_VIDEO
l_D3DPresentParam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE
Local l_WindowName:String = "Null"
Local l_hWnd:Int = CreateWindowExW(0, TWindowsGUIDriver.ClassName(), l_WindowName, 0, 0, 0, 1, 1, Null, Null, Null, Null)
If l_hWnd = 0 Then
Print GetLastError()
Print "0x00000003"
Else
Local l_D3DDevice:IDirect3DDevice9 = Null
If l_D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, l_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, l_D3DPresentParam, l_D3DDevice) < 0
Print "0x00000004"
Else
Local l_DesktopRT:IDirect3DSurface9 = Null
Local l_RecordRT:IDirect3DSurface9 = Null
If l_D3DDevice.GetRenderTarget(0, l_DesktopRT) < 0
Print "0x00000005"
Else
Local l_D3DDisplayMode:D3DDISPLAYMODE = New D3DDISPLAYMODE
If l_D3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT, l_D3DDisplayMode) < 0
Print "0x00000006"
Else
If l_D3DDevice.CreateOffscreenPlainSurface(l_D3DDisplayMode.Width, l_D3DDisplayMode.Height, l_D3DDisplayMode.Format, D3DPOOL_SYSTEMMEM, l_RecordRT, Null) < 0
Print "0x00000007"
Else
If l_D3DDevice.GetRenderTargetData(l_DesktopRT, l_RecordRT) < 0
Print "0x00000008"
Else
Local File:String = "C:\Dokumente und Einstellungen\Teilnehmer\Desktop\" + MilliSecs() + ".png"
Local FileCStr:Byte Ptr = File.ToCString()
Print D3DXSaveSurfaceToFile(FileCStr, 3, Byte Ptr(l_RecordRT), Null, Null)
If D3DXSaveSurfaceToFile(FileCStr, 3, Byte Ptr(l_RecordRT), Null, Null) <> 0
Print "0x00000009"
Else
Print "Success?"
EndIf
MemFree FileCStr
EndIf
l_RecordRT.Release_
EndIf
l_D3DDisplayMode = Null
EndIf
l_DesktopRT.Release_
EndIf
EndIf
DestroyWindow l_hWnd
EndIf
EndIf
l_D3D.Release_
EndIf
Rem
//copy the render target to the destination surface.
hr = Device->GetRenderTargetData(pRenderTarget, pDestTarget);
//save its contents to a bitmap file.
hr = D3DXSaveSurfaceToFile(file,
D3DXIFF_BMP,
pDestTarget,
NULL,
NULL);
+11
View File
@@ -0,0 +1,11 @@
xaymar.resource
=======================
I created this back when multi-threading was highly praised for the features it could give you. This allows you to load anything asynchronous and still know how far the loading process is. Easily extendable as it was designed to work flawlessly with as many types as possible. Requires threading, otherwise it will just be synchronous.
Supports both basic BRL modules as well as xaymar.datapak, which allows you to load large files without the program hanging up for a while. Thank god for threading!
Documentation at: http://www.blitzforum.de/forum/viewtopic.php?p=390021#390021
License
=======
xaymar.resource by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+166
View File
@@ -0,0 +1,166 @@
'!BRL.Audio + AudioSample
Import brl.audio
Import brl.audiosample
Type TSoundResource Extends TResource
Field Flags:Int
Method SetSound(Name:String, File:String, Flags:Int=-1)
Self.Flags = Flags
Set(Name,File)
EndMethod
Method _Load()
Self.Resource = LoadSound(Self.File, Self.Flags)
EndMethod
End Type
Type TAudioSampleResource Extends TResource
Method _Load()
Self.Resource = LoadAudioSample(Self.File)
End Method
End Type
'!BRL.Bank + BRL.BankStream
Import brl.bank
Type TBankResource Extends TResource
Method _Load()
Self.Resource = LoadBank(Self.File)
End Method
Method _Save()
SaveBank(TBank(Self.Resource), Self.File)
End Method
End Type
'!BRL.Font
Import brl.font
Type TFontResource Extends TResource
Field Size:Int
Field Style:Int
Method SetFont(Name:String, File:String, Size:Int, Style:Int=SMOOTHFONT)
Self.Size = Size
Self.Style = Style
Set(Name,File)
EndMethod
Method _Load()
Self.Resource = LoadFont(Self.File, Self.Size, Self.Style)
End Method
End Type
'BRL.Max2D
Import brl.max2d
Type TImageResource Extends TResource
Field Flags:Int = -1
Field Animated:Int = False
Field CellWidth:Int = 0
Field CellHeight:Int = 0
Field FirstCell:Int = 0
Field CellCount:Int = 0
Method SetImage(Name:String, File:String, Flags:Int=-1)
Self.Flags = Flags
Self.Animated = False
Set(Name,File)
End Method
Method SetAnimImage(Name:String, File:String, CellWidth:Int, CellHeight:Int, FirstCell:Int, CellCount:Int, Flags:Int=-1)
Self.Flags = Flags
Self.Animated = True
Self.CellWidth = CellWidth
Self.CellHeight = CellHeight
Self.FirstCell = FirstCell
Self.CellCount = CellCount
Set(Name,File)
EndMethod
Method _Load()
If Self.Animated = False
Self.Resource = LoadImage(Self.File, Self.Flags)
Else
Self.Resource = LoadAnimImage(Self.File, Self.CellWidth, Self.CellHeight, Self.FirstCell, Self.CellCount, Self.Flags)
EndIf
EndMethod
End Type
'BRL.Pixmap
Import brl.pixmap
Import brl.bmploader
Import brl.jpgloader
Import brl.pngloader
Import brl.tgaloader
Type TPixmapResource Extends TResource
Field IsPNG:Int
Field Parameter:Int
Method SetPixmapJPG(Name:String, File:String, Quality:Int=75)
Self.IsPNG = False
Self.Parameter = Quality
Set(Name, File)
End Method
Method SetPixmapPNG(Name:String, File:String, Compression:Int=5)
Self.IsPNG = True
Self.Parameter = Compression
Set(Name, File)
End Method
Method _Load()
Self.Resource = LoadPixmap(Self.File)
End Method
Method _Save()
If IsPNG = True
SavePixmapPNG(TPixmap(Self.Resource), Self.File, Self.Parameter)
Else
SavePixmapJPeg(TPixmap(Self.Resource), Self.File, Self.Parameter)
EndIf
End Method
End Type
'BRL.Stream
Import brl.stream
Type TByteArrayResource Extends TResource
Method _Load()
Self.Resource = LoadByteArray(Self.File)
End Method
Method _Save()
SaveByteArray(Byte[](Self.Resource), Self.File)
End Method
End Type
Type TObjectResource Extends TResource
Method _Load()
Self.Resource = LoadObject(Self.File)
End Method
Method _Save()
SaveObject(Self.Resource, Self.File)
End Method
End Type
Type TStringResource Extends TResource
Method _Load()
Self.Resource = LoadString(Self.File)
End Method
Method _Save()
SaveString(String(Self.Resource), Self.File)
End Method
End Type
Type TStreamResource Extends TResource
Field Readable:Int = False
Field Writeable:Int = False
Method SetStream(Name:String, File:String, Readable:Int, Writeable:Int)
Readable = Readable
Writeable = Writeable
Set(Name, File)
End Method
Method _Load()
Self.Resource = OpenStream(Self.File, Self.Readable, Self.Writeable)
End Method
Method _Save()
FlushStream(TStream(Self.Resource))
End Method
End Type
'BRL.TextStream
Import brl.textstream
Type TTextResource Extends TResource
Method _Load()
Self.Resource = LoadText(Self.File)
End Method
End Type
@@ -0,0 +1,37 @@
'Xaymar.DataPak
Import xaymar.datapak
Type TDataPakResource Extends TResource
Field Password:String
Field Compressed:Int
Field Stream:TStream
Method SetDataPak(Name:String, URL:Object, Password:String="", Compressed:Int=False)
Self.Password = Password
Self.Compressed = Compressed
If TStream(URL) <> Null Then
Self.Stream = TStream(URL)
Set(Name, "")
ElseIf String(URL) <> Null Then
Self.Stream = Null
Set(Name, String(URL))
EndIf
End Method
Method _Load()
If Stream = Null
Self.Resource = TDataPak.FromFile(Self.File, Self.Password)
Else
Self.Resource = TDataPak.FromStream(Self.Stream)
End If
End Method
Method _Save()
Local _Flags:Byte
If Self.Password <> "" Then _Flags :+ TDP_FLAG_PASSWORDED
If Self.Compressed <> 0 Then _Flags :+ TDP_FLAG_COMPRESSED
If Stream = Null
TDataPak(Self.Resource).ToFile(Self.File, _Flags, Self.Password)
Else
TDataPak(Self.Resource).ToStream(Self.Stream)
End If
End Method
End Type
@@ -0,0 +1,106 @@
'Xaymar.Resource: Test 01
' Loading of Images and Sounds
SuperStrict
Import xaymar.resource
Import xaymar.brlaudio
Import xaymar.brlmax2d
Import brl.audio
Import brl.max2d
Graphics(800,600,0,60)
SetVirtualResolution(100,100)
Global MyResource:TResourceManager = New TResourceManager
Local imgDir:String[] = LoadDir("data/img/")
For Local fileImg:String = EachIn imgDir
Local _Res:TImageResource = New TImageResource
_Res.SetImage(fileImg, "data/img/"+fileImg)
MyResource.AddResource(_Res)
Next
Local sndDir:String[] = LoadDir("data/snd/")
For Local fileSnd:String = EachIn sndDir
Local _Res:TSoundResource = New TSoundResource
_Res.SetSound(fileSnd, "data/snd/"+fileSnd)
MyResource.AddResource(_Res)
Next
Local _ExitLoad:Int = False
Repeat
Cls
Local _BarPerc:Float = Float(MyResource.GetCount(TRM_LOADED)) / Float(MyResource.GetCount(TRM_ALL))
Local _BarPercLoad:Float = Float(MyResource.GetCount(TRM_LOADING)) / Float(MyResource.GetCount(TRM_ALL))
Local _BarPercError:Float = Float(MyResource.GetCount(TRM_ERROR)) / Float(MyResource.GetCount(TRM_ALL))
Local _BarColorMod:Float = 0.5+Sin( Float(MilliSecs()) / Float(1000/360) )*0.5
SetBlend ALPHABLEND
SetColor 102+153*_BarColorMod, 102+153*_BarColorMod, 102+153*_BarColorMod
DrawLine( 5, 90, 95, 90)
DrawLine( 5, 90, 5, 95)
DrawLine( 5, 95, 95, 95)
DrawLine(95, 90, 95, 95)
SetAlpha 0.9+0.1*_BarColorMod
SetColor 51, 255, 51
DrawRect( 6, 91, 89*_BarPerc, 4)
SetAlpha 0.8+0.2*_BarColorMod
SetColor 255, 255, 51
DrawRect( 6+89*_BarPerc, 91, 89*_BarPercLoad, 4)
SetAlpha 0.7+0.3*_BarColorMod
SetColor 255, 51, 51
DrawRect( 6+89*_BarPerc+89*_BarPercLoad, 91, 89*_BarPercError, 4)
SetColor 255,255,255
SetAlpha 1.0*_BarColorMod*_BarPerc
DrawRect( 5.5, 90.5, 90, 5)
SetAlpha 0.8
SetVirtualResolution(GraphicsWidth(),GraphicsHeight())
DrawText("Complete %:"+Int(_BarPerc*100),0,0)
DrawText("Loading %:"+Int(_BarPercLoad*100),0,15)
DrawText("Errored %:"+Int(_BarPercError*100),0,30)
If MyResource.GetResource(TRM_NONE) <> Null
DrawText(MyResource.GetResource(TRM_NONE).File,800*0.05,600*0.80)
Else
DrawText("Done, Press any key to continue...",800*0.05,600*0.80)
EndIf
SetVirtualResolution(100,100)
Flip
Local LRCode:Int = MyResource.LoadResource()
MyResource.Update() 'Update Count
If AppTerminate()
End
End If
If LRCode = TRM_LS_NORESOURCE
For Local I:Int = 0 To 255
If KeyDown(I) = True
_ExitLoad = True
End If
Next
End If
Until _ExitLoad = True
SetVirtualResolution(GraphicsWidth(),GraphicsHeight())
Print "Resource List:"
For Local _Res:TResource = EachIn MyResource.GetResources(TRM_ALL)
Select _Res._State
Case TRM_LOADED, TRM_SAVED
Print " SUCCESS: ["+_Res.Name+"]"+_Res.File
Case TRM_LOADING, TRM_SAVING
Print " STUCK: ["+_Res.Name+"]"+_Res.File
Case TRM_ERROR, TRM_NONE
Print " FAILED: ["+_Res.Name+"]"+_Res.File + " //"+_Res.Exception.ToString()
End Select
Next
End
+299
View File
@@ -0,0 +1,299 @@
SuperStrict
?Threaded
Import brl.threads
?
Import brl.linkedlist
Module xaymar.resource
ModuleInfo "License: Public Domain"
ModuleInfo "Original Author: Michael Dirks <support@levelnull.de>"
ModuleInfo "Purpose: Load your Files the better way! (Threading supported)"
Const TRM_SAVED:Int = -2
Const TRM_SAVING:Int = -1
Const TRM_NONE:Int = +0
Const TRM_LOADING:Int = +1
Const TRM_LOADED:Int = +2
Const TRM_ERROR:Int = $FF
Const TRM_ALL:Int = $FE
Const TRM_LS_ERROR:Int = 0
Const TRM_LS_SUCCESS:Int = 1
Const TRM_LS_NORESOURCE:Int = 2
Type TRLException
Method ToString:String()
Return "An Error appeared during Loading/Saving the Object."
End Method
End Type
Type TResourceManager
'Members
Field _ResList:TList = New TList
Field _ResourceLoaderFunc(Res:TResource)
Field _ResourceSaverFunc(Res:TResource)
'Members: Stats
Field _SavingRes:Int, _SavedRes:Int
Field _TotalRes:Int, _ErrorRes:Int
Field _LoadingRes:Int, _LoadedRes:Int
'Threaded Members
?Threaded Field _ResMutex:TMutex = CreateMutex()
?
'Methods
Method New();SetLoaderFunc(TResourceLoaderFunc);SetSaverFunc(TResourceSaverFunc);End Method
Method Remove()
?Threaded _ResMutex.Lock()
?
_ResList.Clear()
_ResList = Null
?Threaded _ResMutex.Unlock()
_ResMutex.Close()
_ResMutex = Null
?
End Method
Method SetLoaderFunc(LoaderFunc:Byte Ptr)
_ResourceLoaderFunc = LoaderFunc
End Method
Method SetSaverFunc(SaverFunc:Byte Ptr)
_ResourceSaverFunc = SaverFunc
End Method
Method Update()
?Threaded _ResMutex.Lock()
?
_TotalRes = _ResList.Count()
_LoadingRes = 0;_SavingRes = 0
_LoadedRes = 0;_SavedRes = 0
_ErrorRes = 0;
For Local _Res:TResource = EachIn _ResList
Select _Res._State
Case TRM_LOADING
_LoadingRes :+ 1
Case TRM_LOADED
_LoadedRes :+ 1
Case TRM_SAVING
_SavingRes :+ 1
Case TRM_SAVED
_SavedRes :+ 1
Case TRM_NONE
Default
_ErrorRes :+ 1
End Select
Next
?Threaded _ResMutex.Unlock()
?
End Method
Method GetCount:Int(Which:Int)
Select Which
Case TRM_NONE
Return _TotalRes-_LoadedRes-_LoadingRes-_SavedRes-_SavingRes-_ErrorRes
Case TRM_LOADING
Return _LoadingRes
Case TRM_LOADED
Return _LoadedRes
Case TRM_SAVING
Return _SavingRes
Case TRM_SAVED
Return _SavedRes
Case TRM_ERROR
Return _ErrorRes
Case TRM_ALL
Return _TotalRes
Default
Return 0
End Select
EndMethod
Method AddResource(Res:TResource)
?Threaded _ResMutex.Lock()
?
_ResList.AddLast(Res)
Res._State = TRM_NONE
?Threaded _ResMutex.Unlock()
?
End Method
Method RemoveResourceName(Name:String)
?Threaded _ResMutex.Lock()
?
For Local _Res:TResource = EachIn _ResList
If _Res.Name = Name Then
_ResList.Remove(_Res)
_Res = Null
End If
Next
?Threaded _ResMutex.Unlock()
?
End Method
Method RemoveResource(Res:TResource)
?Threaded _ResMutex.Lock()
?
_ResList.Remove(Res)
?Threaded _ResMutex.Unlock()
?
End Method
Method ClearResource(Which:Int=TRM_ALL)
?Threaded _ResMutex.Lock()
?
_ResList.Clear()
?Threaded _ResMutex.Unlock()
?
End Method
Method GetResourceName:TResource(Name:String, Which:Int=TRM_ALl)
Local _rRes:TResource
?Threaded _ResMutex.Lock()
?
For Local _Res:TResource = EachIn _ResList
If _Res.Name = Name And (_Res._State = Which Or Which = TRM_ALL)
_rRes = _Res
Exit
EndIf
Next
?Threaded _ResMutex.Unlock()
?
Return _rRes
End Method
Method GetResourcesName:TResource[](Name:String, Which:Int=TRM_ALL)
Local _rList:TList = New TList
?Threaded _ResMutex.Lock()
?
For Local _Res:TResource = EachIn _ResList
If _Res.Name = Name And (_Res._State = Which Or Which = TRM_ALL)
_rList.AddLast(_Res)
EndIf
Next
?Threaded _ResMutex.Unlock()
?
Return TResource[](_rList.ToArray())
End Method
Method GetResource:TResource(Which:Int=TRM_ALl)
Local _rRes:TResource
?Threaded _ResMutex.Lock()
?
For Local _Res:TResource = EachIn _ResList
If (_Res._State = Which Or Which = TRM_ALL)
_rRes = _Res
Exit
EndIf
Next
?Threaded _ResMutex.Unlock()
?
Return _rRes
End Method
Method GetResources:TResource[](Which:Int=TRM_ALL)
Local _rList:TList = New TList
?Threaded _ResMutex.Lock()
?
For Local _Res:TResource = EachIn _ResList
If (_Res._State = Which Or Which = TRM_ALL)
_rList.AddLast(_Res)
EndIf
Next
?Threaded _ResMutex.Unlock()
?
Return TResource[](_rList.ToArray())
End Method
Method LoadResource:Int(Which:Int=TRM_NONE)
Local _Res:TResource = GetResource(Which), _rVal:Int
If _Res = Null
Return TRM_LS_NORESOURCE
Else
?Threaded _ResMutex.Lock()
?
_Res._State = TRM_LOADING
?Threaded _ResMutex.Unlock()
?
_ResourceLoaderFunc(_Res)
?Threaded _ResMutex.Lock()
?
If _Res.Exception = Null And _Res.Resource <> Null
_Res._State = TRM_LOADED
_rVal = TRM_LS_SUCCESS
Else
If _Res.Exception = Null
_Res.Exception = New TRLException
End If
_Res._State = TRM_ERROR
_rVal = TRM_LS_ERROR
End If
?Threaded _ResMutex.Unlock()
?
Return _rVal
End If
End Method
Method SaveResource:Int(Which:Int=TRM_NONE)
Local _Res:TResource = GetResource(Which), _rVal:Int
If _Res = Null
Return TRM_LS_NORESOURCE
Else
?Threaded _ResMutex.Lock()
?
_Res._State = TRM_SAVING
?Threaded _ResMutex.Unlock()
?
_ResourceSaverFunc(_Res)
?Threaded _ResMutex.Lock()
?
If _Res.Exception = Null
_Res._State = TRM_SAVED
_rVal = TRM_LS_SUCCESS
Else
_Res._State = TRM_ERROR
_rVal = TRM_LS_ERROR
End If
?Threaded _ResMutex.Unlock()
?
Return _rVal
End If
End Method
End Type
Type TResource
Field _State:Int
Field Name:String, File:String
Field Resource:Object, Exception:Object
Method New();EndMethod
Method Set(Name:String, File:String)
Self.Name = Name
Self.File = File
Self.Resource = Null
Self.Exception = Null
End Method
Method Remove()
Self.Resource = Null
Self.Exception = Null
Self.File = Null
Self.Name = Null
End Method
Method _Load();End Method
Method _Save();End Method
End Type
Function TResourceLoaderFunc(Res:TResource)
Try
Res._Load()
Catch E:Object
Res.Exception = E
Res.Resource = Null
EndTry
End Function
Function TResourceSaverFunc(Res:TResource)
Try
Res._Save()
Catch E:Object
Res.Exception = E
Res.Resource = Null
EndTry
End Function
Binary file not shown.

After

Width:  |  Height:  |  Size: 938 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Some files were not shown because too many files have changed in this diff Show More