506 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			506 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace FML\Controls;
 | |
| 
 | |
| use FML\Script\Builder;
 | |
| use FML\Script\Features\ActionTrigger;
 | |
| use FML\Script\Features\ControlScript;
 | |
| use FML\Script\Features\MapInfo;
 | |
| use FML\Script\Features\PlayerProfile;
 | |
| use FML\Script\Features\ScriptFeature;
 | |
| use FML\Script\Features\Toggle;
 | |
| use FML\Script\Features\Tooltip;
 | |
| use FML\Script\Features\UISound;
 | |
| use FML\Script\ScriptLabel;
 | |
| use FML\Types\Renderable;
 | |
| use FML\Types\ScriptFeatureable;
 | |
| use FML\UniqueID;
 | |
| 
 | |
| /**
 | |
|  * Base Control
 | |
|  * (CMlControl)
 | |
|  *
 | |
|  * @author    steeffeen <mail@steeffeen.com>
 | |
|  * @copyright FancyManiaLinks Copyright © 2014 Steffen Schröder
 | |
|  * @license   http://www.gnu.org/licenses/ GNU General Public License, Version 3
 | |
|  */
 | |
| abstract class Control implements Renderable, ScriptFeatureable {
 | |
| 	/*
 | |
| 	 * Constants
 | |
| 	 */
 | |
| 	const CENTER  = 'center';
 | |
| 	const CENTER2 = 'center2';
 | |
| 	const TOP     = 'top';
 | |
| 	const RIGHT   = 'right';
 | |
| 	const BOTTOM  = 'bottom';
 | |
| 	const LEFT    = 'left';
 | |
| 
 | |
| 	/*
 | |
| 	 * Protected properties
 | |
| 	 */
 | |
| 	protected $tagName = 'control';
 | |
| 	protected $controlId = null;
 | |
| 	protected $posX = 0.;
 | |
| 	protected $posY = 0.;
 | |
| 	protected $posZ = 0.;
 | |
| 	protected $width = -1.;
 | |
| 	protected $height = -1.;
 | |
| 	protected $hAlign = self::CENTER;
 | |
| 	protected $vAlign = self::CENTER2;
 | |
| 	protected $scale = 1.;
 | |
| 	protected $hidden = null;
 | |
| 	protected $rotation = 0.;
 | |
| 	/** @var string[] $classes */
 | |
| 	protected $classes = array();
 | |
| 	/** @var ScriptFeature[] $scriptFeatures */
 | |
| 	protected $scriptFeatures = array();
 | |
| 
 | |
| 	/**
 | |
| 	 * Create a new Control object
 | |
| 	 *
 | |
| 	 * @param string $controlId (optional) Control id
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public static function create($controlId = null) {
 | |
| 		return new static($controlId);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Construct a new Control object
 | |
| 	 *
 | |
| 	 * @param string $controlId (optional) Control id
 | |
| 	 */
 | |
| 	public function __construct($controlId = null) {
 | |
| 		if ($controlId !== null) {
 | |
| 			$this->setId($controlId);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Check Id for dangerous characters and assign a new unique id if necessary
 | |
| 	 *
 | |
| 	 * @param bool $forceNewId (optional) Whether to force setting a newly generated id
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function checkId($forceNewId = false) {
 | |
| 		if ($forceNewId || !$this->getId()) {
 | |
| 			$this->setId(new UniqueID());
 | |
| 			return $this;
 | |
| 		}
 | |
| 		$dangerousCharacters = array(' ', '	', '.', '|', '-', PHP_EOL);
 | |
| 		$idCharacters        = str_split($this->getId());
 | |
| 		$danger              = false;
 | |
| 		foreach ($idCharacters as $character) {
 | |
| 			if (!in_array($character, $dangerousCharacters)) {
 | |
| 				continue;
 | |
| 			}
 | |
| 			$danger = true;
 | |
| 			break;
 | |
| 		}
 | |
| 		if ($danger) {
 | |
| 			trigger_error("Please don't use special characters in ids, they might cause problems! (I stripped them for you.)");
 | |
| 			$controlId = str_ireplace($dangerousCharacters, '', $this->getId());
 | |
| 			$this->setId($controlId);
 | |
| 		}
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get the Control id
 | |
| 	 *
 | |
| 	 * @param bool $escaped        (optional) Whether the id should be escaped for ManiaScript
 | |
| 	 * @param bool $addApostrophes (optional) Whether to add apostrophes before and after the text
 | |
| 	 * @return string
 | |
| 	 */
 | |
| 	public function getId($escaped = false, $addApostrophes = false) {
 | |
| 		if ($escaped) {
 | |
| 			return Builder::escapeText($this->controlId, $addApostrophes);
 | |
| 		}
 | |
| 		return $this->controlId;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set Control id
 | |
| 	 *
 | |
| 	 * @param string $controlId Control id
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setId($controlId) {
 | |
| 		$this->controlId = (string)$controlId;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set Control position
 | |
| 	 *
 | |
| 	 * @param float $posX Horizontal position
 | |
| 	 * @param float $posY Vertical position
 | |
| 	 * @param float $posZ (optional) Depth
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setPosition($posX, $posY, $posZ = null) {
 | |
| 		$this->setX($posX);
 | |
| 		$this->setY($posY);
 | |
| 		if ($posZ !== null) {
 | |
| 			$this->setZ($posZ);
 | |
| 		}
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set X position
 | |
| 	 *
 | |
| 	 * @param float $posX Horizontal position
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setX($posX) {
 | |
| 		$this->posX = (float)$posX;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set Y position
 | |
| 	 *
 | |
| 	 * @param float $posY Vertical position
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setY($posY) {
 | |
| 		$this->posY = (float)$posY;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set Z position
 | |
| 	 *
 | |
| 	 * @param float $posZ Depth
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setZ($posZ) {
 | |
| 		$this->posZ = (float)$posZ;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set Control size
 | |
| 	 *
 | |
| 	 * @param float $width  Control width
 | |
| 	 * @param float $height Control height
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setSize($width, $height) {
 | |
| 		$this->setWidth($width);
 | |
| 		$this->setHeight($height);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set Control width
 | |
| 	 *
 | |
| 	 * @param float $width Control width
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setWidth($width) {
 | |
| 		$this->width = (float)$width;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set Control height
 | |
| 	 *
 | |
| 	 * @param float $height Control height
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setHeight($height) {
 | |
| 		$this->height = (float)$height;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Center alignment
 | |
| 	 *
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function centerAlign() {
 | |
| 		$this->setAlign(self::CENTER, self::CENTER2);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set horizontal and vertical alignment
 | |
| 	 *
 | |
| 	 * @param string $hAlign Horizontal alignment
 | |
| 	 * @param string $vAlign Vertical alignment
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setAlign($hAlign, $vAlign) {
 | |
| 		$this->setHAlign($hAlign);
 | |
| 		$this->setVAlign($vAlign);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set horizontal alignment
 | |
| 	 *
 | |
| 	 * @param string $hAlign Horizontal alignment
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setHAlign($hAlign) {
 | |
| 		$this->hAlign = (string)$hAlign;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set vertical alignment
 | |
| 	 *
 | |
| 	 * @param string $vAlign Vertical alignment
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setVAlign($vAlign) {
 | |
| 		$this->vAlign = (string)$vAlign;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Reset alignment
 | |
| 	 *
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function resetAlign() {
 | |
| 		$this->setAlign(null, null);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set Control scale
 | |
| 	 *
 | |
| 	 * @param float $scale Control scale
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setScale($scale) {
 | |
| 		$this->scale = (float)$scale;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set visibility
 | |
| 	 *
 | |
| 	 * @param bool $visible Whether the Control should be visible
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setVisible($visible = true) {
 | |
| 		$this->hidden = ($visible ? 0 : 1);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set Control rotation
 | |
| 	 *
 | |
| 	 * @param float $rotation Control rotation
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function setRotation($rotation) {
 | |
| 		$this->rotation = (float)$rotation;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a new class name
 | |
| 	 *
 | |
| 	 * @param string $class Class name
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function addClass($class) {
 | |
| 		$class = (string)$class;
 | |
| 		if (!in_array($class, $this->classes)) {
 | |
| 			array_push($this->classes, $class);
 | |
| 		}
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a dynamic Action Trigger
 | |
| 	 *
 | |
| 	 * @param string $actionName Action to trigger
 | |
| 	 * @param string $eventLabel (optional) Event on which the action is triggered
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function addActionTriggerFeature($actionName, $eventLabel = ScriptLabel::MOUSECLICK) {
 | |
| 		if ($actionName instanceof ActionTrigger) {
 | |
| 			$this->addScriptFeature($actionName);
 | |
| 		} else {
 | |
| 			$actionTrigger = new ActionTrigger($actionName, $this, $eventLabel);
 | |
| 			$this->addScriptFeature($actionTrigger);
 | |
| 		}
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a new Script Feature
 | |
| 	 *
 | |
| 	 * @param ScriptFeature $scriptFeature Script Feature
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function addScriptFeature(ScriptFeature $scriptFeature) {
 | |
| 		if (!in_array($scriptFeature, $this->scriptFeatures, true)) {
 | |
| 			array_push($this->scriptFeatures, $scriptFeature);
 | |
| 		}
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a dynamic Feature opening the current map info
 | |
| 	 *
 | |
| 	 * @param string $eventLabel (optional) Event on which the map info will be opened
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function addMapInfoFeature($eventLabel = ScriptLabel::MOUSECLICK) {
 | |
| 		$mapInfo = new MapInfo($this, $eventLabel);
 | |
| 		$this->addScriptFeature($mapInfo);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a dynamic Feature to open a specific player profile
 | |
| 	 *
 | |
| 	 * @param string $login      Login of the player
 | |
| 	 * @param string $eventLabel (optional) Event on which the player profile will be opened
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function addPlayerProfileFeature($login, $eventLabel = ScriptLabel::MOUSECLICK) {
 | |
| 		$playerProfile = new PlayerProfile($login, $this, $eventLabel);
 | |
| 		$this->addScriptFeature($playerProfile);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a dynamic Feature playing a UISound
 | |
| 	 *
 | |
| 	 * @param string $soundName  UISound name
 | |
| 	 * @param int    $variant    (optional) Sound variant
 | |
| 	 * @param string $eventLabel (optional) Event on which the sound will be played
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function addUISoundFeature($soundName, $variant = 0, $eventLabel = ScriptLabel::MOUSECLICK) {
 | |
| 		$uiSound = new UISound($soundName, $this, $variant, $eventLabel);
 | |
| 		$this->addScriptFeature($uiSound);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a dynamic Feature toggling another Control
 | |
| 	 *
 | |
| 	 * @param Control $toggledControl Toggled Control
 | |
| 	 * @param string  $labelName      (optional) Script label name
 | |
| 	 * @param bool    $onlyShow       (optional) Whether it should only show the Control but not toggle
 | |
| 	 * @param bool    $onlyHide       (optional) Whether it should only hide the Control but not toggle
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function addToggleFeature(Control $toggledControl, $labelName = Scriptlabel::MOUSECLICK, $onlyShow = false, $onlyHide = false) {
 | |
| 		$toggle = new Toggle($this, $toggledControl, $labelName, $onlyShow, $onlyHide);
 | |
| 		$this->addScriptFeature($toggle);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a dynamic Feature showing a Tooltip on hovering
 | |
| 	 *
 | |
| 	 * @param Control $tooltipControl Tooltip Control
 | |
| 	 * @param bool    $stayOnClick    (optional) Whether the Tooltip should stay on click
 | |
| 	 * @param bool    $invert         (optional) Whether the visibility toggling should be inverted
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function addTooltipFeature(Control $tooltipControl, $stayOnClick = false, $invert = false) {
 | |
| 		$tooltip = new Tooltip($this, $tooltipControl, $stayOnClick, $invert);
 | |
| 		$this->addScriptFeature($tooltip);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a dynamic Feature showing a Tooltip on hovering
 | |
| 	 *
 | |
| 	 * @param Label  $tooltipControl Tooltip Control
 | |
| 	 * @param string $text           Text to display on the Tooltip Label
 | |
| 	 * @param bool   $stayOnClick    (optional) Whether the Tooltip should stay on click
 | |
| 	 * @param bool   $invert         (optional) Whether the visibility toggling should be inverted
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function addTooltipLabelFeature(Label $tooltipControl, $text, $stayOnClick = false, $invert = false) {
 | |
| 		$tooltip = new Tooltip($this, $tooltipControl, $stayOnClick, $invert, $text);
 | |
| 		$this->addScriptFeature($tooltip);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a custom Control Script text part
 | |
| 	 *
 | |
| 	 * @param string $scriptText Script text
 | |
| 	 * @param string $label      (optional) Script label name
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function addScriptText($scriptText, $label = ScriptLabel::MOUSECLICK) {
 | |
| 		$customText = new ControlScript($this, $scriptText, $label);
 | |
| 		$this->addScriptFeature($customText);
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Remove all Script Features
 | |
| 	 *
 | |
| 	 * @return static
 | |
| 	 */
 | |
| 	public function removeScriptFeatures() {
 | |
| 		$this->scriptFeatures = array();
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @see \FML\Types\ScriptFeatureable::getScriptFeatures()
 | |
| 	 */
 | |
| 	public function getScriptFeatures() {
 | |
| 		return $this->scriptFeatures;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @see \FML\Types\Renderable::render()
 | |
| 	 */
 | |
| 	public function render(\DOMDocument $domDocument) {
 | |
| 		$xmlElement = $domDocument->createElement($this->tagName);
 | |
| 		if ($this->controlId) {
 | |
| 			$xmlElement->setAttribute('id', $this->controlId);
 | |
| 		}
 | |
| 		if ($this->posX || $this->posY || $this->posZ) {
 | |
| 			$xmlElement->setAttribute('posn', "{$this->posX} {$this->posY} {$this->posZ}");
 | |
| 		}
 | |
| 		if ($this->width >= 0. || $this->height >= 0.) {
 | |
| 			$xmlElement->setAttribute('sizen', "{$this->width} {$this->height}");
 | |
| 		}
 | |
| 		if ($this->hAlign !== self::LEFT) {
 | |
| 			$xmlElement->setAttribute('halign', $this->hAlign);
 | |
| 		}
 | |
| 		if ($this->vAlign !== self::TOP) {
 | |
| 			$xmlElement->setAttribute('valign', $this->vAlign);
 | |
| 		}
 | |
| 		if ($this->scale != 1.) {
 | |
| 			$xmlElement->setAttribute('scale', $this->scale);
 | |
| 		}
 | |
| 		if ($this->hidden) {
 | |
| 			$xmlElement->setAttribute('hidden', $this->hidden);
 | |
| 		}
 | |
| 		if ($this->rotation) {
 | |
| 			$xmlElement->setAttribute('rot', $this->rotation);
 | |
| 		}
 | |
| 		if (!empty($this->classes)) {
 | |
| 			$classes = implode(' ', $this->classes);
 | |
| 			$xmlElement->setAttribute('class', $classes);
 | |
| 		}
 | |
| 		return $xmlElement;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get the ManiaScript class of the Control
 | |
| 	 *
 | |
| 	 * @return string
 | |
| 	 */
 | |
| 	public abstract function getManiaScriptClass();
 | |
| }
 |