public KeywordView(BohemianArtifact bbshelf, Vector3 position, Vector3 size) { bookshelf = bbshelf; bookshelf.Library.SelectedArtifactChanged += new ArtifactLibrary.SelectedArtifactHandler(library_SelectedArtifactChanged); bookshelf.Library.LanguageChanged += new ArtifactLibrary.ChangeLanguageHandler(Library_LanguageChanged); this.position = position; this.size = size; draggedText = null; titleText = new SelectableText(XNA.Font, "Keywords", new Vector3(0.4f, 0, 0), bookshelf.GlobalTextColor, Color.White); titleText.InverseScale(0.8f, size.X, size.Y); WavyText.createAllLetters(bbshelf.Library.Artifacts); centerCircleRadius = 0.1f; relatedCircleRadius = centerCircleRadius * 0.5f; artifactCircles = new List<KeywordContainer>(); for (int i = 0; i < MAX_CIRCLES; i++) { KeywordContainer newContainer = new KeywordContainer(); newContainer.Circle = new SelectableEllipse(new Vector2(center.X, center.Y), relatedCircleRadius, centerCircleRadius * 0.05f, Color.White, new Color(1, 1, 1, 0), Color.Black, null); newContainer.Circle.TouchActivated += new TouchActivatedEventHandler(Circle_TouchActivated); newContainer.Circle.TouchReleased += new TouchReleaseEventHandler(Circle_TouchReleased); bookshelf.SelectableObjects.AddObject(newContainer.Circle); artifactCircles.Add(newContainer); } artifactCircles[CENTER_CIRCLE_ID].Circle.Radius = centerCircleRadius; PositionRelatedCircles(); }
private void Circle_TouchReleased(object sender, TouchArgs e) { if (bookshelf.TouchPoints.ContainsKey(e.TouchId) == false) { bool fastRelease = true; if (draggedText != null) { fastRelease = draggedText.FastRelease; draggedText.Mode = WavyText.DisplayMode.BounceBack; // if we fast released, this object is getting wiped out anyway, otherwise bounce back } draggedText = null; if (fastRelease) { lock (artifactCircles) { KeywordContainer selectedCircle = FindMaterialContainerFromCircle((SelectableEllipse)sender); // only do stuff if we tap on a circle that's not the center circle if (selectedCircle != artifactCircles[CENTER_CIRCLE_ID]) { bookshelf.Library.SelectedArtifact = selectedCircle.Artifact; } } } } }
private void library_SelectedArtifactChanged(Artifact selectedArtifact) { // change the central circle artifact and texture artifactCircles[CENTER_CIRCLE_ID].Artifact = selectedArtifact; artifactCircles[CENTER_CIRCLE_ID].Circle.Texture = selectedArtifact.Texture; Console.WriteLine("*** New selected artifact " + selectedArtifact.ArticleName + ", colors (" + selectedArtifact.Color.ToString() + ") and it's stems:"); Console.Write("\t"); foreach (StemPair stempair in selectedArtifact.Stems) { Console.Write(stempair.Stem + ", "); } Console.Write("\n"); List<Artifact> candidateList = new List<Artifact>(); // use the stem graph to find related artifacts and put all found into a candidate list foreach (StemPair sp in selectedArtifact.Stems) { List<StemPair> relatedStemPairs = bookshelf.Library.StemGraph[sp.Stem]; foreach (StemPair relatedSP in relatedStemPairs) { if (candidateList.Contains(relatedSP.ArtifactRef) == false && relatedSP.ArtifactRef != selectedArtifact) { candidateList.Add(relatedSP.ArtifactRef); } } } List<KeyValuePair<Artifact, float>> weightedCandidateList = new List<KeyValuePair<Artifact, float>>(); foreach (Artifact a in candidateList) { float sameStemCount = 0; int numMatchedStems = 0; foreach (StemPair sp in a.Stems) { if (selectedArtifact.Stems.Contains(sp) == true) { sameStemCount += bookshelf.Library.StemGraph[sp.Stem].Count; numMatchedStems++; //sameStemCount++; } } weightedCandidateList.Add(new KeyValuePair<Artifact, float>(a, sameStemCount / (numMatchedStems * numMatchedStems))); } // sort based on relevence weightedCandidateList.Sort(CompareArtifactSimilarity); weightedCandidateList.Reverse(); /* debugging foreach (KeyValuePair<Artifact, float> kvp in weightedCandidateList) { Artifact a = kvp.Key; Console.WriteLine(a.ArticleName); Console.Write("\t"); foreach (StemPair stempair in a.Stems) { if (selectedArtifact.Stems.Contains(stempair)) { Console.Write(stempair.Stem + ", "); } } Console.Write("\n\n"); } //*/ int i; lock (artifactCircles) { for (i = 0; i < MAX_CIRCLES - 1 && i < weightedCandidateList.Count; i++) { artifactCircles[i].Artifact = weightedCandidateList[i].Key; artifactCircles[i].Circle.Texture = artifactCircles[i].Artifact.Texture; } } numArtifactCircles = i; // create the wavy text wavyText.Clear(); WavyText wave; for (i = 0; i < numArtifactCircles; i++) { float angleDeg = (float)(i * 360f / numArtifactCircles); angleDeg += 22.5f; // add a tilt so it's more separated into quadrants float angleRad = (float)(angleDeg * Math.PI / 180); Vector2 direction = WavyText.rotateVector(Vector2.UnitX, angleRad); direction.Normalize(); Vector2 startPos = new Vector2(artifactCircles[CENTER_CIRCLE_ID].Circle.Position.X, artifactCircles[CENTER_CIRCLE_ID].Circle.Position.Y); startPos += (artifactCircles[CENTER_CIRCLE_ID].Circle.Radius * 1.3f) * direction; float waveHeight = 0.03f; string text = artifactCircles[i].Artifact.ArticleName; if (maxTextLength > 0 && text.Length > maxTextLength) text = text.Substring(0, maxTextLength - 3) + "..."; wave = new WavyText(startPos, direction, waveHeight, text, artifactCircles[i].Circle); int textLength = text.Length; // make some lengths of text appear better on screen by shrinking the font size (DrawScale) and squishing/expanding the space between letters (StretchFactor) // DrawScale is absolute value so have to multiply by a percentage, StretchFactor is relative so just assign percentage directly if (textLength <= 5) { wave.DrawScale *= 1.45f; wave.StretchFactor = 1.25f; } else if (textLength <= 11) { wave.DrawScale *= 1.25f; wave.StretchFactor = 1.15f; } else if (textLength > 20) { wave.DrawScale *= 0.85f; wave.StretchFactor = 0.9f; } //wave.WaveSpeed = 1f; // if between 90 degrees and 270 degrees, flip the text if (angleDeg > 90 && angleDeg <= 270) wave.InsideOutText = true; wave.resetMovement(); // only need to do if you manually change movement parameters after creating object wave.Mode = WavyText.DisplayMode.GrowOutward; // starts by growing outward, will change itself when it hits max wavyText.Add(wave); } // add half very related /* for (i = 0; i < MAX_CIRCLES / 2 && i < weightedCandidateList.Count; i++) { artifactCircles[i].Artifact = weightedCandidateList[i].Key; artifactCircles[i].Circle.Texture = artifactCircles[i].Artifact.Texture; } // and half Random random = new Random(); for (; i < MAX_CIRCLES - 1; i++) { Artifact randomArtifact; // make sure the random artifact hasn't already been used do { randomArtifact = bookshelf.Library.Artifacts[random.Next(bookshelf.Library.Artifacts.Count)]; } while (candidateList.Contains(randomArtifact) == true); artifactCircles[i].Artifact = randomArtifact; artifactCircles[i].Circle.Texture = artifactCircles[i].Artifact.Texture; } numArtifactCircles = MAX_CIRCLES - 1; // add 1/4 least related // add 1/4 random //*/ PositionRelatedCircles(); }
void Circle_TouchActivated(object sender, TouchArgs e) { WavyText wave = FindWavyTextFromCircle(sender as SelectableEllipse); if (wave != null && wave != draggedText && bookshelf.TouchPoints.ContainsKey(e.TouchId)) { draggedText = wave; Touch touch = bookshelf.TouchPoints[e.TouchId]; wave.DragPosition = convertTouchAbsoluteToRelative(new Vector2(touch.X, touch.Y)); wave.Mode = WavyText.DisplayMode.StraightLine; } }