<commit_before>/*
 * FXGL - JavaFX Game Library. The MIT License (MIT).
 * Copyright (c) AlmasB (<EMAIL>).
 * See LICENSE for details.
 */

package com.almasb.fxgl.app.scene

import com.almasb.fxgl.animation.AnimatedValue
import com.almasb.fxgl.core.math.FXGLMath.*
import com.almasb.fxgl.core.math.Vec2
import com.almasb.fxgl.core.util.EmptyRunnable
import com.almasb.fxgl.dsl.FXGL
import com.almasb.fxgl.entity.Entity
import javafx.beans.binding.Bindings
import javafx.beans.binding.NumberBinding
import javafx.beans.property.ReadOnlyDoubleProperty
import javafx.beans.property.ReadOnlyDoubleWrapper
import javafx.beans.property.SimpleDoubleProperty
import javafx.beans.property.SimpleIntegerProperty
import javafx.geometry.Point2D
import javafx.geometry.Rectangle2D
import javafx.scene.paint.Color
import javafx.scene.shape.Rectangle

/**
 * Scene viewport.
 *
 * @author <NAME> (AlmasB) (<EMAIL>)
 */
class Viewport

/**
 * Constructs a viewport with given width and height.
 *
 * @param initialWidth viewport width
 * @param initialHeight viewport height
 */
