Hi leute.
Ich hab mich mal die letzten tage drangeklemmt eine Konsole zu schreiben. Bisher fehlt noch die komplette dokumentation, sowie autocomplete.
Hier erstmal der Code:
TConsole.bmx:
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN]
Include "TColorContainer.bmx" Include "TText.bmx"
Global gConsole:TRainbowConsole = New TRainbowConsole
Function Help:Byte(args:String[]) If (args.length<1) gConsole.Output("$3**********************Help**********************") gConsole.Output("$3For more info about an object or function type:") gConsole.Output("$5 help command") gConsole._objHandler.PrintObjects() gConsole._functionHandler.PrintFunctions() Else Local desc:String desc = gConsole._objHandler.GetDescription(args[0]) If (desc<>"") gConsole.Output("$3 "+args[0]+" - "+desc) Return EndIf desc = gConsole._functionHandler.GetDescription(args[0]) If (desc<>"") gConsole.Output("$3 "+args[0]+" - "+desc) Return EndIf gConsole.Output("$2Object or Function $5"+args[0]+"$2 has either no description or is not vaild!") EndIf End Function gConsole.RegisterFunction("help", Help, "Shows infos about commands")
Private
Const RAINBOW_CONSOLE_COMMAND_BUFFER_SIZE:Int = 100 Const RAINBOW_CONSOLE_LINE_BUFFER_SIZE:Int = 100 Const RAINBOW_CONSOLE_POPUP_SPEED:Int = 10 Const RAINBOW_CONSOLE_VERSION:String = "Rainbow-Console v 0.1 beta"
Type TConsoleObjectHandler Field _Objects:TMap Field _Descriptions:TMap Field _Parent:TRainbowConsole Method New() _objects = New TMap _Descriptions:TMap = New TMap End Method Method Init() If (_Parent=Null) Then Return; _Parent.RegisterObject("ObjectHandler",Self) _Parent.RegisterMethod("ObjectHandler","DumpObject") _Parent.RegisterMethod("ObjectHandler","DumpCVar") _Parent.RegisterMethod("ObjectHandler","SetField") _Parent.RegisterMethod("ObjectHandler","GetField") End Method Method Exists:Byte(name:String) Return MapContains(_objects, name) End Method Method Register:Byte(name:String, obj:Object, desc:String = "") If (MapContains(_Objects, name) Or _Parent.GetFunctionHandler().Exists(name)) Then _Parent.Output("$2[ERROR] Double double use of name $5"+name) Return False Else MapInsert(_Descriptions, name, desc) MapInsert(_Objects, name, obj) Return True EndIf End Method Method RegisterCVar:Byte(name:String, value:Object = Null, desc:String = "") Return Self.Register(name, String(value), desc) End Method Method UnRegister:Byte(name:String) If (Not MapContains(_Objects, name)) Then _Parent.Output("$2[ERROR] No such object: $5"+name) Return False Else MapRemove(_objects, name) Return True EndIf End Method Method GetObject:Object(name:String) If (Not MapContains(_objects, name)) Then _Parent.Output("$2[ERROR] No such object: $5"+name) Return Null Else Return MapValueForKey(_Objects, name) EndIf End Method Method DumpObject:Byte(objName:String) If (Not MapContains(_Objects, objName)) Then _Parent.Output("$2[ERROR] No such object: $5"+objName) Return False EndIf Local obj:Object = MapValueForKey(_Objects, objName) Local id:TTypeId = TTypeId.ForObject(obj) Local Fields:TList = id.EnumFields() Local Methods:TList = id.EnumMethods() Local name:String _Parent.Output("$3**********OBJECT DUMP*********") _Parent.Output("$4Name: $3 "+objName) _Parent.Output("$4Class: $3 "+id.Name()) If (fields.Count()>0) _Parent.Output("$4Fileds: $3"+Fields.Count()) _Parent.Output("$4Methods: $3"+Methods.Count()) _Parent.Output("$3**********FIELD DUMP**********") Local _Field:TField, stringValue:String For _Field = EachIn Fields stringValue = "" Local _Type:TTypeId = _Field.TypeId() If (_Type.SuperType() = ArrayTypeId) Local i:Int = 0 stringValue = "[" For i = 0 To _Type.ArrayLength(_Field.get(obj))-1 StringValue:+_Type.GetArrayElement(_Field.get(obj), i).ToString()+", " Next stringValue = stringValue[..Len(stringValue)-2]+"]" Else stringValue:String = String(_Field.Get(obj)) EndIf name:String = String(_Field.Name()) _Parent.Output("$3"+name+":$5"+String(_Field.TypeId()._name)+"$5 =$3 "+stringValue) Next EndIf If (methods.Count()>0) _Parent.Output("$3*********METHOD DUMP**********") Local _Method:TMethod For _Method = EachIn Methods name:String = String(_Method.Name()) Local args:TTypeId[] = _method.ArgTypes() _Parent.Output("$3"+name+":$5"+String(_Method.TypeId()._name)) Next EndIf Return True End Method Method GetField:Byte(objName:String, fieldName:String) If (Not MapContains(_Objects, objName)) Then _Parent.Output("$2[ERROR] No such object: $5"+objName) Return False EndIf Local obj:Object = MapValueForKey(_objects, objName) Local id:TTypeId = TTypeId.ForObject(obj) Local _Field:TField = id.FindField(fieldName) If (_Field) _Parent.Output("$3"+objName+"$4.$3"+fieldName+"$4:$3"+String(_Field.TypeId()._name)+" $4=$3 "+String(_Field.Get(Obj))) Return True Else _Parent.Output("$2[ERROR] Unrecognized Field: $3"+objName+"$2.$3"+fieldName) Return False EndIf End Method Method SetField:Byte(objName:String, fieldName:String, stringValue:String) If (Not MapContains(_Objects, objName)) Then _Parent.Output("$2[ERROR] No such object: $5"+objName) Return False EndIf Local obj:Object = MapValueForKey(_objects, objName) Local id:TTypeId = TTypeId.ForObject(obj) Local _Field:TField = id.FindField(fieldName) If (_Field) Select Lower(_Field.TypeId()._name) Case "int" _Field.SetInt(obj, Int(stringValue)) Case "float" _Field.SetFloat(obj, Float(stringValue)) Case "string" _Field.SetString(obj, stringValue) Default _Parent.Output("$2[ERROR] $5"+objName+"$2.$5"+fieldName+" has unrecognized type $5"+_Field.TypeId()._name) Return False End Select Return True Else _Parent.Output("$2[ERROR] Unrecognized Field: $3"+objName+"$2.$3"+fieldName) Return False EndIf End Method Method SetCVar:Byte(CVarName:String, value:Object) If (Not MapContains(_objects, CVarName)) Then _Parent.Output("$2[ERROR] Unrecognized CVar: $5"+CVarName) Return False EndIf Local CVar:Object = MapValueForKey(_objects, CVarName) Local id:TTypeId = TTypeId.ForObject(CVar) If (id.EnumMethods().Count() > 0 Or id.EnumFields().Count() > 0) _Parent.Output("$2[ERROR] Unrecognized CVar: $5"+CVarName) Return False EndIf MapRemove(_objects, CVarName) MapInsert(_objects, CVarName, value) _Parent.Output("$5"+CVarName+" $3=$5 "+String(value.ToString())) Return True End Method Method DumpCVar:Byte(CVarName:String) If (Not MapContains(_objects, CVarName)) Then _Parent.Output("$2[ERROR] Unrecognized CVar: $5"+CVarName) Return False EndIf Local CVar:Object = MapValueForKey(_objects, CVarName) Local id:TTypeId = TTypeId.ForObject(CVar) If (id.EnumMethods().Count() > 0 Or id.EnumFields().Count() > 0) _Parent.Output("$2[ERROR] Unrecognized CVar: $5"+CVarName) Return False EndIf _Parent.Output("$5"+CVarName+" $3=$5 "+String(Cvar.ToString())) Return True End Method Method IsCVar:Byte(CVarName:String) If (Not MapContains(_objects, CVarName)) Then _Parent.Output("$2[ERROR] Unrecognized CVar: $5"+CVarName) Return False EndIf Local CVar:Object = MapValueForKey(_objects, CVarName) Local id:TTypeId = TTypeId.ForObject(CVar) Return (id.EnumMethods().Count()<=0 And id.EnumFields().Count()<=0) End Method Method CallMethod:Byte(objName:String, methodName:String, args:String[]) If (Not MapContains(_Objects, objName)) Then _Parent.Output("$2[ERROR] No such object: $5"+objName) Return False EndIf Local obj:Object = MapValueForKey(_objects, objName) Local id:TTypeId = TTypeId.ForObject(obj) Local _Method:TMethod = id.FindMethod(methodName) If (_method) _Method.Invoke(obj, args) Return True Else _Parent.Output("$2[ERROR] No such method: $5"+objName+"$2:$5"+methodName) Return False EndIf End Method Method PrintObjects() If (_Parent=Null) Return EndIf _Parent.Output("$3Objects:") Local str:String For str = EachIn _Descriptions.Keys() _Parent.Output("$3 - "+str) Next End Method Method GetDescription:String(name:String) If (Not MapContains(_Descriptions, name)) Then Return "" Else Return String(MapValueForKey(_Descriptions, name)) EndIf End Method End Type
Type TConsoleFunction Field _Type:String Field _Function:Byte(args:String[]) Field _Method:TMethod Field _MethodObj:Object Field _Help:String Function CreateFromFunction:TConsoleFunction(func:Byte(args:String[])) Local this:TConsoleFunction = New TConsoleFunction this._Function = func this._Type = "function" Return this End Function Function CreateFromMethod:TConsoleFunction(obj:Object, methodName:String) Local this:TConsoleFunction = New TConsoleFunction this._methodObj = obj Local id:TTypeId = TTypeId.ForObject(Obj) this._Method = id.FindMethod(methodName) If (Not this._method) Return Null EndIf this._Type = "method" Return this End Function Method SetDescription(desc:String) _Help = desc End Method Method GetDescription:String() Return _Help End Method Method Call:Byte(args:String[]) Select _Type Case "function" Return _Function(args) Case "method" Return _Method.Invoke(_MethodObj, args) <> Null End Select End Method End Type Type TConsoleFunctionHandler Field _Functions:TMap Field _Parent:TRainbowConsole Method New() _Functions = New TMap End Method Method RegisterFunction:Byte(Name:String, func:Byte(args:String[]), desc:String = "") If (MapContains(_Functions, name) Or _Parent.GetObjectHandler().Exists(name)) _Parent.Output("$2[ERROR] Double use of name $5"+name) Return False EndIf Local _Function:TConsoleFunction = TConsoleFunction.CreateFromFunction(func) If (Not _Function) _Parent.Output("$2[ERROR] Failed to register function $5"+name) Return False EndIf If (desc<>"") Then _Function.SetDescription(desc) EndIf _Functions.Insert(name, _Function) Return True End Method Method RegisterMethod:Byte(objName:String, methodName:String, desc:String = "") If (MapContains(_Functions, objName+"."+methodName) Or _Parent.GetObjectHandler().Exists(objName+"."+methodName)) _Parent.Output("$2[ERROR] Double use of name $5"+objName+"."+methodName) Return False EndIf Local obj:Object = _Parent.GetObjectHandler().GetObject(objName) If (Not Obj) Return False EndIf Local _Function:TConsoleFunction = TConsoleFunction.CreateFromMethod(obj, methodName) If (Not _Function) _Parent.Output("$2[ERROR] No such method: $5"+objName+"$2.$5"+methodName) Return False EndIf If (desc<>"") Then _Function.SetDescription(desc) EndIf _Functions.Insert(objName+"."+methodName, _Function) Return True End Method Method UnRegister:Byte(name:String) If (MapContains(_Functions, name)) MapRemove(_Functions, name) Return True Else _Parent.Output("$2[ERROR] No such function or method: $5"+name) Return False EndIf End Method Method Exists:Byte(name:String) Return MapContains(_Functions, name) End Method Method Call:Byte(name:String, args:String[]) If (Not MapContains(_Functions, name)) _Parent.Output("$2[ERROR] No such function or method: $5"+name) Return False EndIf TConsoleFunction(MapValueForKey(_Functions, name)).Call(args) End Method Method PrintFunctions() If (_Parent=Null) Then Return EndIf _Parent.Output("$3Functions:") For str:String = EachIn _Functions.Keys() _Parent.Output("$3 - "+str) Next End Method Method GetDescription:String(name:String) If (Not MapContains(_Functions, name)) Return "" EndIf Return TConsoleFunction(MapValueForKey(_functions, name)).GetDescription() End Method End Type
Public
Type TRainbowConsole Field _LineBuffer:TList Field _LinePos:Int Field _CommandBuffer:String[] Field _CommandBufferPos:Int Field _objHandler:TConsoleObjectHandler Field _functionHandler:TConsoleFunctionHandler Field _ConsoleLines:Int Field _InputBuffer:String Field _Open:Byte Field _Opening:Byte Field _Closing:Byte Field _ConsoleToogleKey:Int Field _Ticks:Int Field _CursorPos:Int Field _CharsPerLine:Int Field _consoleBg:TImage Field _imageScaleX:Float Field _imageScaleY:Float Field _BGColor:TColorContainer Field _LineColor:TColorContainer Field _ConsoleHeight:Int Field _ConsoleWidth:Int Field _ConsoleAlpha:Float Field _ConsoleTextHeight:Int Field _ConsoleMovement:Float Field _DrawCursor:Byte Method New() _LineBuffer = New TList _objHandler = New TConsoleObjectHandler _objHandler._Parent = Self _functionHandler = New TConsoleFunctionHandler _functionHandler._Parent = Self _BGColor = TColorContainer.Create(0,0,0) _LineColor = TColorContainer.Create(255,255,255) _ConsoleAlpha = 1 _LinePos = 0 _Open = False _Opening = False _Closing = False _CommandBufferPos = 0 _DrawCursor = False _Ticks = 0 _CursorPos = 0 _objHandler.Init() Output("$3******************************") Output("$5"+RAINBOW_CONSOLE_VERSION) Output("$3******************************") _objHandler.Register("console", Self) End Method Method Output(msg:String) If (_LineBuffer.Count()>RAINBOW_CONSOLE_LINE_BUFFER_SIZE) _LineBuffer.RemoveLast() EndIf If (Not _CharsPerLine Or _CharsPerLine>=Len(TText.Clean(msg))) _LineBuffer.AddFirst(TText.Create("$1"+msg)) Else Local printText:String = TText.ToLength(msg, _CharsPerLine) Local text:TText = TText.Create("$1"+msg[..Len(printText)-1]) Local nextText:String = text.GetLastColorCode()+msg[Len(printText)..] _LineBuffer.AddFirst(text) Output(nextText) EndIf End Method Method GetObjectHandler:TConsoleObjectHandler() Return _ObjHandler End Method Method GetFunctionHandler:TConsoleFunctionHandler() Return _functionHandler End Method Method PhraseInput:Byte() Local args:String[] = GetArgs() If (Not args) Return False EndIf If (_CommandBuffer.length-1>=RAINBOW_CONSOLE_COMMAND_BUFFER_SIZE) _CommandBuffer = _CommandBuffer[1..] EndIf _CommandBuffer = _CommandBuffer[.._commandBuffer.length+1] _CommandBuffer[_commandBuffer.length-1] = _InputBuffer _CommandBufferPos = _CommandBuffer.length _InputBuffer = "" _CursorPos = 0 If (_objHandler.Exists(args[0])) If (_objHandler.IsCVar(args[0])) If (args.length>1) Local stringValue:String, i:Int For i=1 To args.length-1 If (Not (i=1 And args[i] = "=")) stringValue:+args[i]+" " EndIf Next _objHandler.SetCVar(args[0], stringValue) Else _objHandler.DumpCVar(args[0]) EndIf EndIf ElseIf (_functionHandler.Exists(args[0])) _functionHandler.Call(args[0], args[1..]) Else Output("$2[ERROR] No such object or function $5"+args[0]) Return False EndIf Return True End Method Method Update() _ticks:+1 If (_ticks>25) ToogleCursor() _ticks=0 EndIf If (KeyDown(KEY_PAGEUP)) If (_LineBuffer.Count()>_ConsoleLines And (_LineBuffer.Count()-_LinePos)>_ConsoleLines) _LinePos:+1 EndIf ElseIf(KeyDown(KEY_PAGEDOWN)) If (_LinePos>0) _LinePos:-1 EndIf EndIf If (_CommandBuffer) If (KeyHit(KEY_UP)) If (_CommandBufferPos>0) _CommandBufferPos:-1 EndIf _InputBuffer = _CommandBuffer[_CommandBufferPos] FlushKeys() ElseIf (KeyHit(KEY_DOWN)) If (_CommandBufferPos<_CommandBuffer.length) _CommandBufferPos:+1 EndIf If (_CommandBufferPos>_CommandBuffer.length-1) _InputBuffer = "" Else _InputBuffer = _CommandBuffer[_CommandBufferPos] EndIf FlushKeys() EndIf EndIf If (KeyHit(KEY_LEFT)) If (_CursorPos>0) _CursorPos:-1 EndIf ElseIf (KeyHit(KEY_RIGHT)) If (_CursorPos<Len(_InputBuffer)) _CursorPos:+1 EndIf EndIf If (KeyHit(_ConsoleToogleKey)) Toogle() EndIf Draw() If (_Open) UpdateInput() Else UpdateMovement() EndIf End Method Method Toogle() If (_Open) _Closing = True _Opening = False _Open = False Else If (_ConsoleMovement <= 0) _ConsoleMovement = _ConsoleHeight EndIf _Opening = True _Closing = False _Open = False EndIf FlushKeys() End Method Method ToogleCursor() _DrawCursor = Not _DrawCursor End Method Method UpdateMovement() If (_Opening) _ConsoleMovement:- RAINBOW_CONSOLE_POPUP_SPEED If (_ConsoleMovement <=0) _ConsoleMovement = 0 _Opening = False _Open = True EndIf ElseIf (_Closing) _ConsoleMovement:+ RAINBOW_CONSOLE_POPUP_SPEED If (_ConsoleMovement >= _ConsoleHeight) _ConsoleMovement = _ConsoleHeight _Closing = False EndIf EndIf End Method Method UpdateInput() Local char:Int = GetChar() While char Select char Case KEY_ENTER output("$3> $5"+_inputBuffer) PhraseInput() Case KEY_BACKSPACE If (Len(_InputBuffer)>0) _InputBuffer = _InputBuffer[.._CursorPos-1]+_InputBuffer[_CursorPos..] _CursorPos:-1 EndIf Case KEY_TAB Default _InputBuffer = _InputBuffer[.._CursorPos]+Chr(char)+_InputBuffer[_CursorPos..] _CursorPos:+1 End Select char = GetChar() Wend End Method Method GetArgs:String[]() Local args:String[], i:Int, count:Int=0, lastArg:Int = 0, inQuotes:Byte = False, wasInQuotes:Byte = False For i=0 To Len(_inputBuffer)-1 Local char:String = _inputBuffer[i..(i+1)] Select char Case Chr(34) inQuotes = Not inQuotes wasInQuotes = True Case " " If (inQuotes) Continue EndIf If (_inputBuffer[lastArg..i] And _inputBuffer[lastArg..i]<>" " And _inputBuffer[lastArg..i] <> Chr(KEY_QUOTES)+" "+Chr(KEY_QUOTES)) args = args[..count+1] If (wasInQuotes) args[count] = _InputBuffer[lastArg+1..i-1] Else args[count] = _inputBuffer[lastArg..i] EndIf count:+1 EndIf wasInQuotes = False lastArg = i+1 End Select Next args = args[..count+1] args[count] = _inputBuffer[lastArg..] Return args End Method Method Draw() If (Not GraphicsHeight()) Return EndIf If (Not _ConsoleHeight) Then _ConsoleHeight = GraphicsHeight()/3 EndIf If (Not _ConsoleWidth) Then _ConsoleWidth = GraphicsWidth() EndIf If (Not _ConsoleTextHeight) _ConsoleTextHeight = TextHeight("M") EndIf If (Not _ConsoleLines) _ConsoleLines = Floor(Float((_ConsoleHeight-_ConsoleTextHeight-4)/_ConsoleTextHeight)+0.5) EndIf If (Not _CharsPerLine) _CharsPerLine = Floor(Float((_ConsoleWidth-5)/TextWidth("X")+0.5)) EndIf If (Not _Open And Not _Opening And Not _Closing) Return EndIf Local lastColor:TColorContainer = TColorContainer.CreateFromCurrent() Local lastScaleX:Float, lastScaleY:Float GetScale(lastScaleX, lastScaleY) Local lastAlpha:Float = GetAlpha() Local lastBlend:Byte = GetBlend() SetBlend(ALPHABLEND) SetAlpha(_ConsoleAlpha) If (_consoleBg) Then If (Not _ImageScaleX) _ImageScaleX = _ConsoleWidth/ImageWidth(_consoleBg) EndIf If (Not _ImageScaleY) _ImageScaleY = _ConsoleHeight/ImageHeight(_consoleBg) EndIf SetScale(_ImageScaleX, _ImageScaleY) DrawImage(_consoleBg, 0, 0-_ConsoleMovement) Else _BGColor.Set() DrawRect(0,0,_ConsoleWidth,_ConsoleHeight-_ConsoleMovement) EndIf SetScale(lastScaleX, lastScaleY) _LineColor.Set() DrawLine(0,_ConsoleHeight-_ConsoleTextHeight-2-_ConsoleMovement, _ConsoleWidth, _ConsoleHeight-_ConsoleTextHeight-2-_ConsoleMovement) If (_DrawCursor) DrawText(_InputBuffer, 5, _ConsoleHeight-_ConsoleTextHeight-1-_ConsoleMovement) DrawText("_",TextWidth(_InputBuffer[.._CursorPos])+5, _ConsoleHeight-_ConsoleTextHeight-_ConsoleMovement) Else DrawText(_InputBuffer, 5, _ConsoleHeight-_ConsoleTextHeight-1-_ConsoleMovement) EndIf Local tempScreenPos:Int = _ConsoleHeight-2*_ConsoleTextHeight-4, i:Int = 1, tempText:TText, tempLinePos:Int = 0 ?Debug If (_LineBuffer.Count()<=0) DebugLog("Empty buffer") EndIf ? For tempText = EachIn _LineBuffer If (tempLinePos<_LinePos) tempLinePos:+1 Continue EndIf _LineColor.Set() tempText.Draw(5,tempScreenPos-_ConsoleMovement) i:+1 tempScreenPos:-_ConsoleTextHeight+1 If (i>_ConsoleLines Or tempScreenPos<-_ConsoleTextHeight) Exit EndIf Next SetBlend(lastBlend) SetAlpha(lastAlpha) lastColor.Set() End Method Method SetBackgroundImage(path:String) _consoleBg = LoadImage(path) End Method Method SetToogleKey(key:Int) _ConsoleToogleKey = key End Method Method SetBackgroundColor(r:Int, g:Int, b:Int) _BGColor = TColorContainer.Create(r, g, b) End Method Method SetConsoleAlpha(alpha:Float) _consoleAlpha = alpha End Method Method SetLineColor(r:Int, g:Int, b:Int) _LineColor = TColorContainer.Create(r, g, b) End Method Method RegisterFunction:Byte(name:String, Func:Byte(args:String[]), desc:String = "") Return _functionHandler.RegisterFunction(name, func, desc) End Method Method RegisterMethod:Byte(objName:String, methodName:String, desc:String = "") Return _functionHandler.RegisterMethod(objName, methodName, desc) End Method Method RegisterObject:Byte(name:String, obj:Object, desc:String = "") Return _objHandler.Register(name, obj, desc) End Method Method RegisterCVar:Byte(name:String, value:Object = Null) Return _objHandler.RegisterCVar(name, value) End Method Method UnRegisterFunction:Byte(name:String) Return _functionHandler.UnRegister(name) End Method Method UnRegisterMethod:Byte(objName:String, methodName:String) Return _FunctionHandler.UnRegister(objName+"."+methodName) End Method Method UnRegisterObject:Byte(name:String) Return _objHandler.UnRegister(name) End Method Method UnRegisterCVar:Byte(name:String) Return _objHandler.UnRegister(name) End Method
End Type
TColorContainer:
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN]
Type TColorContainer Field fRed:Int Field fGreen:Int Field fBlue:Int Function Create:TColorContainer(r:Int, g:Int, b:Int) Local _self:TColorContainer = New TColorContainer _self.fRed = r _self.fGreen = g _self.fBlue = b Return _self End Function Function CreateFromCurrent:TColorContainer() Local r:Int, g:Int, b:Int GetColor(r, g, b) Return TColorContainer.Create(r, g, b) End Function Method Set() SetColor(fRed, fGreen, fBlue) End Method Method ToString:String() Return "Red: "+fRed+" Blue: "+fBlue+" Green "+fGreen End Method End Type
TText.bmx
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN]
Type TText Global Colors:TMap = New TMap Field Text:TList Field Color:TList Method New() Text = New TList Color = New TList End Method Function Create:TText(msg:String) Local this:TText = New TText this.Color.AddLast(TColorContainer.Create(255,255,255)) Local dollarMsgStart:Int = -1, colorMsgStart:Int = 0, i:Int For i = 0 To Len(msg)-1 Local char:String = msg[i..(i+1)] If(dollarMsgStart>=0) If (MapContains(TText.Colors, msg[dollarMsgStart..i])) Then this.Text.AddLast(msg[colorMsgStart..dollarMsgStart]) this.Color.AddLast(tColorContainer(MapValueForKey(TText.Colors, msg[dollarMsgStart..i]))) If (Char="$") dollarMsgStart = i Else dollarMsgStart = -1 EndIf colorMsgStart = i Else If (Char="$") dollarMsgStart = i EndIf EndIf ElseIf (Char="$") dollarMsgStart = i EndIf Next If (colorMsgStart And colorMsgStart<>i) this.Text.AddLast(msg[colorMsgStart..]) EndIf Return this End Function Function Clean:String(msg:String) Local finalMsg:String = "", cleanMsgStart:Int = 0, dollarMsgStart:Int = -1, i:Int For i = 0 To Len(msg)-1 Local char:String = msg[i..(i+1)] If(dollarMsgStart>=0) If (MapContains(TText.Colors, msg[dollarMsgStart..i])) Then finalMsg:+msg[cleanMsgStart..dollarMsgStart] If (Char="$") dollarMsgStart = i Else dollarMsgStart = -1 EndIf cleanMsgStart = i Else If (Char="$") dollarMsgStart = i EndIf EndIf ElseIf (Char="$") dollarMsgStart = i EndIf Next If (cleanMsgStart And cleanMsgStart<>i) finalMsg:+msg[cleanMsgStart..] EndIf Return finalMsg End Function Method Draw(x:Int, y:Int) Local lText:String, width:Int = x, lastColor:TColorContainer = TColorContainer.CreateFromCurrent(), i:Int = 0 For lText = EachIn Text TColorContainer(Color.ValueAtIndex(i)).Set() DrawText(lText, width, y) width:+TextWidth(lText) i:+1 Next lastColor.Set() End Method Method GetLastColorCode:String() Local lastColor:Object = Color.Last() Local colorObj:Object For colorObj = EachIn MapKeys(TText.Colors) If (MapValueForKey(TText.Colors, colorObj) = lastColor) Return colorObj.ToString() EndIf Next End Method Function ToLength:String(msg:String, length:Int) If (length<=0) Return "" EndIf Local dollarMsgStart:Int = -1, i:Int, _length:Int=1 , dollarMsg:Byte For i=0 To Len(msg)-1 Local char:String = msg[i..(i+1)] If(dollarMsgStart>=0) If (MapContains(TText.Colors, msg[dollarMsgStart..i])) Then _length:-Len(msg[dollarMsgStart..i]) If (Char="$") dollarMsgStart = i dollarMsg = True If (_length>=length) Return msg[..(i-1)] EndIf Else dollarMsgStart = -1 dollarMsg = False EndIf Else If (Char="$") dollarMsg = True dollarMsgStart = i EndIf _length:+1 EndIf ElseIf (Char="$") dollarMsg = True dollarMsgStart = i _length:+1 Else _length:+1 EndIf If (_length>=length And Not dollarMsg) Return msg[..(i-1)] EndIf Next _length:-Len(msg[dollarMsgStart..]) If (_length>0) Return msg[..(dollarMsgStart-1)] Else Return msg[..length] EndIf End Function Function RegisterColor(name:String, r:Int, g:Int, b:Int) If (Left(name,1)<>"$") name = "$"+name EndIf If (MapContains(TText.Colors, name)) Return EndIf MapInsert(TText.Colors, name, TColorContainer.Create(r, g, b)) End Function End Type
TText.RegisterColor("$0", 0 , 0 , 0 ) TText.RegisterColor("$1", 255, 255 , 255 ) TText.RegisterColor("$2", 255, 0 , 0 ) TText.RegisterColor("$3", 0 , 255 , 0 ) TText.RegisterColor("$4", 0 , 0 , 255 ) TText.RegisterColor("$5", 255, 255 , 0 ) TText.RegisterColor("$6", 0 , 255 , 255 ) TText.RegisterColor("$7", 255, 0 , 255 )
Sooo. Jetzt nochn paar erklärungen und ein beispiel.
Als erstes sollte man eine globale Konsole erstellen
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] gConsole:TRainbowConsole = New TRainbowConsole
So jetzt wollen wir erstmal eine Test Object hinzufügen
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] Type TTest Extends TTest2 Method test() gConsole.Output("$3TTest.Test called") End Method End Type
Type TTest2 Method test2() gConsole.Output("TTest2.Test2 called") End Method End Type
so jetzt zum registrieren. Das geht volgendermaßen:
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] gConsole.RegisterObject("testObj", New TTest, "Test Objekt")
Der letzte Parameter ist jeweils für die Hilfe-Funktion, ist aber Optional
Als nächstes wollen wir die beiden methoden tegistriern.
Wichtig: Es können nur methoden von bereits vorhandenen objekten registriert werden
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] gConsole.RegisterMethod("testObj", "test", "Test Methode") gConsole.RegisterMethod("testObj", "test2")
Bei test2 lassen wir den Hilfe-String weg um festzustellen, was passiert wenn keiner vorhanden ist
Gut nachdem das getan ist, registrieren wir noch eine test funktion
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] Function test:Byte(args:String[]) If (args.length<2) Then gConsole.Output("$2Not enought arguments!") Return; EndIf gConsole.Output("$3args[0] = $5"+args[0]+" $3args[1] = $5"+args[1]) End Function
gConsole.RegisterFunction("testFunc", test, "Test Funktion")
So jetzt setzen wir noch eine taste, die die konsole öffnet. Ich nehme in diesem fall die taste ^
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] gConsole.SetToogleKey(220)
In meinem Fall benutze ich zusätzlich ein Hintergrundbild (zum Test) und setze es Durchlässig
Beides optional.
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] gConsole.SetBackgroundImage("res/bmax120.png"); gConsole.SetConsoleAlpha(0.5);
Als letzes !!muss!! noch der Garfikmodus gesetzt werden. Ich nehme hier
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] Graphics 1024,768
Jetzt nurnoch die hauptschleife
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] While (Not KeyDown(KEY_ESCAPE) And Not AppTerminate()) Cls gConsole.Update() Flip Wend
Und hier nochmal der ganze Code für die Faulen unter euch
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] Include "TConsole.bmx"
Type TTest Extends TTest2 Method test() gConsole.Output("$3TTest.Test called") End Method End Type
Type TTest2 Method test2() gConsole.Output("TTest2.Test2 called") End Method End Type
gConsole.RegisterObject("testObj", New TTest, "Test Objekt") gConsole.RegisterMethod("testObj", "test", "Test Methode") gConsole.RegisterMethod("testObj", "test2") Function test:Byte(args:String[]) If (args.length<2) Then gConsole.Output("$2Not enought arguments!") Return; EndIf gConsole.Output("$3args[0] = $5"+args[0]+" $3args[1] = $5"+args[1]) End Function
gConsole.RegisterFunction("testFunc", test, "Test Funktion") gConsole.SetToogleKey(220) gConsole.SetBackgroundImage("res/bmax120.png"); gConsole.SetConsoleAlpha(0.5);
Graphics 1024,768
While (Not KeyDown(KEY_ESCAPE) And Not AppTerminate()) Cls gConsole.Update() Flip Wend
Standardmäßige Kommandos sind:
ObjectHandler.DumpObject <Object>
ObjectHandler.DumpCVar <CVar>
ObjectHandler.SetField <Object> <Field> <Value>
ObjectHandler.GetFiel <Object> <Field>
help [Object]
Parameter in <> sind nötig!
Parameter in [] sind optional!
Wenn ihr die Konsole dann mit ^ geöffnet habt, könnt ihr einfach Kommandos eingeben (siehe unten)
Scrollen könnt ihr mit Bild-Auf und Bild-Ab, zuletzt benutzte Kommandos könnt ihr mit Auf und Ab auswählen
Bilder:
Es gibt noch weitere funktionen, die ich hier jetzt noch nicht vorstelle. Diese werde ich dann wenn das Modul fertig ist zeigen und erklären
Kritik ist erwünscht und wer Fehler findet, darf sie gerne melden
Greez
Pope
|