Skip to main content

Mad Mirrajabi

Persian Calendar View for Android - افزونه تقویم فارسی اندروید

In our current project, we needed a solar/Persian calendar for the app. I searched a lot for it in existing libraries and found Ebrahim Byagowi’s open-source Persian calendar.

There were also some Hijri calendars, but I didn’t want them. So, I decided to create my own calendar view plugin library and publish it. To achieve this, I read the source of Byagowi’s project and realized it could be easily converted into a separate library. I detached the calendar part from the application, made some changes and customizations, and now it’s ready for use in your Android projects.

JSON Data Mocking for OkHttp

In every client project that is connected to a remote REST server, the process of preparing and testing requests/responses may take a lot of time.

This simple library helps you mock your data for use with OkHttp + Retrofit in JSON format in just a few moves. It routes the requests to local JSON files and returns the data stored in them.

You can find the library and all the instructions in my GitHub repository: OkhttpJsonMock.

Carousel Slider in Unity 3D

Hi, this is my second post, and I hope it could be useful to you. Using this component is really easy, and I’ll show you how to do it step by step. First, I’m going to give you the C# code and then I will explain how it works.

## Carousel.cs

using UnityEngine;
using System.Collections;

public class Carousel : MonoBehaviour
{
    private static int _nearestIndex = 0;

    private static float _minMoveTreshold = 20f;
    private static float _newScroll = 0;
    private static AnimationCurve _miniTransitionCurve;
    public static bool Draw(Rect rect, ref float scroll, out int selectedIndex, float growMultiplyer, float slidesDistance, Texture2D[] slides, float size, float transitionTime, bool startTransition)
    {
        CheckMoves();
        selectedIndex = _nearestIndex;
        if (_miniTransitionCurve != null && _miniTransitionCurve.Evaluate(Time.time) < 0.90f)
        {
            if (Input.touchCount < 1)
            {
                scroll = Mathf.Lerp(scroll, _newScroll, _miniTransitionCurve.Evaluate(Time.time));
            }
        }
        if (startTransition)
        {
            _miniTransitionCurve = AnimationCurve.Linear(Time.time, 0, Time.time + transitionTime, 1);
            _miniTransitionCurve.preWrapMode = WrapMode.Clamp;
            _miniTransitionCurve.postWrapMode = WrapMode.Clamp;
        }
        GUI.BeginGroup(rect);
        {
            GUI.BeginGroup(new Rect(-scroll, rect.height / 2 - size * growMultiplyer, int.MaxValue, size * growMultiplyer * 2));
            {
                float minDistance = float.MaxValue;
                for (int i = 0; i < slides.Length; i++)
                {
                    float relativePosition = rect.width / 2 - size / 2 + i * (size + slidesDistance) + size / 2 - scroll;
                    float grow = 1 + Ratio(relativePosition, rect.width) * (growMultiplyer - 1);
                    GUI.DrawTexture(new Rect(rect.width / 2 - size * grow / 2 + i * (size + slidesDistance), size * growMultiplyer - size * grow / 2, size * grow, size * grow), slides[i]);
                    if (GUI.Button(new Rect(rect.width / 2 - size * grow / 2 + i * (size + slidesDistance), size * growMultiplyer - size * grow / 2, size * grow, size * grow), "", GUIStyle.none))
                    {
                        if (!_moved)
                        {
                            selectedIndex = i;
                            return true;
                        }
                    }

                    float distance = Mathf.Abs(relativePosition - rect.width / 2);
                    if (distance < minDistance)
                    {
                        minDistance = distance;
                        _nearestIndex = i;
                        _newScroll = scroll + (relativePosition - rect.width / 2);
                    }
                }
            }
            GUI.EndGroup();
        }
        GUI.EndGroup();
        return false;
    }

    private static Vector2 _startPosition;

    private static bool _moved = false;
    private static void CheckMoves()
    {
        if (Input.touchCount > 0)
        {
            if (Input.touches[0].phase == TouchPhase.Began)
            {
                _moved = false;
                _startPosition = Input.touches[0].position;
            }

            if (Input.touches[0].phase == TouchPhase.Moved || Input.touches[0].phase == TouchPhase.Ended || Input.touches[0].phase == TouchPhase.Canceled)
            {
                if (Vector2.Distance(Input.touches[0].position, _startPosition) > _minMoveTreshold)
                {
                    _moved = true;
                }
            }
        }
    }

    private static float Ratio(float pos, float length)
    {
        if (pos <= length / 2)
            return pos / (length / 2);
        else
            return (length - pos) / (length / 2);
    }
}

The CheckMoves function checks if we are scrolling or selecting a slide. If we move our hand and our touch movement was bigger than the threshold, we are scrolling. As you can see, the Draw function is static, so you don’t need to attach this component to an existing game object. This function does all the work for you, and all you have to do is place it in an OnGUI() method where you want to draw a carousel. If you didn’t catch what I just said, here is the code:

C++ Ludo Game

When I was a University student, we were tasked to implement a simple Ludo game in C++ language. It was a fun project and I learned a few things from it. The code is not that great but it works! And at the time, I was proud of it. So why not share it!

You can find the code on this GitHub repository.

Note: I used the rlutil library to change foreground colors. To compile it, you need to download it and add it to your project headers. “rlutil” project’s blog: http://tapiov.net/rlutil