- Follow the instructions here: How To Run Your Entire Development Environment in Docker Containers on macOS
However you'll need to install MariaDB instead of MySQL 8.0 as at the time of writing MySQL doesn't run on the Mac M1 processor. (Anyway MariaDB is better). - To install MariaDB follow the instructions here: Apple M1 Chip to work with MariaDB docker image
The command to use to launch the docker MariaDB server container is:
docker run --restart always --name mysql-localhost --net dev-network -v /Users/[your_username]/Develop/mysql_data/8.0:/var/lib/mysql -v /Users/[your_username]/Develop/docker_configs/mysql:/etc/mysql/conf.d -p 3306:3306 -d -e MYSQL_ROOT_PASSWORD=[Root DB Password] mariadb
This is the command from the instructions from step 1 but specifying that we're using MariaDB instead of mysql:8.0 - At this point PHP should be working and you should be able to access the database using your database management application eg: Sequel Ace. So check that you can do this. However you'll probably find that PHP is not able to connect to the MariaDB database. So there are 2 more things that you'll need to do.
- Find the IP address of the mariaDB server:
docker inspect mysql-localhost | grep IPAddress
This is the address that you'll need to use for the server name in the mysqli_connect statement. - Create a DB user for php to use as I believe that the recent versions of MariaDB do not allow PHP to connect using the root user. See: How do I create a user with the same privileges as root in MySQL/MariaDB?
Dev Diary for an Online Game
This has been a long project to develop a data driven game. Initially I wanted to the able to enter the game data using a website developed using CakePHP. The game itself would be developed in Unity 3D using the exported data. However this has now changed to the entire game being developed using CakePHP.. The posts that I've made are for things that I found difficult to solve and I've put them here for my own future reference. They are also for anyone else who might find them useful.
Saturday, January 15, 2022
Setting up Docker on Mac M1 to run Apache/PHP/Maria DB
Saturday, July 3, 2021
Getting associated data in CakePHP 3 loaded using 'contain'
So you've loaded associated data using 'contain' eg:
$object_attributes = $object_attributes_table
->find("all", ["contain" => ["attributes"]])
->where(["object_id = " => $object_id]);
So how do actually access the data?
Well it's stored as an array. So in the above example to get the attribute name:
$name = $object_attribute->Attributes['name'];
Friday, April 16, 2021
Helper Directory in CakePHP 3
The helper directory is located in the View directory:
ie: src\View\Helper
(I posted this as I rarely need to find it and often forget where it lives!)
Tuesday, September 17, 2019
How to Bake in CakePHP 3
- In the command console go to your project root directory. In my case this is:
C:\wamp64\www\colab - Enter the command like:
- cake bake all TableNameLikeThis
- cake bake controller TableNameLikeThis
- cake bake model TableNameLikeThis
- cake bake template TableNameLikeThis
Wednesday, February 6, 2019
How to add a plugin to CakePHP 3
I had a bit of trouble getting the cakephp-csvview plugin to install so I used a combination of steps from the following to web pages.
- https://github.com/FriendsOfCake/cakephp-csvview
- https://andy-carter.com/blog/exporting-data-to-a-downloadable-csv-file-with-cakephp-3-and-csvview
The first link is the one that finally got things working.
1. From the console on your web server navigate to the directory where your cake project lives. Be sure to open the console as Administrator.
2. Install the plugin with the command:
composer require friendsofcake/cakephp-csvview3. Load the plugin with the command:
bin\cake plugin load CsvView4. In the Cake project edit the file config/bootstrap.php and add the following line in the plugins section near the end of the file:
Plugin::load("CsvView");The plugin should now be installed and ready to use.
Monday, August 20, 2018
How to stop an Input field being submitted when it loses focus
In Unity the default behaviour of an input field when it loses focus is to fire the OnEndEdit event.
Solution:
If you don't want this to happen - at the start of the method that is called by OnEndEdit check to see if the enter key is being pressed and return without doing anything is it isn't.
Eg:
if (!Input.GetKey(KeyCode.Return)) return;
Saturday, June 16, 2018
Contents of Scroll View UI won't display
Symptoms:
My exact symptoms were that the Scroll View contents would be displayed if I played from the scene with the Scroll View, but if I started in another scene and went to that scene the Scroll View would be empty.Solution:
Set the Under the Scroll Rect component of the Scroll View set the visibility to "Permanent".Friday, June 15, 2018
How to create Linked Text in Unity with Textmesh Pro
Here is the link: https://assetstore.unity.com/packages/essentials/beta-projects/textmesh-pro-84126
Unfortunately the documentation is a bit sketchy, some out-of-date, and difficult to find for the newer version.
So to get it to work...
- Update to Unity 5.6 or later.
- Download and install the package.
- From GameObject > UI add a TextMeshPro-Text to the canvas.
- Make sure the scene has an Event System object.
- Add a script to TextMesh Pro Text object based on TMP_Text_Selector_B.cs
- Links in the text need to be tagged like: Some text <link="link_name">this text has a link</link> and this is boring text.
- In TMP_TextInfoDebugTool.cs comment out the contents of method OnDrawGizmos() as this causes errors in the editor.
- There is a sample scene called: 12 - Link Example with links that work.
- If using the color tag (which works a little different to to the Text color tag) make sure that the base text color is white. Color tags are in the form: <#40A0FF>This is a color tag - just specify the color in the tag.</color>
- While I could get the mouseovers to work using the new TMP Text Event Handler script I couldn't get it to register mouse clicks so I used the old TMP_Text_Selector_B version instead.
using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; using System.Collections; using System.Collections.Generic; using TMPro; // Disabled warning due to SetVertices being deprecated // until new release with SetMesh() is available. #pragma warning disable 0618 public class TextOutputTextSelector : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler, IPointerUpHandler { public RectTransform TextPopup_Prefab_01; private RectTransform m_TextPopup_RectTransform; private TextMeshProUGUI m_TextPopup_TMPComponent; private const string k_LinkText = "You have selected link <#ffff00>"; private const string k_WordText = "Word Index: <#ffff00>"; private TextMeshProUGUI m_TextMeshPro; private Canvas m_Canvas; private Camera m_Camera; // Flags private bool isHoveringObject; private int m_selectedLink = -1; private int m_selectedWord = -1; private int m_lastIndex = -1; private Matrix4x4 m_matrix; private TMP_MeshInfo[] m_cachedMeshInfoVertexData; // ---------------------------------------------------------------------------- public void Awake() { m_TextMeshPro = gameObject.GetComponent<TextMeshProUGUI>(); m_Canvas = gameObject.GetComponentInParent<Canvas>(); // Get a reference to the camera if Canvas Render Mode is not ScreenSpace Overlay. if (m_Canvas.renderMode == RenderMode.ScreenSpaceOverlay) m_Camera = null; else m_Camera = m_Canvas.worldCamera; } // ---------------------------------------------------------------------------- public void OnEnable() { // Subscribe to event fired when text object has been regenerated. TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED); } // ---------------------------------------------------------------------------- public void OnDisable() { // UnSubscribe to event fired when text object has been regenerated. TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED); } // ---------------------------------------------------------------------------- public void ON_TEXT_CHANGED(Object obj) { if (obj == m_TextMeshPro) { // Update cached vertex data. m_cachedMeshInfoVertexData = m_TextMeshPro.textInfo.CopyMeshInfoVertexData(); } } // ---------------------------------------------------------------------------- public void LateUpdate() { if (isHoveringObject) { // LINKS // Check if mouse intersects with any links. int linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextMeshPro, Input.mousePosition, m_Camera); // Clear previous link selection if one existed. if ((linkIndex == -1 && m_selectedLink != -1) || linkIndex != m_selectedLink) { m_selectedLink = -1; } // Handle new Link selection. if (linkIndex != -1 && linkIndex != m_selectedLink) { m_selectedLink = linkIndex; TMP_LinkInfo linkInfo = m_TextMeshPro.textInfo.linkInfo[linkIndex]; Debug.Log("(Late Update) Selected Link Index: " + m_selectedLink); Debug.Log("*** (Late Update) Link ID: \"" + linkInfo.GetLinkID() + "\" Link Text: \"" + linkInfo.GetLinkText() + "\""); Vector3 worldPointInRectangle = Vector3.zero; RectTransformUtility.ScreenPointToWorldPointInRectangle(m_TextMeshPro.rectTransform, Input.mousePosition, m_Camera, out worldPointInRectangle); // change color of link (Doesn't quite work but leaving here for future use) // Iterate through each of the characters of the word. /* Debug.Log("First Character Index: " + linkInfo.linkTextfirstCharacterIndex); Debug.Log("Link Text Length: " + linkInfo.linkTextLength); for (int i = 0; i < linkInfo.linkTextLength; i++) { int characterIndex = linkInfo.linkTextfirstCharacterIndex + i; // Get the index of the material / sub text object used by this character. int meshIndex = m_TextMeshPro.textInfo.characterInfo[characterIndex].materialReferenceIndex; int vertexIndex = m_TextMeshPro.textInfo.characterInfo[characterIndex].vertexIndex; // Get a reference to the vertex color Color32[] vertexColors = m_TextMeshPro.textInfo.meshInfo[meshIndex].colors32; Color32 c = vertexColors[vertexIndex + 0].Tint(0.75f); vertexColors[vertexIndex + 0] = c; vertexColors[vertexIndex + 1] = c; vertexColors[vertexIndex + 2] = c; vertexColors[vertexIndex + 3] = c; } // Update Geometry m_TextMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All); */ } } else { // Restore any character that may have been modified if (m_lastIndex != -1) { RestoreCachedVertexAttributes(m_lastIndex); m_lastIndex = -1; } } } // ---------------------------------------------------------------------------- public void OnPointerEnter(PointerEventData eventData) { isHoveringObject = true; } // ---------------------------------------------------------------------------- public void OnPointerExit(PointerEventData eventData) { //Debug.Log("OnPointerExit()"); isHoveringObject = false; } // ---------------------------------------------------------------------------- public void OnPointerClick(PointerEventData eventData) { // Check if Mouse intersects any words and if so assign a random color to that word. int linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextMeshPro, Input.mousePosition, m_Camera); if (linkIndex != -1) { //TMP_LinkInfo linkInfo = m_TextMeshPro.textInfo.linkInfo[linkIndex]; Debug.Log("(On Pointer Click) - Selected Link ID: " + m_selectedLink); Debug.Log("Mouse position - X: " + Input.mousePosition.x + ", Y: " + Input.mousePosition.y); } } // ---------------------------------------------------------------------------- public void OnPointerUp(PointerEventData eventData) { //Debug.Log("OnPointerUp()"); } // ---------------------------------------------------------------------------- void RestoreCachedVertexAttributes(int index) { if (index == -1 || index > m_TextMeshPro.textInfo.characterCount - 1) return; // Get the index of the material / sub text object used by this character. int materialIndex = m_TextMeshPro.textInfo.characterInfo[index].materialReferenceIndex; // Get the index of the first vertex of the selected character. int vertexIndex = m_TextMeshPro.textInfo.characterInfo[index].vertexIndex; // Restore Vertices // Get a reference to the cached / original vertices. Vector3[] src_vertices = m_cachedMeshInfoVertexData[materialIndex].vertices; // Get a reference to the vertices that we need to replace. Vector3[] dst_vertices = m_TextMeshPro.textInfo.meshInfo[materialIndex].vertices; // Restore / Copy vertices from source to destination dst_vertices[vertexIndex + 0] = src_vertices[vertexIndex + 0]; dst_vertices[vertexIndex + 1] = src_vertices[vertexIndex + 1]; dst_vertices[vertexIndex + 2] = src_vertices[vertexIndex + 2]; dst_vertices[vertexIndex + 3] = src_vertices[vertexIndex + 3]; // Restore Vertex Colors // Get a reference to the vertex colors we need to replace. Color32[] dst_colors = m_TextMeshPro.textInfo.meshInfo[materialIndex].colors32; // Get a reference to the cached / original vertex colors. Color32[] src_colors = m_cachedMeshInfoVertexData[materialIndex].colors32; // Copy the vertex colors from source to destination. dst_colors[vertexIndex + 0] = src_colors[vertexIndex + 0]; dst_colors[vertexIndex + 1] = src_colors[vertexIndex + 1]; dst_colors[vertexIndex + 2] = src_colors[vertexIndex + 2]; dst_colors[vertexIndex + 3] = src_colors[vertexIndex + 3]; // Restore UV0S // UVS0 Vector2[] src_uv0s = m_cachedMeshInfoVertexData[materialIndex].uvs0; Vector2[] dst_uv0s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs0; dst_uv0s[vertexIndex + 0] = src_uv0s[vertexIndex + 0]; dst_uv0s[vertexIndex + 1] = src_uv0s[vertexIndex + 1]; dst_uv0s[vertexIndex + 2] = src_uv0s[vertexIndex + 2]; dst_uv0s[vertexIndex + 3] = src_uv0s[vertexIndex + 3]; // UVS2 Vector2[] src_uv2s = m_cachedMeshInfoVertexData[materialIndex].uvs2; Vector2[] dst_uv2s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs2; dst_uv2s[vertexIndex + 0] = src_uv2s[vertexIndex + 0]; dst_uv2s[vertexIndex + 1] = src_uv2s[vertexIndex + 1]; dst_uv2s[vertexIndex + 2] = src_uv2s[vertexIndex + 2]; dst_uv2s[vertexIndex + 3] = src_uv2s[vertexIndex + 3]; // Restore last vertex attribute as we swapped it as well int lastIndex = (src_vertices.Length / 4 - 1) * 4; // Vertices dst_vertices[lastIndex + 0] = src_vertices[lastIndex + 0]; dst_vertices[lastIndex + 1] = src_vertices[lastIndex + 1]; dst_vertices[lastIndex + 2] = src_vertices[lastIndex + 2]; dst_vertices[lastIndex + 3] = src_vertices[lastIndex + 3]; // Vertex Colors src_colors = m_cachedMeshInfoVertexData[materialIndex].colors32; dst_colors = m_TextMeshPro.textInfo.meshInfo[materialIndex].colors32; dst_colors[lastIndex + 0] = src_colors[lastIndex + 0]; dst_colors[lastIndex + 1] = src_colors[lastIndex + 1]; dst_colors[lastIndex + 2] = src_colors[lastIndex + 2]; dst_colors[lastIndex + 3] = src_colors[lastIndex + 3]; // UVS0 src_uv0s = m_cachedMeshInfoVertexData[materialIndex].uvs0; dst_uv0s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs0; dst_uv0s[lastIndex + 0] = src_uv0s[lastIndex + 0]; dst_uv0s[lastIndex + 1] = src_uv0s[lastIndex + 1]; dst_uv0s[lastIndex + 2] = src_uv0s[lastIndex + 2]; dst_uv0s[lastIndex + 3] = src_uv0s[lastIndex + 3]; // UVS2 src_uv2s = m_cachedMeshInfoVertexData[materialIndex].uvs2; dst_uv2s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs2; dst_uv2s[lastIndex + 0] = src_uv2s[lastIndex + 0]; dst_uv2s[lastIndex + 1] = src_uv2s[lastIndex + 1]; dst_uv2s[lastIndex + 2] = src_uv2s[lastIndex + 2]; dst_uv2s[lastIndex + 3] = src_uv2s[lastIndex + 3]; // Need to update the appropriate m_TextMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All); } }
Tuesday, May 15, 2018
CommandInvokationFailure: While Compiling for Android
CommandInvokationFailure: Failed to build apk. See the Console for details.
C:\Program Files\Java\jdk-10.0.1\bin\java.exe -Xmx2048M -Dcom.android.sdkmanager.toolsdir="C:/Program Files (x86)/Android/android-sdk\tools" -Dfile.encoding=UTF8 -jar "C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer/Tools\sdktools.jar"
Solution:
Use Java JDK 8.It seems that Unity 5.3.8 doesn't like JDK 9 or higher.
Downloaded jdk-8u171-windows-x64 from Oracle and install it.
Then in Unity under Edit > Preferences > External Tools point Unity to JDK 8.
Android SDK is outdated
After following the instructions I found here: Building your Unity game to an Android device for testing
I installed Java JDK and Android Studio and pointed Unity to the tools directory that contains the Android SDK.
The Problem
However when I compiled for Android I kept getting the following messages:
"Android SDK is outdated" and "sdk tools version 23 < 24".
Unity then asked me if I wanted to update and after replying "yes" it went off, looped around a bit and then came back with same messages.
The Solution
All that was needed was for Unity to be running in Administrator mode.
Once in Administrator mode Unity managed to download what it needed and continue compiling.
So I decided that I want to make a game in Unity 3D
A Brief Prologue
I've been thinking about this game for about a year now and I've dabbled with Unity 3D on and off over a couple of years. A few years ago I started a Udemy course in Unity which I found pretty good. I only completed the 2D section which I think is all I need to make this game. Link: Complete C# Unity Developer 2D - Learn to Code Making Games
I have a background in programming and graphic design and I've worked a few years in the gaming industry so I'm hoping I know what I'm getting myself and I'm not going to bite off more than I can chew, which is often the case with wanna be game developers.
Anyway I'm not going to go into any detail about what this game is about as that is not the purpose of the blog.
The Purpose of this Blog
The purpose of this blog or rather Dev Diary is to catalogue the problems and solutions I encounter while making this game. This is for both myself as much as for anyone reading this - as I know from experience that I will solve many issues and forget how I solved them when I come across them again.
Also
This is the first time I've used Blogger so things may look a little rough for awhile.