2020-11-15 03:10:44 +01:00
import { InputElement } from "./InputElement"
import { UIEventSource } from "../../Logic/UIEventSource"
import Combine from "../Base/Combine"
import Svg from "../../Svg"
2021-06-23 02:15:28 +02:00
import BaseUIElement from "../BaseUIElement"
2021-06-16 17:09:32 +02:00
import { FixedUiElement } from "../Base/FixedUiElement"
2021-06-23 02:15:28 +02:00
import { Utils } from "../../Utils"
import Loc from "../../Models/Loc"
2021-09-21 02:10:42 +02:00
import Minimap from "../Base/Minimap"
2020-11-15 03:10:44 +01:00
/ * *
* Selects a direction in degrees
* /
export default class DirectionInput extends InputElement < string > {
public readonly IsSelected : UIEventSource < boolean > = new UIEventSource < boolean > ( false )
2021-09-09 00:05:51 +02:00
private readonly _location : UIEventSource < Loc >
2021-06-18 14:30:49 +02:00
private readonly value : UIEventSource < string >
2021-06-23 02:15:28 +02:00
private background
2022-09-08 21:40:48 +02:00
2021-09-09 00:05:51 +02:00
constructor (
mapBackground : UIEventSource < any > ,
2021-06-23 02:15:28 +02:00
location : UIEventSource < Loc > ,
value? : UIEventSource < string >
) {
2020-11-15 03:10:44 +01:00
super ( )
2021-06-23 02:15:28 +02:00
this . _location = location
2020-11-15 03:10:44 +01:00
this . value = value ? ? new UIEventSource < string > ( undefined )
2021-06-23 02:15:28 +02:00
this . background = mapBackground
2021-06-16 17:09:32 +02:00
}
2021-06-18 14:30:49 +02:00
GetValue ( ) : UIEventSource < string > {
return this . value
}
IsValid ( str : string ) : boolean {
const t = Number ( str )
return ! isNaN ( t ) && t >= 0 && t <= 360
}
2021-06-16 17:09:32 +02:00
protected InnerConstructElement ( ) : HTMLElement {
2021-06-23 02:15:28 +02:00
let map : BaseUIElement = new FixedUiElement ( "" )
if ( ! Utils . runningFromConsole ) {
2021-09-21 02:10:42 +02:00
map = Minimap . createMiniMap ( {
2021-06-23 02:15:28 +02:00
background : this.background ,
allowMoving : false ,
location : this._location ,
} )
}
2021-06-16 17:09:32 +02:00
2021-06-18 14:30:49 +02:00
const element = new Combine ( [
2021-09-09 00:05:51 +02:00
Svg . direction_stroke_svg ( )
. SetStyle (
2021-06-10 14:05:26 +02:00
` position: absolute;top: 0;left: 0;width: 100%;height: 100%;transform:rotate( ${
this . value . data ? ? 0
} deg ) ; `
)
2021-06-23 02:15:28 +02:00
. SetClass ( "direction-svg relative" )
2021-09-09 00:05:51 +02:00
. SetStyle ( "z-index: 1000" ) ,
2021-09-03 17:00:36 +02:00
map . SetStyle ( ` position: absolute;top: 0;left: 0;width: 100%;height: 100%; ` ) ,
2021-06-10 14:05:26 +02:00
] )
2021-09-03 17:00:36 +02:00
. SetStyle ( "width: min(100%, 25em); height: 0; padding-bottom: 100%" ) // A bit a weird CSS , see https://stackoverflow.com/questions/13851940/pure-css-solution-square-elements#19448481
2021-08-26 16:24:18 +02:00
. SetClass ( "relative block bg-white border border-black overflow-hidden rounded-full" )
2021-06-10 14:05:26 +02:00
. ConstructElement ( )
2021-06-30 15:38:14 +02:00
this . value . addCallbackAndRunD ( ( rotation ) = > {
2021-06-16 17:09:32 +02:00
const cone = element . getElementsByClassName ( "direction-svg" ) [ 0 ] as HTMLElement
2021-04-21 01:55:15 +02:00
cone . style . transform = ` rotate( ${ rotation } deg) `
2020-11-15 03:10:44 +01:00
} )
2021-06-18 14:30:49 +02:00
this . RegisterTriggers ( element )
2021-07-12 00:05:56 +02:00
element . style . overflow = "hidden"
2021-08-26 16:24:18 +02:00
element . style . display = "block"
2020-11-15 03:10:44 +01:00
2021-06-18 14:30:49 +02:00
return element
2020-11-15 03:10:44 +01:00
}
2021-06-16 17:09:32 +02:00
private RegisterTriggers ( htmlElement : HTMLElement ) {
2020-11-15 03:10:44 +01:00
const self = this
function onPosChange ( x : number , y : number ) {
const rect = htmlElement . getBoundingClientRect ( )
const dx = - ( rect . left + rect . right ) / 2 + x
const dy = ( rect . top + rect . bottom ) / 2 - y
const angle = ( 180 * Math . atan2 ( dy , dx ) ) / Math . PI
const angleGeo = Math . floor ( ( 450 - angle ) % 360 )
2020-11-17 02:22:48 +01:00
self . value . setData ( "" + angleGeo )
2020-11-15 03:10:44 +01:00
}
htmlElement . ontouchmove = ( ev : TouchEvent ) = > {
2020-11-15 19:17:36 +01:00
onPosChange ( ev . touches [ 0 ] . clientX , ev . touches [ 0 ] . clientY )
ev . preventDefault ( )
}
htmlElement . ontouchstart = ( ev : TouchEvent ) = > {
2020-11-15 03:10:44 +01:00
onPosChange ( ev . touches [ 0 ] . clientX , ev . touches [ 0 ] . clientY )
}
let isDown = false
htmlElement . onmousedown = ( ev : MouseEvent ) = > {
isDown = true
2021-04-21 01:55:15 +02:00
onPosChange ( ev . clientX , ev . clientY )
2020-11-15 03:10:44 +01:00
ev . preventDefault ( )
}
htmlElement . onmouseup = ( ev ) = > {
2021-06-18 14:30:49 +02:00
isDown = false
ev . preventDefault ( )
2020-11-15 03:10:44 +01:00
}
htmlElement . onmousemove = ( ev : MouseEvent ) = > {
if ( isDown ) {
2021-04-21 01:55:15 +02:00
onPosChange ( ev . clientX , ev . clientY )
2021-06-18 14:30:49 +02:00
}
ev . preventDefault ( )
2020-11-15 03:10:44 +01:00
}
}
}