(initialWidth: Double, initialHeight: Double) {

    /*
    Moving origin X and Y moves the viewport.
    Moving the camera does nothing.
    Explanation given below for camera's purpose.
     */

    /**
     * Origin x.
     */
    private val xProp = ReadOnlyDoubleWrapper()

    /**
     * Origin y.
     */
    private val yProp = ReadOnlyDoubleWrapper()

    fun xProperty(): ReadOnlyDoubleProperty = xProp.readOnlyProperty
    fun yProperty(): ReadOnlyDoubleProperty = yProp.readOnlyProperty

    var x: Double
        get() = xProp.value
        set(value) { xProp.value = value }

    var y: Double
        get() = yProp.value
        set(value) { yProp.value = value }

    /**
     * @return viewport origin (x, y)
     */
    val origin: Point2D
        get() = Point2D(x, y)

    /**
     * @return current visible viewport area
     */
    val visibleArea: Rectangle2D
        get() = Rectangle2D(x, y, zoomedWidth.value, zoomedHeight.value)

    private val zoom = SimpleDoubleProperty(1.0)
    fun getZoom() = zoom.get()
    fun zoomProperty() = zoom
    fun setZoom(value: Double) = zoomProperty().set(value)

    private val angle = SimpleDoubleProperty()
    fun getAngle() = angle.value
    fun angleProperty() = angle
    fun setAngle(value: Double) = angleProperty().set(value)

    private var boundX: NumberBinding? = null
    private var boundY: NumberBinding? = null

    private val minX = SimpleIntegerProperty(Integer.MIN_VALUE)
    private val minY = SimpleIntegerProperty(Integer.MIN_VALUE)
    private val maxX = SimpleIntegerProperty(Integer.MAX_VALUE)
    private val maxY = SimpleIntegerProperty(Integer.MAX_VALUE)

    private val widthProperty = SimpleDoubleProperty(initialWidth)
    private val heightProperty = SimpleDoubleProperty(initialHeight)

    var width: Double
        get() = widthProperty.value
        set(value) { widthProperty.value = value }

    var height: Double
        get() = heightProperty.value
        set(value) { heightProperty.value = value }

    fun widthProperty() = widthProperty
    fun heightProperty() = heightProperty

    private val zoomedWidth = widthProperty.divide(zoom)
    private val zoomedHeight = heightProperty.divide(zoom)

    var isLazy = false

    /**
     * Currently only supported for non-lazy and entity bound viewports.
     */
    var isFloating = false

    /**
     * This is only used for visual effects and acts like a viewport overlay.
     * Its x and y follow the actual x and y of viewport.
     */
    internal val camera = Entity()

    /**
     * Binds the viewport to entity so that it follows the given entity.
     * distX and distY represent bound distance between entity and viewport origin.
     *
     * bindToEntity(player, getWidth() / 2, getHeight() / 2);
     *
     * the code above centers the camera on player.
     *
     * @param entity the entity to follow
     * @param distX distance in X between origin and entity
     * @param distY distance in Y between origin and entity
     */
    fun bindToEntity(entity: Entity, distX: Double, distY: Double) {
        val position = entity.transformComponent

        // origin X Y with no bounds
        val bx = position.xProperty().add(SimpleDoubleProperty(-distX).divide(zoom))
        val by = position.yProperty().add(SimpleDoubleProperty(-distY).divide(zoom))

        // origin X Y with bounds applied<commit_msg>feat: allow access to viewport camera entity via public API, closes #1168<commit_after>/*
 * FXGL - JavaFX Game Library. The MIT License (MIT).
 * Copyright (c) AlmasB (<EMAIL>).
 * See LICENSE for details.
 */

package com.almasb.fxgl.app.scene

import com.almasb.fxgl.animation.AnimatedValue
import com.almasb.fxgl.core.math.FXGLMath.*
import com.almasb.fxgl.core.math.Vec2
import com.almasb.fxgl.core.util.EmptyRunnable
import com.almasb.fxgl.dsl.FXGL
import com.almasb.fxgl.entity.Entity
import javafx.beans.binding.Bindings
import javafx.beans.binding.NumberBinding
import javafx.beans.property.ReadOnlyDoubleProperty
import javafx.beans.property.ReadOnlyDoubleWrapper
import javafx.beans.property.SimpleDoubleProperty
import javafx.beans.property.SimpleIntegerProperty
import javafx.geometry.Point2D
import javafx.geometry.Rectangle2D
import javafx.scene.paint.Color
import javafx.scene.shape.Rectangle

/**
 * Scene viewport.
 *
 * @author <NAME> (AlmasB) (<EMAIL>)
 */
class Viewport

/**
 * Constructs a viewport with given width and height.
 *
 * @param initialWidth viewport width
 * @param initialHeight viewport height
 */
(initialWidth: Double, initialHeight: Double) {

    /*
    Moving origin X and Y moves the viewport.
    Moving the camera does nothing.
    Explanation given below for camera's purpose.
     */

    /**
     * Origin x.
     */
    private val xProp = ReadOnlyDoubleWrapper()

    /**
     * Origin y.
     */
    private val yProp = ReadOnlyDoubleWrapper()

    fun xProperty(): ReadOnlyDoubleProperty = xProp.readOnlyProperty
    fun yProperty(): ReadOnlyDoubleProperty = yProp.readOnlyProperty

    var x: Double
        get() = xProp.value
        set(value) { xProp.value = value }

    var y: Double
        get() = yProp.value
        set(value) { yProp.value = value }

    /**
     * @return viewport origin (x, y)
     */
    val origin: Point2D
        get() = Point2D(x, y)

    /**
     * @return current visible viewport area
     */
    val visibleArea: Rectangle2D
        get() = Rectangle2D(x, y, zoomedWidth.value, zoomedHeight.value)

    private val zoom = SimpleDoubleProperty(1.0)
    fun getZoom() = zoom.get()
    fun zoomProperty() = zoom
    fun setZoom(value: Double) = zoomProperty().set(value)

    private val angle = SimpleDoubleProperty()
    fun getAngle() = angle.value
    fun angleProperty() = angle
    fun setAngle(value: Double) = angleProperty().set(value)

    private var boundX: NumberBinding? = null
    private var boundY: NumberBinding? = null

    private val minX = SimpleIntegerProperty(Integer.MIN_VALUE)
    private val minY = SimpleIntegerProperty(Integer.MIN_VALUE)
    private val maxX = SimpleIntegerProperty(Integer.MAX_VALUE)
    private val maxY = SimpleIntegerProperty(Integer.MAX_VALUE)

    private val widthProperty = SimpleDoubleProperty(initialWidth)
    private val heightProperty = SimpleDoubleProperty(initialHeight)

    var width: Double
        get() = widthProperty.value
        set(value) { widthProperty.value = value }

    var height: Double
        get() = heightProperty.value
        set(value) { heightProperty.value = value }

    fun widthProperty() = widthProperty
    fun heightProperty() = heightProperty

    private val zoomedWidth = widthProperty.divide(zoom)
    private val zoomedHeight = heightProperty.divide(zoom)

    var isLazy = false

    /**
     * Currently only supported for non-lazy and entity bound viewports.
     */
    var isFloating = false

    /**
     * This is only used for visual effects and acts like a viewport overlay.
     * Its x and y follow the actual x and y of viewport.
     */
    val camera = Entity()

    /**
     * Binds the viewport to entity so that it follows the given entity.
     * distX and distY represent bound distance between entity and viewport origin.
     *
     * bindToEntity(player, getWidth() / 2, getHeight() / 2);
     *
     * the code above centers the camera on player.
     *
     * @param entity the entity to follow
     * @param distX distance in X between origin and entity
     * @param distY distance in Y between origin and entity
     */
    fun bindToEntity(entity: Entity, distX: Double, distY: Double) {
        val position = entity.transformComponent

        // origin X Y with no bounds
        val bx = position.xProperty().add(SimpleDoubleProperty(-distX).divide(zoom))
        val by = position.yProperty().add(SimpleDoubleProperty(-distY).divide(zoom))

        // origin X Y with bounds applied
{'fraction_non_alphanumeric': 0.0927558879339212, 'fraction_numerical': 0.0029021096104475948, 'mean_word_length': 3.096936442615455, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4330333', 'n_tokens_mistral': 2619, 'n_tokens_neox': 2547, 'n_words': 773}