{"action":"created","issue":{"url":"https://api.github.com/repos/ROBLOX/Core-Scripts/issues/158","labels_url":"https://api.github.com/repos/ROBLOX/Core-Scripts/issues/158/labels{/name}","comments_url":"https://api.github.com/repos/ROBLOX/Core-Scripts/issues/158/comments","events_url":"https://api.github.com/repos/ROBLOX/Core-Scripts/issues/158/events","html_url":"https://github.com/ROBLOX/Core-Scripts/issues/158","id":74063907,"number":158,"title":"OOP design on the RootCamera breaks several standards.","user":{"login":"Quenty","id":1774409,"avatar_url":"https://avatars.githubusercontent.com/u/1774409?v=3","gravatar_id":"","url":"https://api.github.com/users/Quenty","html_url":"https://github.com/Quenty","followers_url":"https://api.github.com/users/Quenty/followers","following_url":"https://api.github.com/users/Quenty/following{/other_user}","gists_url":"https://api.github.com/users/Quenty/gists{/gist_id}","starred_url":"https://api.github.com/users/Quenty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Quenty/subscriptions","organizations_url":"https://api.github.com/users/Quenty/orgs","repos_url":"https://api.github.com/users/Quenty/repos","events_url":"https://api.github.com/users/Quenty/events{/privacy}","received_events_url":"https://api.github.com/users/Quenty/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-05-07T17:27:46Z","updated_at":"2015-05-07T19:41:01Z","closed_at":null,"body":"The root camera is trying to do several functions at once, when in reality behavior can be broken into multiple reusable components. This makes modifying the RootCamera (and subsequent versions of cameras) very difficult.\r\n\r\n## Behaviors the RootCamera handles (which should be separated by Encapsulation) \r\n* `Event` disconnect and connection (Should be handled by a `Maid` class).\r\n* `Input` across the following device types\r\n    * Gamepad\r\n    * Touch\r\n    * Mouse\r\n    * Mouse with MouseLock\r\n    * KeyBoard\r\n* Camera `Offset` based upon humanoid and character state\r\n\r\n## Breaking up this behavior\r\nEach of these behaviors are interesting, but should not be linked as a core component of the RootCamera.\r\n\r\n### Base behavior\r\nRather, the RootCamera should only have the following APIs\r\n\r\n```lua\r\nfunction RootCamera:GetCameraLook()\r\nfunction RootCamera:GetCameraZoom()\r\nfunction RootCamera:GetCameraActualZoom()\r\nfunction RootCamera:ViewSizeX() -- Note this method and the one below should start using the camera.ViewportSize\r\nfunction RootCamera:ViewSizeY()\r\nfunction RootCamera.new()\r\nfunction RootCamera:RotateCamera(startLook, xyRotateVector)\r\nfunction RootCamera:ScreenTranslationToAngle(translationVector)\r\n```\r\n\r\n### New API\r\n```lua\r\nfunction RootCamera:SetCamera()\r\nfunction RootCamera:AddChild(ChildModifier)\r\nfunction RootCamera:RemoveChild(ChildModifier)\r\nfunction RootCamera:Destroy() -- Removes events, destroys children\r\n```\r\n### Children/API suggestion\r\nCurrently, the RootCamera has one behavior, but we know this is going to change as ROBLOX goes on.\r\n\r\nRootCameras should be extended via children, or some sort of plug-and-chug input or behavior handling items. For example, the current player's character is tracked, and behavior happens when it joins. A class  `HumanoidTrackingExtension` would handle this behavior nicely. The RootCamera could then loop through these behavior classes and update them, et cetera. The following API could occur\r\n\r\n```lua\r\nfunction HumanoidTrackingExtension:IsInFirstPerson()\r\nfunction HumanoidTrackingExtension:CalculateOffset()\r\nfunction HumanoidTrackingExtension:HandleTransparency()\r\n...\r\nfunction HumanoidTrackingExtension:Destroy()\r\n```\r\n\r\nThis sort of behavior should also be done with the input, so input can easily be swapped in mode, and input mode is easy to track and reusable in other camera extensions, instead of creating an inextensible RootCamera that is not extendable. Note that I've suggested that `MouseLock` and `Mouse` and `Keyboard` all be handled differently because these are inherently different input types that change `input behavior --> camera behavior.`\r\n\r\nAnother example child would be a `InputSystemExtension` which selects which input mode to use. At this point, the `InputSystemExtension` would be able to switch the strategy of input based upon the existing camera mode. These children would interact directly with the `RootCamera` API calling methods, with the `RootCamera` knowing of them. This means the RootCamera has ** few to no dependencies**\r\n\r\nThe following variables should also be camera variables\r\n```lua\r\nworkspace.CurrentCamera --> self.Camera\r\n```\r\n\r\nAllowing the camera and other small variables like this to be set means that \r\n\r\n\r\n## Effects of such a change\r\nAlthough this is a very large refactoring, this also does a lot of things for you\r\n* Lets the script be shorter\r\n    * By separating out the code into many modules and child-behaviors, the code is a lot more concise and clear\r\n* Make it more understandable\r\n    * It's a lot easier to read 100 lines of code than 1000 lines of code\r\n* Make it more reusable\r\n    * Components such as input can easily be reused or even extended to allow players to modify behavior. Making something such as a smoothly animated camera is much easier when you can modify the scrolling and movement APIs and not worry about input.\r\n    * If I wanted to create a smooth gliding camera right now, it would require a modification of the RootCamera, not an extension of it. Furthermore, other behaviors such as `Tracking` or `Following` cameras are *not* easily implemented with my smoothly gliding camera. \r\n* Reduce dependencies\r\n    * The RootCamera does not depend upon child components. This is good. \r\n\r\n"},"comment":{"url":"https://api.github.com/repos/ROBLOX/Core-Scripts/issues/comments/99992797","html_url":"https://github.com/ROBLOX/Core-Scripts/issues/158#issuecomment-99992797","issue_url":"https://api.github.com/repos/ROBLOX/Core-Scripts/issues/158","id":99992797,"user":{"login":"einsteinK","id":6892280,"avatar_url":"https://avatars.githubusercontent.com/u/6892280?v=3","gravatar_id":"","url":"https://api.github.com/users/einsteinK","html_url":"https://github.com/einsteinK","followers_url":"https://api.github.com/users/einsteinK/followers","following_url":"https://api.github.com/users/einsteinK/following{/other_user}","gists_url":"https://api.github.com/users/einsteinK/gists{/gist_id}","starred_url":"https://api.github.com/users/einsteinK/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/einsteinK/subscriptions","organizations_url":"https://api.github.com/users/einsteinK/orgs","repos_url":"https://api.github.com/users/einsteinK/repos","events_url":"https://api.github.com/users/einsteinK/events{/privacy}","received_events_url":"https://api.github.com/users/einsteinK/received_events","type":"User","site_admin":false},"created_at":"2015-05-07T19:41:01Z","updated_at":"2015-05-07T19:41:01Z","body":"Blending would be a completely different thing, probably specific for every game.\r\nIt would be better if the game creator just creates a new camera for the blending.\r\n(or utilises one of the two cameras he's blending)"}}